Добавлен регистратор УМП для графиков SetGUI в 166
Перенесены онлайн-запись, архив отключения и доступ по RS/CAN из 167. Учтены готовность READY, фиксированный разгон ЦАП и каналы АЦП проекта 166. Добавлены документация и тесты, обновлены файлы прошивки.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#include "../../Source/Internal/log_to_mem.c"
|
||||
#include "../../Source/Internal/Include/ump_can_protocol.h"
|
||||
struct mock_gpio GpioDataRegs;
|
||||
int READY = 0, Desk = 6, Mode = 5;
|
||||
int modbus[128];
|
||||
int CanTimeOutErrorTR;
|
||||
unsigned long IMPowse, WAKEpowse;
|
||||
unsigned int adc_table_lem[4];
|
||||
#define CHECK(x) if (!(x)) return __LINE__
|
||||
|
||||
/* Возвращаем номер строки при ошибке, ноль при успехе; CRT не требуется. */
|
||||
__declspec(dllexport) int run_tests(void)
|
||||
{
|
||||
unsigned int i, generation, archived, reply[UMP_CAN_MAX_WORDS], error, length;
|
||||
unsigned long sequence;
|
||||
READY = 100;
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE, 1));
|
||||
READY = 0;
|
||||
adc_table_lem[0] = 2048; adc_table_lem[3] = 4095;
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE+1, 0));
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE+1, 1001));
|
||||
CHECK(ump_log_write(UMP_LOG_BASE+1, 1));
|
||||
modbus[127] = 0x80;
|
||||
/* Unrelated registers must not determine the fixed 166 ramp. */
|
||||
modbus[0x50] = 99; modbus[0x51] = 123;
|
||||
modbus[0x64] = 88; modbus[0x65] = 111;
|
||||
modbus[0x7B] = 1234; modbus[0x1C] = 160;
|
||||
CHECK(ump_log_write(UMP_LOG_BASE, 1));
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE, 1));
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE+1, 20));
|
||||
for (i=0; i<900; i++) ump_log_tick();
|
||||
CHECK(ump_count == UMP_LOG_CAPACITY);
|
||||
CHECK(ump_word(0, 0, 0) == 101);
|
||||
CHECK(ump_word(0, UMP_LOG_CAPACITY-1, 0) == 900);
|
||||
CHECK(ump_word(0, 0, 8) == 1234);
|
||||
CHECK(ump_word(0, 0, 24) == 6);
|
||||
CHECK(ump_word(0, 0, 25) == 16);
|
||||
CHECK(ump_word(0, 0, 36) == 2048);
|
||||
CHECK(ump_word(0, 0, 39) == 4095);
|
||||
/* Короткая CAN-команда должна остаться отдельным событием. */
|
||||
modbus[127] = 0x40;
|
||||
ump_log_can(0x807F, 0x40, 0, 0);
|
||||
CHECK(ump_post == 1000);
|
||||
CHECK(ump_word(0, ump_count-1, 2) == 0x102);
|
||||
CHECK(ump_word(0, ump_count-1, 18) == 0x807F);
|
||||
for (i=0; i<999; i++) ump_log_tick();
|
||||
CHECK(ump_generation == 0);
|
||||
ump_log_tick();
|
||||
CHECK(ump_generation == 1);
|
||||
CHECK(ump_archive_count == UMP_LOG_CAPACITY);
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY/2-1, 2) == 0x102);
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 2) == 0x205);
|
||||
CHECK(ump_count == 0 && ump_state == 1);
|
||||
generation = ump_generation;
|
||||
archived = ump_word(1, UMP_LOG_CAPACITY-1, 0);
|
||||
sequence = ump_sequence;
|
||||
for (i=0; i<200; i++) ump_log_tick();
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived);
|
||||
CHECK(ump_generation == generation);
|
||||
CHECK(ump_sequence == sequence + 200);
|
||||
CHECK(ump_log_read(UMP_LOG_LIVE+2) == 3);
|
||||
CHECK(ump_log_read(UMP_LOG_LIVE+4) == ump_time-2);
|
||||
CHECK(ump_log_write(UMP_LOG_BASE+3, 1));
|
||||
CHECK(ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY-1));
|
||||
CHECK(ump_log_read(UMP_LOG_DATA) == archived);
|
||||
CHECK(ump_log_read(UMP_LOG_DATA+UMP_LOG_WORDS) == 0);
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY));
|
||||
CHECK(ump_log_write(UMP_LOG_BASE, 0));
|
||||
sequence = ump_sequence;
|
||||
ump_log_tick(); ump_log_io(); ump_log_can(1,2,3,4);
|
||||
CHECK(sequence == ump_sequence);
|
||||
CHECK(ump_log_write(UMP_LOG_BASE, 1));
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived);
|
||||
/* Новый пуск и спад start без reset также фиксируют отключение. */
|
||||
modbus[127] = 0x80; ump_log_rs();
|
||||
modbus[127] = 0; ump_log_rs();
|
||||
CHECK(ump_post == 1000);
|
||||
for (i=0; i<1000; i++) ump_log_tick();
|
||||
CHECK(ump_generation == generation+1);
|
||||
/* CAN читает те же регистры и формирует цельный снимок из 124 слов.
|
||||
* Запись по старым технологическим адресам через сервис запрещена. */
|
||||
length = ump_can_prepare(3, UMP_LOG_BASE, 16, reply, &error);
|
||||
CHECK(!error && length == 16 && reply[0] == 0x554D && reply[1] == 2);
|
||||
length = ump_can_prepare(3, UMP_LOG_LIVE, 124, reply, &error);
|
||||
CHECK(!error && length == 124);
|
||||
ump_can_prepare(3, UMP_LOG_LIVE, 126, reply, &error);
|
||||
CHECK(error == 2);
|
||||
ump_can_prepare(6, 127, 0x80, reply, &error);
|
||||
CHECK(error == 2 && modbus[127] == 0);
|
||||
length = ump_can_prepare(6, UMP_LOG_BASE, 0, reply, &error);
|
||||
CHECK(!error && length == 2 && reply[0] == UMP_LOG_BASE && reply[1] == 0);
|
||||
CHECK(ump_state == 3);
|
||||
ump_can_prepare(6, UMP_LOG_BASE+1, 0, reply, &error);
|
||||
CHECK(error == 3);
|
||||
ump_can_prepare(99, UMP_LOG_BASE, 16, reply, &error);
|
||||
CHECK(error == 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Host test of the 166 recorder. Requires Clang/lld or MSVC (Windows).
|
||||
|
||||
Example: py -3 tests/ump_logger/run_test.py --compiler "C:/path/to/cl.exe"
|
||||
All build products are written to a temporary directory.
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--compiler', default=shutil.which('clang') or shutil.which('cl'))
|
||||
args = parser.parse_args()
|
||||
if not args.compiler:
|
||||
parser.error('Provide --compiler pointing to clang.exe or cl.exe')
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
with tempfile.TemporaryDirectory(prefix='ump-recorder-') as directory:
|
||||
output = Path(directory)
|
||||
library = output / 'recorder_test.dll'
|
||||
includes = [root / 'tests/ump_logger/stubs', root / 'Source/Internal/Include']
|
||||
source = root / 'tests/ump_logger/recorder_test.c'
|
||||
if Path(args.compiler).stem.lower() == 'cl':
|
||||
command = [args.compiler, '/nologo', '/LD', '/GS-', '/wd4068', '/wd4312',
|
||||
*['/I' + str(p) for p in includes], str(source),
|
||||
'/Fo' + str(output / 'recorder.obj'), '/link', '/NOENTRY',
|
||||
'/NODEFAULTLIB', '/OUT:' + str(library)]
|
||||
else:
|
||||
command = [args.compiler, '-shared', '-nostdlib', '-fuse-ld=lld',
|
||||
'-Wl,/noentry,/nodefaultlib', '-Wno-unknown-pragmas',
|
||||
'-Wno-int-to-pointer-cast', *['-I' + str(p) for p in includes],
|
||||
str(source), '-o', str(library)]
|
||||
subprocess.run(command, cwd=output, check=True)
|
||||
subprocess.run([os.sys.executable, '-c',
|
||||
'import ctypes,sys; r=ctypes.CDLL(sys.argv[1]).run_tests(); '
|
||||
'print("PASS" if r==0 else f"FAIL: C line {r}"); sys.exit(bool(r))',
|
||||
str(library)], check=True)
|
||||
@@ -0,0 +1 @@
|
||||
extern unsigned int adc_table_lem[4];
|
||||
@@ -0,0 +1 @@
|
||||
extern unsigned long IMPowse, WAKEpowse;
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef UMP_TEST_DEVICE_H
|
||||
#define UMP_TEST_DEVICE_H
|
||||
struct mock_bits { unsigned int GPIO3, GPIO6, GPIO8, GPIO11, GPIO58, GPIO62; };
|
||||
struct mock_reg { struct mock_bits bit; };
|
||||
struct mock_gpio { struct mock_reg GPADAT, GPBDAT; };
|
||||
extern struct mock_gpio GpioDataRegs;
|
||||
static unsigned int __disable_interrupts(void) { return 0; }
|
||||
static void __restore_interrupts(unsigned int saved) { (void)saved; }
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
/* Подмена зависимостей для проверки регистратора без платы. */
|
||||
@@ -0,0 +1 @@
|
||||
/* Подмена зависимостей для проверки регистратора без платы. */
|
||||
@@ -0,0 +1,2 @@
|
||||
extern int READY, Desk, Mode;
|
||||
#define READY_FREQ 1000
|
||||
@@ -0,0 +1 @@
|
||||
/* Подмена зависимостей для проверки регистратора без платы. */
|
||||
@@ -0,0 +1,9 @@
|
||||
extern int modbus[128];
|
||||
#define dsk_LOAD 6
|
||||
#define Commands modbus[127]
|
||||
#define sens_data (modbus+24)
|
||||
#define DAC_min() modbus[0x79]
|
||||
#define DAC_max() modbus[0x78]
|
||||
#define DAC_cal() modbus[0x7A]
|
||||
#define DAC_04 modbus[0x6F]
|
||||
#define DAC_20 modbus[0x6E]
|
||||
@@ -0,0 +1 @@
|
||||
/* Подмена зависимостей для проверки регистратора без платы. */
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Декларации TI-интринсиков только для проверки синтаксиса на компьютере. */
|
||||
unsigned int __disable_interrupts(void);
|
||||
void __restore_interrupts(unsigned int saved);
|
||||
Reference in New Issue
Block a user