Перенести настройки выпуска в JSON, добавить переносимый сценарий сборки и проверки BIN. Обновить конфигурации CCS, исходники в UTF-8, обработку TESTLAMP, образы прошивки и регрессионные проверки.
331 lines
16 KiB
C
331 lines
16 KiB
C
/* Параметры и обработчики Modbus после проверки CRC. Массив modbus
|
||
* содержит обычные адреса 0..127, область 0x1000 обслуживает логгер.
|
||
* EEPROM хранит параметры, но не является источником START/STOP:
|
||
* при загрузке сохраняется последняя живая команда нагрузки.
|
||
* Функции вызываются из main; EEPROM блокирует этот контекст.
|
||
*/
|
||
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
|
||
#include "package.h"
|
||
#include "RS485.h"
|
||
#include "crc16.h"
|
||
#include "cntrl_adr.h"
|
||
#include "bios_dsp.h"
|
||
#include "message.h"
|
||
#include "filter_bat2.h"
|
||
#include "measure.h"
|
||
|
||
|
||
#include "ADC.h"
|
||
#include "peripher.h"
|
||
|
||
#include "ecan.h"
|
||
#include "pulto.h"
|
||
#include "spise2p.h"
|
||
#include "include/balsam167_eeprom_block.h" /* Использует общий с 167 контракт FC03: окно 0x8000..0xBFFF, до 120 слов AT25256B за запрос. */
|
||
|
||
#include "caliber.h"
|
||
#include "log_to_mem.h"
|
||
#include "firmware_info.h" /* Подключает адрес и границы неизменяемого паспорта 0x1200, совместимого с проверкой прошивки в 167. */
|
||
#include "../src/firmware_info_static.c" /* Собирает общие 12 слов firmware-info через include-путь firmware-info/include; как в 167, копии упаковщика в проекте нет. */
|
||
#include "DAC.h"
|
||
|
||
int modbus[ANSWER_LEN+1];
|
||
unsigned int param[ANSWER_LEN+1];
|
||
|
||
void Default_params()
|
||
{
|
||
unsigned int i,def;
|
||
|
||
int shkf_lo_edge[] = {300, // 380
|
||
300, // 38O
|
||
0, // 0
|
||
0, // 0
|
||
15, // 31
|
||
22, // 27
|
||
20, // 24
|
||
10, // 15
|
||
60}; // AD
|
||
|
||
int bright[] = {10,8,6,8,6,8};
|
||
|
||
for(i=0;i<ANSWER_LEN;i++)
|
||
{
|
||
/* Команда нагрузки не является параметром по умолчанию. */
|
||
if (Desk != dsk_LOAD || i != 127) Modbus[i].all = 0;
|
||
}
|
||
|
||
UMP_reset_parameter_commands();
|
||
LastMode = Mode;
|
||
|
||
if(Desk == dsk_EPLT)
|
||
{
|
||
Cancount[m_FAST] = 10; // Задаёт для пульта быстрый CAN-пакет раз в 10 базовых интервалов CANPOWSE по 20 мс, то есть примерно 200 мс; это значение по умолчанию, которое могут заменить параметры EEPROM.
|
||
|
||
for(i=0;i<6;i++) Bright[i] = bright[i];
|
||
}
|
||
else
|
||
{
|
||
Cancount[m_FAST] = 12; // пауза между посылками CAN
|
||
Brightness = 8;
|
||
}
|
||
|
||
Cancount[m_SLOW] = 50; // Задаёт медленную CAN-рассылку раз в 50 базовых интервалов CANPOWSE по 20 мс, то есть примерно раз в секунду; это значение по умолчанию могут заменить параметры EEPROM.
|
||
|
||
if(Kalibro)
|
||
{
|
||
def = Mode-3;
|
||
if(Mode==adr_SHKF) def=4;
|
||
|
||
for(i=0;i<8;i++) Caliber[i] = def_cal[def][i];
|
||
}
|
||
|
||
if(Desk == dsk_COMM)
|
||
{
|
||
for(i=0;i<TPL_POW*2;i++)
|
||
{
|
||
sens_hi_edge[i] = 70;
|
||
sens_lo_edge[i] = 60;
|
||
} }
|
||
|
||
if(Desk==dsk_BKSD)
|
||
{
|
||
for(i=0;i<6;i++)
|
||
{
|
||
sens_hi_edge[i] = 170;
|
||
sens_lo_edge[i] = 150;
|
||
}
|
||
for(i=6;i<8;i++)
|
||
{
|
||
sens_hi_edge[i] = 115;
|
||
sens_lo_edge[i] = 105;
|
||
} }
|
||
|
||
if(Desk==dsk_BKST)
|
||
for(i=0;i<TPL_TRN*2;i++)
|
||
{
|
||
sens_hi_edge[i] = 70;
|
||
sens_lo_edge[i] = 60;
|
||
}
|
||
|
||
if(Mode==adr_SHKF)
|
||
{
|
||
for(i=0;i<15;i++) sens_lo_edge[i] = shkf_lo_edge[sens_type[i]];
|
||
|
||
sens_hi_edge[13] = 70;
|
||
sens_hi_edge[14] = 70;
|
||
}
|
||
|
||
if(Desk==dsk_LOAD)
|
||
{
|
||
sens_hi_edge[0] = 420;
|
||
sens_hi_edge[1] = 420;
|
||
sens_hi_edge[2] = 900;
|
||
sens_hi_edge[3] = 900;
|
||
sens_lo_edge[0] = 300;
|
||
sens_lo_edge[1] = 300;
|
||
sens_lo_edge[2] = 800;
|
||
sens_lo_edge[3] = 800;
|
||
|
||
DAC_20 = Caliber[6];
|
||
DAC_04 = Caliber[7];
|
||
|
||
/* Не врема!
|
||
DAC_go = 6; // начало зарада
|
||
DAC_stop= 15; // конец зарада
|
||
*/
|
||
}
|
||
|
||
if(Kurrent)
|
||
for(i=0;i<4;i++)
|
||
Zero_lev[i] = 0x800;
|
||
|
||
Init_sensors_more();
|
||
}
|
||
|
||
/* CRC и Mode проверяются до применения EEPROM. Слово 127
|
||
* нагрузки не копируется даже временно: ISR не должен увидеть
|
||
* старый START из EEPROM либо потерять текущую CAN-команду.
|
||
*/
|
||
void Load_params()
|
||
{
|
||
unsigned int i,crc;
|
||
|
||
Seeprom_read(0x3FFF-(ANSWER_LEN+1), param, (ANSWER_LEN+1)*2);
|
||
crc = get_crc16(param,ANSWER_LEN);
|
||
if( (crc==param[ANSWER_LEN]) &&
|
||
(crc !=0xFFFF) &&
|
||
(Mode == param[126]))
|
||
{
|
||
/* Не восстанавливать START/STOP из EEPROM даже на один тик ISR. */
|
||
for(i=0;i<ANSWER_LEN;i++)
|
||
if (Desk != dsk_LOAD || i != 127) modbus[i] = param[i];
|
||
UMP_reset_parameter_commands();
|
||
}
|
||
else
|
||
{
|
||
Default_params();
|
||
UMP_reset_parameter_commands();
|
||
Save_params();
|
||
if(Desk == dsk_COMM)
|
||
{
|
||
cTermoCal = 1;
|
||
Caliber_time = 0xFFFF;
|
||
} } }
|
||
|
||
/* ISR продолжает менять измерения во время сбора param. CRC
|
||
* относится к собранному массиву, а не атомарному снимку всей платы.
|
||
* Не вызывать сохранение из критического пути дискретов.
|
||
*/
|
||
void Save_params()
|
||
{
|
||
unsigned int i,dif=0;
|
||
|
||
for(i=0;i<ANSWER_LEN;i++)
|
||
if(param[i] != modbus[i])
|
||
{
|
||
param[i] = modbus[i];
|
||
dif=1;
|
||
}
|
||
if(dif)
|
||
{
|
||
param[ANSWER_LEN] = get_crc16(param,ANSWER_LEN);
|
||
Seeprom_write(0x3FFF-(ANSWER_LEN+1),param,(ANSWER_LEN+1)*2);
|
||
} }
|
||
|
||
/***************************************************************/
|
||
/***************************************************************/
|
||
/* Передача данных по протоколу ModBus - команда 3
|
||
Чтение ачеек данных */
|
||
/***************************************************************/
|
||
/***************************************************************/
|
||
|
||
static void modbus_exception(RS_DATA *rs_arr, unsigned int function, unsigned int error)
|
||
{
|
||
unsigned int crc;
|
||
rs_arr->buffer[0] = CNTRL_ADDR;
|
||
rs_arr->buffer[1] = function | 0x80;
|
||
rs_arr->buffer[2] = error;
|
||
crc = get_crc_16(0xFFFF, rs_arr->buffer, 3);
|
||
rs_arr->buffer[3] = LOBYTE(crc); rs_arr->buffer[4] = HIBYTE(crc);
|
||
rs_arr->flag_TIMEOUT_to_Send = true;
|
||
RS_Send(rs_arr, rs_arr->buffer, 5);
|
||
}
|
||
|
||
void ReceiveCommandModbus3(RS_DATA *rs_arr)
|
||
{
|
||
unsigned int crc, Address_MB, Length_MB, i, value, saved = 0;
|
||
|
||
// получили начальный адрес чтениа
|
||
Address_MB = (rs_arr->RS_Header[2] << 8) | rs_arr->RS_Header[3];
|
||
|
||
// получили количество слов данных
|
||
Length_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5];
|
||
if (Address_MB >= BALSAM167_EEPROM_RTU_BASE) { /* Выделяет только верхнее окно EEPROM; старые регистры, логгер и паспорт обрабатываются прежним кодом ниже. */
|
||
if (!balsam167_eeprom_block_valid_profile(CMD_MODBUS_3, Address_MB, Length_MB, 0U)) { /* Профиль 0 сохраняет контракт 167 для 32 КиБ: запрещает пустой блок, более 120 слов, M95 и выход за конец окна. */
|
||
modbus_exception(rs_arr, CMD_MODBUS_3, 2U); /* Возвращает Illegal Data Address с CRC до любого обращения к SPI при неверном диапазоне. */
|
||
return; /* Не допускает перехода ошибочного запроса EEPROM к backend логгера или обычным регистрам. */
|
||
} /* Валидатор проверяет конец через вычитание, поэтому переполнение 16-битного адреса не разрешает чтение. */
|
||
Seeprom_read(Address_MB - BALSAM167_EEPROM_RTU_BASE, &rs_arr->buffer[3], Length_MB * 2U); /* Как в 167, SPI получает адрес в 16-битных словах и длину в октетах; IRQ остаются разрешены для автомата Timer2. */
|
||
for (i = Length_MB; i > 0U; --i) { /* Разворачивает прочитанные слова с конца в том же UART-буфере без нового массива и перезаписи ещё не обработанных слов. */
|
||
value = rs_arr->buffer[i + 2U]; /* Временное слово сохраняет оба SPI-октета до расширения одного элемента C28x в два октета RTU. */
|
||
rs_arr->buffer[i * 2U + 2U] = value & 0xFFU; /* Записывает младший октет слова после старшего, как требует физический дамп EEPROM в SETGUI. */
|
||
rs_arr->buffer[i * 2U + 1U] = (value >> 8) & 0xFFU; /* Маска 0xFF выделяет восемь бит линии из 16-битного unsigned int C28x. */
|
||
} /* Обратный обход корректен и для одного слова, и для максимального блока из 120 слов. */
|
||
rs_arr->buffer[0] = CNTRL_ADDR; /* Отвечает собственным адресом платы, сохраняя поддержку общего адреса 16 существующим приёмником. */
|
||
rs_arr->buffer[1] = CMD_MODBUS_3; /* Возвращает стандартную команду FC03 без введения отдельной команды BIOS или записи памяти. */
|
||
rs_arr->buffer[2] = Length_MB * 2U; /* Число полезных октетов находится в диапазоне 2..240 и помещается в одном октете RTU. */
|
||
crc = get_crc_16(0xFFFFU, rs_arr->buffer, Length_MB * 2U + 3U); /* Проверяет адрес, команду, длину и весь блок тем же Modbus CRC16, что остальные ответы прошивки. */
|
||
rs_arr->buffer[Length_MB * 2U + 3U] = LOBYTE(crc); /* Передаёт младший октет CRC первым в соответствии с Modbus RTU. */
|
||
rs_arr->buffer[Length_MB * 2U + 4U] = HIBYTE(crc); /* Завершает кадр старшим октетом CRC без устаревшего нулевого хвоста. */
|
||
rs_arr->flag_TIMEOUT_to_Send = true; /* Использует штатное управление таймаутом UART при отправке готового ответа из main. */
|
||
RS_Send(rs_arr, rs_arr->buffer, Length_MB * 2U + 5U); /* Отправляет ровно 5 служебных октетов плюс данные, максимум 245 элементов из существующего буфера на 400. */
|
||
return; /* Завершает только новый маршрут EEPROM, сохраняя прежние форматы остальных ответов FC03. */
|
||
} /* Новый маршрут не меняет PEEK, запись EEPROM, адреса параметров или драйвер SPI. */
|
||
if (!Length_MB || Length_MB > 125 ||
|
||
!((Address_MB < ANSWER_LEN && Length_MB <= ANSWER_LEN-Address_MB) ||
|
||
(Address_MB >= UMP_LOG_BASE && Address_MB <= UMP_LOG_BASE+15 &&
|
||
Length_MB <= UMP_LOG_BASE+16-Address_MB) ||
|
||
(Address_MB >= UMP_LOG_DATA && Address_MB < UMP_LOG_DATA+120 &&
|
||
Length_MB <= UMP_LOG_DATA+120-Address_MB) ||
|
||
(Address_MB == UMP_LOG_LIVE && Length_MB == 124) || /* Сохраняет точное прежнее 124-словное онлайн-окно логгера. */
|
||
firmware_info_range(Address_MB, Length_MB))) { /* Дополнительно разрешает только полное или частичное чтение двенадцати регистров паспорта. */
|
||
modbus_exception(rs_arr, CMD_MODBUS_3, 2); return;
|
||
}
|
||
|
||
/////////////////////////////////////////////////
|
||
// Отсылка
|
||
/* Посчитали контрольную сумму перед самой посылкой */
|
||
|
||
rs_arr->buffer[0] = CNTRL_ADDR;
|
||
rs_arr->buffer[1] = CMD_MODBUS_3;
|
||
rs_arr->buffer[2] = Length_MB*2;
|
||
|
||
/* Защищаем целостность одного снимка/блока; передача UART идёт уже
|
||
* с разрешёнными прерываниями и не задерживает измерение/управление. */
|
||
if (Address_MB >= UMP_LOG_BASE && Address_MB < FIRMWARE_INFO_ADDRESS) saved = __disable_interrupts(); /* Неизменяемый паспорт не требует блокировки IRQ; целостность прежних снимков логгера сохраняется. */
|
||
for (i=0;i<Length_MB;i++)
|
||
{
|
||
if (Address_MB >= FIRMWARE_INFO_ADDRESS) value = firmware_info_static_read(Address_MB - FIRMWARE_INFO_ADDRESS + i); /* После проверки диапазона читает только соответствующее слово статического паспорта, без обращения к логгеру. */
|
||
else value = Address_MB >= UMP_LOG_BASE ? ump_log_read(Address_MB+i) : (unsigned int)modbus[Address_MB+i]; /* Сохраняет прежнюю маршрутизацию и беззнаковое представление 16-битных слов технологической карты и логгера v4. */
|
||
rs_arr->buffer[3+i*2] = (value >> 8) & 0xFF;
|
||
rs_arr->buffer[3+i*2+1] = value & 0xFF;
|
||
}
|
||
|
||
if (Address_MB >= UMP_LOG_BASE && Address_MB < FIRMWARE_INFO_ADDRESS) __restore_interrupts(saved); /* Возвращает сохранённую маску только для действительно защищённого снимка логгера. */
|
||
crc = 0xffff;
|
||
crc = get_crc_16(crc, rs_arr->buffer, Length_MB*2+3);
|
||
|
||
rs_arr->buffer[Length_MB*2+3] = LOBYTE(crc);
|
||
rs_arr->buffer[Length_MB*2+4] = HIBYTE(crc);
|
||
|
||
rs_arr->buffer[Length_MB*2+5] = 0;
|
||
rs_arr->buffer[Length_MB*2+6] = 0;
|
||
rs_arr->buffer[Length_MB*2+7] = 0;
|
||
rs_arr->buffer[Length_MB*2+8] = 0;
|
||
|
||
rs_arr->flag_TIMEOUT_to_Send=true;
|
||
/* Расширение логгера отвечает точным кадром Modbus без хвостовых
|
||
* нулей: они иначе попали бы в начало ответа следующего блока GUI.
|
||
* Исторический формат технологических регистров оставлен прежним. */
|
||
RS_Send(rs_arr, rs_arr->buffer, Length_MB*2+(Address_MB >= UMP_LOG_BASE ? 5 : 8));
|
||
|
||
return;
|
||
}
|
||
|
||
void ReceiveCommandModbus6(RS_DATA *rs_arr)
|
||
{
|
||
unsigned int Address_MB, Data_MB, i;
|
||
|
||
/////////////////////////////////////////////////
|
||
// Отсылка
|
||
/* Отправлаем назад то же самое */
|
||
|
||
for (i=0;i<8;i++)
|
||
rs_arr->buffer[i] = rs_arr->RS_Header[i];
|
||
|
||
|
||
// получили начальный адрес записи
|
||
Address_MB = (rs_arr->RS_Header[2] << 8) | rs_arr->RS_Header[3];
|
||
|
||
// получили слово данных
|
||
Data_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5];
|
||
if (Address_MB >= FIRMWARE_INFO_ADDRESS && Address_MB < FIRMWARE_INFO_END) { modbus_exception(rs_arr, CMD_MODBUS_6, 2); return; } /* Как в контракте 167, запись в паспорт запрещена с Illegal Data Address и не достигает параметров или логгера. */
|
||
|
||
if (Address_MB >= UMP_LOG_BASE) {
|
||
if (!ump_log_write(Address_MB, Data_MB)) {
|
||
modbus_exception(rs_arr, CMD_MODBUS_6, 3); return;
|
||
}
|
||
} else if (Address_MB < ANSWER_LEN) {
|
||
/* RS и CAN используют одну историю фронтов. Чередование каналов
|
||
* не создаёт двух независимых повторных запусков. */
|
||
if (Address_MB == 127) {
|
||
UMP_commands_write(Data_MB);
|
||
ump_log_rs();
|
||
} else Modbus[Address_MB].all = Data_MB;
|
||
} else { modbus_exception(rs_arr, CMD_MODBUS_6, 2); return; }
|
||
|
||
rs_arr->flag_TIMEOUT_to_Send=true;
|
||
RS_Send(rs_arr, rs_arr->buffer, Address_MB >= UMP_LOG_BASE ? 8 : 10);
|
||
}
|
||
|