/* Служебный CAN-протокол логгера УМП. Не использует адреса 0..127 * технологического обмена. Формат полезных данных совместим с порядком * слов старого CAN: MDL (слова 1,2), затем MDH (маркер, слово 0). * Запрос: маркер 0x1F00, слово 0 = token:8 | function:8, * слова 1,2 = адрес расширения и число слов/записываемое значение. * Ответы: маркер 0x1F00 + номер фрагмента, слово 0 = token:8 | error:8, * слова 1,2 = два слова единого зафиксированного снимка. * Биты маски записи в заголовке запроса равны нулю: старая плата * игнорирует запрос, не изменяя технологические регистры. */ #ifndef UMP_CAN_PROTOCOL_H #define UMP_CAN_PROTOCOL_H #include "log_to_mem.h" #include "firmware_info.h" /* Использует то же окно firmware-info v1, что FC03, сохраняя остальной служебный CAN-протокол 166. */ #define UMP_CAN_MARKER 0x1F00U #define UMP_CAN_MAX_WORDS 124U /* Вызывающий код защищает весь снимок от IRQ. Функция не ждёт CAN и * не пишет за пределами reply[124]. Ошибки возвращаются отдельным кадром. */ static unsigned int ump_can_prepare(unsigned int function, unsigned int address, unsigned int value, unsigned int *reply, unsigned int *error) { unsigned int i; *error = 0; if (function == 3) { if (firmware_info_range(address, value)) { /* Признаёт только чтение внутри нового двенадцатисловного паспорта. */ for (i = 0; i < value; ++i) reply[i] = firmware_info_static_read(address - FIRMWARE_INFO_ADDRESS + i); /* Общий статический упаковщик выдаёт те же слова, что RS, без чтения архива логгера. */ return value; /* Передаёт паспорт существующему механизму фрагментов CAN без изменения mailbox, ID и повторов. */ } /* Все остальные запросы продолжают проходить прежнюю проверку окон логгера v4. */ if (!((address == UMP_LOG_BASE && value == 16) || /* Разрешает от одной до десяти целых 12-словных записей v4 в пределах 120 слов полезного окна CAN. */ (address == UMP_LOG_DATA && value >= UMP_LOG_WORDS && value <= 120U && value % UMP_LOG_WORDS == 0U) || (address == UMP_LOG_LIVE && value == 124))) *error = 2; else { for (i = 0; i < value; i++) reply[i] = ump_log_read(address+i); return value; } } else if (function == 6) { if (address < UMP_LOG_BASE || address > UMP_LOG_BASE+3) *error = 2; else if (!ump_log_write(address, value)) *error = 3; } else *error = 1; /* Для записи возвращаем эхо адреса и значения, для ошибки — её контекст. */ reply[0] = address; reply[1] = value; return 2; } #endif