Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41e24629ce | ||
|
|
a5e46d4627 | ||
|
|
95c8b8ac7d |
@@ -9,5 +9,5 @@ if(NOT WIN32)
|
||||
endif()
|
||||
add_library(candle SHARED candle.c candle_ctrl_req.c candle.def)
|
||||
target_compile_definitions(candle PRIVATE UNICODE _UNICODE)
|
||||
target_link_libraries(candle PRIVATE setupapi winusb ole32 advapi32)
|
||||
target_link_libraries(candle PRIVATE setupapi winusb ole32 advapi32 cfgmgr32) # Configuration Manager сопоставляет интерфейсы CAN и DFU по родительскому USB-узлу.
|
||||
target_include_directories(candle PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
+149
-4
@@ -34,6 +34,86 @@
|
||||
#include "candle_defs.h"
|
||||
#include "candle_ctrl_req.h"
|
||||
#include "ch_9.h"
|
||||
#include <cfgmgr32.h> /* Сопоставляет интерфейсы CAN и DFU по общему родительскому USB-устройству Windows. */
|
||||
|
||||
static DWORD candle_dfu_parent(const wchar_t *path, DEVINST *parent) /* Возвращает родителя интерфейса, чтобы команда не попала в другой подключённый адаптер. */
|
||||
{ /* Начало поиска физического USB-устройства по пути выбранного CAN-интерфейса. */
|
||||
HDEVINFO devices = SetupDiCreateDeviceInfoList(NULL, NULL); /* Создаёт временный набор SetupAPI без перечисления посторонних устройств. */
|
||||
if (devices == INVALID_HANDLE_VALUE) return GetLastError(); /* Сохраняет причину отказа создания набора Windows. */
|
||||
SP_DEVICE_INTERFACE_DATA iface = {0}; /* Подготавливает описание интерфейса для открытия по точному пути. */
|
||||
iface.cbSize = sizeof(iface); /* Передаёт SetupAPI размер структуры текущей разрядности процесса. */
|
||||
SP_DEVINFO_DATA info = {0}; /* Получает идентификатор узла PnP выбранного интерфейса. */
|
||||
info.cbSize = sizeof(info); /* Указывает размер структуры устройства согласно контракту SetupAPI. */
|
||||
DWORD size = 0, error = ERROR_SUCCESS; /* Хранит требуемое число байтов и итоговый код Windows. */
|
||||
if (!SetupDiOpenDeviceInterfaceW(devices, path, 0, &iface)) error = GetLastError(); /* Открывает только заданный путь, сохраняя ошибку исчезнувшего устройства. */
|
||||
if (!error) SetupDiGetDeviceInterfaceDetailW(devices, &iface, NULL, 0, &size, NULL); /* Узнаёт объём буфера переменной длины для пути USB-интерфейса. */
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail = size ? malloc(size) : NULL; /* Выделяет буфер только после успешного определения его размера. */
|
||||
if (!error && !detail) error = size ? ERROR_NOT_ENOUGH_MEMORY : GetLastError(); /* Отличает нехватку памяти от ошибки поиска описания. */
|
||||
if (detail) { /* Обрабатывает описание только при наличии выделенного буфера. */
|
||||
detail->cbSize = sizeof(*detail); /* Согласует размер заголовка с архитектурой Win32 или Win64. */
|
||||
if (!SetupDiGetDeviceInterfaceDetailW(devices, &iface, detail, size, NULL, &info)) error = GetLastError(); /* Получает узел интерфейса из SetupAPI. */
|
||||
else if (CM_Get_Parent(parent, info.DevInst, 0) != CR_SUCCESS) error = ERROR_NOT_FOUND; /* Получает общий родительский узел составного USB-адаптера. */
|
||||
free(detail); /* Освобождает описание после получения идентификатора родителя. */
|
||||
} /* Завершает работу с описанием интерфейса. */
|
||||
SetupDiDestroyDeviceInfoList(devices); /* Освобождает набор SetupAPI при любом результате поиска. */
|
||||
return error; /* Возвращает ноль при успехе либо причину отказа Windows. */
|
||||
} /* Завершает сопоставление интерфейса с физическим USB-устройством. */
|
||||
|
||||
uint32_t __stdcall candle_dev_enter_dfu(const wchar_t *can_path, uint8_t status[6]) /* Возвращает код Windows и шестибайтовый DFU_GETSTATUS согласно DFU 1.1. */
|
||||
{ /* Начало отдельного сеанса управляющего интерфейса обновления. */
|
||||
if (!can_path || !status) return ERROR_INVALID_PARAMETER; /* Запрещает отсутствие точного пути адаптера или выходного буфера статуса. */
|
||||
memset(status, 0, 6); /* Исключает использование неинициализированных полей ответа при ошибке USB. */
|
||||
DEVINST wanted_parent = 0; /* Запоминает физический адаптер, выбранный пользователем до остановки CAN. */
|
||||
DWORD error = candle_dfu_parent(can_path, &wanted_parent); /* Ищет родителя по сохранённому пути CAN, не заменяя его первым найденным устройством. */
|
||||
if (error) return error; /* Прерывает переход, если выбранный адаптер уже исчез из PnP. */
|
||||
GUID guid = {0xc25b4308, 0x04d3, 0x11e6, {0xb3, 0xea, 0x60, 0x57, 0x18, 0x9e, 0x64, 0x43}}; /* GUID интерфейса обновления из дескриптора CANable 2.5. */
|
||||
HDEVINFO devices = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); /* Перечисляет только подключённые интерфейсы обновления CANable 2.5. */
|
||||
if (devices == INVALID_HANDLE_VALUE) return GetLastError(); /* Возвращает отказ SetupAPI без попытки послать команду. */
|
||||
error = ERROR_NOT_FOUND; /* Отсутствие интерфейса обновления не считается успешным входом в DFU. */
|
||||
for (DWORD index = 0; ; ++index) { /* Проверяет интерфейсы до точного совпадения физического устройства. */
|
||||
SP_DEVICE_INTERFACE_DATA iface = {0}; /* Создаёт независимое описание очередного DFU-интерфейса. */
|
||||
iface.cbSize = sizeof(iface); /* Задаёт обязательный размер структуры SetupAPI. */
|
||||
if (!SetupDiEnumDeviceInterfaces(devices, NULL, &guid, index, &iface)) { /* Завершает обход либо сообщает ошибку перечисления. */
|
||||
if (GetLastError() != ERROR_NO_MORE_ITEMS) error = GetLastError(); /* Отличает штатный конец списка от отказа Windows. */
|
||||
break; /* Выходит из обхода после исчерпания интерфейсов или ошибки. */
|
||||
} /* Завершает проверку результата перечисления. */
|
||||
DWORD size = 0; /* Хранит размер описания очередного интерфейса в байтах. */
|
||||
SetupDiGetDeviceInterfaceDetailW(devices, &iface, NULL, 0, &size, NULL); /* Определяет буфер для полного пути интерфейса обновления. */
|
||||
if (!size) { error = GetLastError(); break; } /* Не продолжает работу с неполным результатом SetupAPI. */
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail = malloc(size); /* Выделяет описание с достаточным местом для USB-пути. */
|
||||
if (!detail) { error = ERROR_NOT_ENOUGH_MEMORY; break; } /* Не допускает обращения к отсутствующему буферу. */
|
||||
detail->cbSize = sizeof(*detail); /* Сохраняет ABI описания интерфейса Windows. */
|
||||
if (!SetupDiGetDeviceInterfaceDetailW(devices, &iface, detail, size, NULL, NULL)) { /* Получает путь, который можно передать CreateFileW. */
|
||||
error = GetLastError(); free(detail); break; /* Сохраняет ошибку и освобождает буфер перед выходом. */
|
||||
} /* Завершает чтение пути интерфейса. */
|
||||
DEVINST parent = 0; /* Хранит родителя текущего кандидата на обновление. */
|
||||
if (candle_dfu_parent(detail->DevicePath, &parent) || parent != wanted_parent) { /* Исключает каждый интерфейс другого физического адаптера. */
|
||||
free(detail); continue; /* Освобождает описание неподходящего кандидата и продолжает поиск. */
|
||||
} /* Завершает проверку принадлежности выбранному USB-адаптеру. */
|
||||
HANDLE file = CreateFileW(detail->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); /* Эксклюзивно открывает интерфейс обновления выбранного устройства для WinUSB. */
|
||||
free(detail); /* Путь больше не нужен после открытия системного дескриптора. */
|
||||
if (file == INVALID_HANDLE_VALUE) { error = GetLastError(); break; } /* Не скрывает отсутствие доступа или занятость интерфейса. */
|
||||
WINUSB_INTERFACE_HANDLE usb = NULL; /* Хранит отдельный WinUSB-сеанс интерфейса обновления без CAN bulk endpoint. */
|
||||
error = ERROR_SUCCESS; /* Сбрасывает исходное отсутствие интерфейса после точного совпадения устройства. */
|
||||
if (!WinUsb_Initialize(file, &usb)) error = GetLastError(); /* Проверяет наличие рабочего WinUSB-драйвера DFU runtime. */
|
||||
USB_INTERFACE_DESCRIPTOR descriptor = {0}; /* Получает реальный номер и класс открытого интерфейса. */
|
||||
if (!error && !WinUsb_QueryInterfaceSettings(usb, 0, &descriptor)) error = GetLastError(); /* Не предполагает, что произвольный WinUSB-интерфейс поддерживает DFU. */
|
||||
if (!error && (descriptor.bInterfaceClass != 0xFE || descriptor.bInterfaceSubClass != 1 || descriptor.bInterfaceProtocol != 1)) error = ERROR_NOT_SUPPORTED; /* Проверяет класс приложения, подкласс DFU и runtime-протокол по DFU 1.1. */
|
||||
ULONG timeout = 500, transferred = 0; /* Ограничивает управляющий USB-запрос 500 миллисекундами и учитывает длину ответа. */
|
||||
if (!error && !WinUsb_SetPipePolicy(usb, 0, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout)) error = GetLastError(); /* Устанавливает тайм-аут endpoint 0, чтобы отсутствующий ответ не блокировал программу. */
|
||||
WINUSB_SETUP_PACKET packet = {0}; /* Обнуляет поля USB SETUP перед запросом перехода в загрузчик. */
|
||||
packet.RequestType = 0x21; packet.Request = 0; packet.Value = 1000; packet.Index = descriptor.bInterfaceNumber; /* DFU_DETACH: class/interface OUT, запрос 0, ожидаемое время отключения 1000 мс. */
|
||||
if (!error && !WinUsb_ControlTransfer(usb, packet, NULL, 0, &transferred, NULL)) error = GetLastError(); /* Отправляет DETACH и требует подтверждённой USB-транзакции. */
|
||||
packet.RequestType = 0xA1; packet.Request = 3; packet.Value = 0; packet.Length = 6; /* DFU_GETSTATUS: class/interface IN, запрос 3, ответ ровно 6 байт по DFU 1.1. */
|
||||
if (!error && !WinUsb_ControlTransfer(usb, packet, status, 6, &transferred, NULL)) error = GetLastError(); /* Проверяет результат до отложенного перехода прошивки через 300 мс. */
|
||||
if (!error && transferred != 6) error = ERROR_INVALID_DATA; /* Не трактует укороченный ответ как подтверждение входа в загрузчик. */
|
||||
if (usb) WinUsb_Free(usb); /* Освобождает WinUSB до появления загрузчика с другим VID/PID. */
|
||||
CloseHandle(file); /* Освобождает файловый дескриптор после успеха и при любой ошибке USB. */
|
||||
break; /* Не отправляет DETACH повторно и не переключается на другой адаптер при отказе. */
|
||||
} /* Завершает поиск и обработку единственного выбранного адаптера. */
|
||||
SetupDiDestroyDeviceInfoList(devices); /* Освобождает перечень интерфейсов при любом результате. */
|
||||
return error; /* Статус прошивки возвращается отдельно от системной ошибки USB. */
|
||||
} /* Завершает управление DFU runtime без записи flash или изменения образа. */
|
||||
|
||||
static bool candle_dev_interal_open(candle_handle hdev);
|
||||
|
||||
@@ -656,6 +736,30 @@ bool __stdcall DLL candle_dev_open(candle_handle hdev)
|
||||
|
||||
}
|
||||
|
||||
bool __stdcall DLL candle_dev_get_product(candle_handle hdev, wchar_t *product, uint32_t capacity) /* Читает USB Product String открытого адаптера в буфер UTF-16; capacity измеряется в wchar_t, включая завершающий ноль. */
|
||||
{ /* Начало чтения отображаемого имени без изменения режима CAN. */
|
||||
if (!product || !capacity) return false; /* Не пишет в отсутствующий либо пустой выходной буфер. */
|
||||
product[0] = 0; /* Сохраняет пустую строку при любом отказе чтения дескриптора. */
|
||||
candle_device_t *dev = (candle_device_t*)hdev; /* Получает уже открытый WinUSB-сеанс выбранного физического адаптера. */
|
||||
if (!dev || !dev->winUSBHandle) return false; /* Не открывает устройство заново и не обращается к закрытому интерфейсу. */
|
||||
USB_DEVICE_DESCRIPTOR descriptor = {0}; /* Получает индекс строки продукта из стандартного дескриптора устройства. */
|
||||
ULONG received = 0; /* Хранит фактически полученное количество байтов управляющего ответа. */
|
||||
if (!WinUsb_GetDescriptor(dev->winUSBHandle, 1, 0, 0, (PUCHAR)&descriptor, sizeof(descriptor), &received) || received != sizeof(descriptor)) return false; /* Тип 1 обозначает Device Descriptor по USB 2.0; неполный ответ не используется. */
|
||||
UCHAR string_index = descriptor.iProduct; /* Для обычных адаптеров использует объявленный устройством индекс USB Product String. */
|
||||
if (descriptor.idVendor == 0x1D50 && descriptor.idProduct == 0x606F) string_index = 2; /* В CANable Candlelight имя продукта имеет индекс 2; WinUSB может подменять iProduct индексом имени интерфейса, как описано в штатном примере проекта. */
|
||||
if (!string_index) return false; /* Нулевой iProduct означает, что устройство не предоставляет имя продукта. */
|
||||
UCHAR raw[256] = {0}; /* Буфер вмещает строковый дескриптор USB, чей однобайтовый bLength ограничен 255 байтами. */
|
||||
USHORT language = 0x0409; /* Использует английский идентификатор USB как резервный вариант для устройств без списка языков. */
|
||||
if (WinUsb_GetDescriptor(dev->winUSBHandle, 3, 0, 0, raw, sizeof(raw), &received) && received >= 4 && raw[0] >= 4 && raw[1] == 3) language = (USHORT)(raw[2] | ((USHORT)raw[3] << 8)); /* Тип 3 и индекс 0 возвращают список LANGID; выбирает первый язык, предоставленный адаптером. */
|
||||
if (!WinUsb_GetDescriptor(dev->winUSBHandle, 3, string_index, language, raw, sizeof(raw), &received)) return false; /* Читает именно строку продукта на поддерживаемом устройством языке. */
|
||||
if (received < 2 || raw[1] != 3 || raw[0] < 2 || raw[0] > received || (raw[0] & 1)) return false; /* Проверяет тип, размер и чётное число байтов UTF-16 перед копированием в выходной буфер. */
|
||||
uint32_t count = (raw[0] - 2) / 2; /* Исключает двухбайтовый заголовок и переводит длину UTF-16LE из байтов в число кодовых единиц. */
|
||||
if (count >= capacity) return false; /* Не обрезает индивидуальный номер в конце имени и оставляет место для завершающего нуля. */
|
||||
for (uint32_t index = 0; index < count; ++index) product[index] = (wchar_t)(raw[2 + index * 2] | ((USHORT)raw[3 + index * 2] << 8)); /* Явно собирает кодовые единицы UTF-16LE без предположений о выравнивании массива байтов. */
|
||||
product[count] = 0; /* Завершает строку для безопасного чтения через ctypes и отображения в Qt. */
|
||||
return count > 0; /* Пустое имя оставляет интерфейсу стандартную резервную подпись адаптера. */
|
||||
} /* Завершает получение настоящего имени из прошивки USB-адаптера. */
|
||||
|
||||
bool __stdcall DLL candle_dev_get_timestamp_us(candle_handle hdev, uint32_t *timestamp_us)
|
||||
{
|
||||
return candle_ctrl_get_timestamp(hdev, timestamp_us);
|
||||
@@ -823,6 +927,38 @@ bool __stdcall DLL candle_channel_stop(candle_handle hdev, uint8_t ch)
|
||||
return candle_ctrl_set_device_mode(dev, ch, CANDLE_DEVMODE_RESET, 0);
|
||||
}
|
||||
|
||||
bool __stdcall DLL candle_channel_start_configured(candle_handle hdev, uint8_t ch, uint32_t flags) /* Новый вход сохраняет прежний ABI start и позволяет отключать HW_TIMESTAMP. */
|
||||
{ /* Явно выбранные Python-флаги должны попасть в прошивку без автоматического дополнения. */
|
||||
return candle_ctrl_set_device_mode((candle_device_t*)hdev, ch, CANDLE_DEVMODE_START, flags); /* Передаём точную маску после проверки возможностей на уровне транспорта. */
|
||||
} /* Завершение запуска с явно заданными параметрами. */
|
||||
|
||||
bool __stdcall DLL candle_channel_get_data_capabilities(candle_handle hdev, uint8_t ch, candle_capability_t *cap) /* Экспортируем чтение FD-пределов для расчёта тайминга на любой частоте CAN. */
|
||||
{ /* Общая форма capability позволяет повторно использовать валидатор номинального тайминга. */
|
||||
return candle_ctrl_data_capability((candle_device_t*)hdev, ch, cap); /* USB-запрос возвращает реальные пределы выбранного канала. */
|
||||
} /* Завершение получения возможностей быстрой фазы. */
|
||||
|
||||
bool __stdcall DLL candle_channel_set_termination(candle_handle hdev, uint8_t ch, uint32_t state) /* Значения 0 и 1 соответствуют OFF и ON стандарта gs_usb. */
|
||||
{ /* Проверка исключает отправку неопределённого состояния в прошивку. */
|
||||
return state <= 1 && candle_ctrl_termination((candle_device_t*)hdev, ch, &state, true); /* Выполняем запись только для допустимого состояния. */
|
||||
} /* Завершение переключения терминатора. */
|
||||
|
||||
bool __stdcall DLL candle_channel_get_termination(candle_handle hdev, uint8_t ch, uint32_t *state) /* Чтение состояния не меняет топологию CAN. */
|
||||
{ /* Используем тот же формат 32-битного значения, что и при записи. */
|
||||
return candle_ctrl_termination((candle_device_t*)hdev, ch, state, false); /* false выбирает USB_DIR_IN и GET_TERMINATION. */
|
||||
} /* Завершение чтения терминатора. */
|
||||
|
||||
bool __stdcall DLL candle_channel_get_diagnostics(candle_handle hdev, uint8_t ch, uint32_t *state, uint32_t *rxerr, uint32_t *txerr) /* Сохраняем счётчики, которые старый get_state отбрасывал. */
|
||||
{ /* Диагностика выполняется только для уже открытого устройства. */
|
||||
candle_device_state_t data = {0}; /* Полная структура протокола содержит три слова: состояние, RX и TX. */
|
||||
if (!candle_ctrl_get_state((candle_device_t*)hdev, ch, &data)) { /* Не возвращаем нулевые счётчики как будто запрос был успешным. */
|
||||
return false; /* Причина USB-отказа уже записана управляющим запросом. */
|
||||
} /* Дальнейшее копирование относится только к подтверждённому ответу. */
|
||||
*state = data.state; /* Сохраняем состояние Error-active, Warning, Passive, Bus-off, Stopped или Sleeping. */
|
||||
*rxerr = data.rxerr; /* Счётчик ошибок приёма измеряется в единицах CAN-контроллера. */
|
||||
*txerr = data.txerr; /* Счётчик ошибок передачи помогает отличать отсутствие ACK от ошибок приёма. */
|
||||
return true; /* Все три выходных значения относятся к одному USB-ответу. */
|
||||
} /* Завершение расширенной диагностики канала. */
|
||||
|
||||
/* Write len bytes from buf to the OUT pipe, aborting after 300 ms.
|
||||
* Writes are serialised by writeMutex in CandleApiInterface so dev->txEvent
|
||||
* is never accessed by two threads simultaneously. */
|
||||
@@ -1017,14 +1153,13 @@ bool __stdcall DLL candle_fd_frame_read(candle_handle hdev, candle_fd_frame_t *f
|
||||
}
|
||||
dev->rxurbs[urb_num].pending = false;
|
||||
|
||||
/* Minimum: classic CAN header (12 bytes) + at least 8 data bytes = 20 bytes */
|
||||
static const DWORD classic_min = sizeof(candle_frame_t) - 4;
|
||||
if (bytes_transfered < classic_min) {
|
||||
const DWORD header_size = 12; /* Заголовок gs_usb занимает 12 байт в Classic и FD; короткий FD может не содержать восьми байтов данных. */
|
||||
if (bytes_transfered < header_size) { /* До чтения flags и DLC проверяем наличие полного заголовка. */
|
||||
candle_prepare_read(dev, urb_num);
|
||||
candle_logf(L"fd read too small urb=%u bytes=%lu min=%lu",
|
||||
urb_num,
|
||||
bytes_transfered,
|
||||
classic_min);
|
||||
header_size); /* Минимальная длина здесь относится к заголовку, а payload проверяется после определения формата. */
|
||||
dev->last_error = CANDLE_ERR_READ_SIZE;
|
||||
return false;
|
||||
}
|
||||
@@ -1047,6 +1182,11 @@ bool __stdcall DLL candle_fd_frame_read(candle_handle hdev, candle_fd_frame_t *f
|
||||
if (is_fd_frame) {
|
||||
/* can_dlc is at byte offset 8 in both classic and FD wire frames. */
|
||||
const uint8_t raw_dlc = dev->rxurbs[urb_num].buf[8];
|
||||
if (raw_dlc > 15) { /* FD DLC является четырёхбитным кодом и не может содержать значения выше 15. */
|
||||
candle_prepare_read(dev, urb_num); /* Повреждённый USB-пакет не должен останавливать последующий приём. */
|
||||
dev->last_error = CANDLE_ERR_READ_SIZE; /* Неверный DLC считается ошибкой формата входного кадра. */
|
||||
return false; /* Не превращаем повреждённый DLC в пустой успешный FD-кадр. */
|
||||
} /* Далее длина безопасно вычисляется по таблице CAN FD. */
|
||||
const DWORD data_len = candle_dlc_to_len(raw_dlc);
|
||||
const DWORD min_size = 12 + data_len; /* header + data, without timestamp */
|
||||
|
||||
@@ -1077,6 +1217,11 @@ bool __stdcall DLL candle_fd_frame_read(candle_handle hdev, candle_fd_frame_t *f
|
||||
}
|
||||
/* else: timestamp stays zero from memset above */
|
||||
} else {
|
||||
if (bytes_transfered < sizeof(candle_frame_t) - sizeof(uint32_t)) { /* Classic-пакет обязан содержать весь восьмибайтовый буфер данных, даже при меньшем DLC. */
|
||||
candle_prepare_read(dev, urb_num); /* Возобновляем соответствующий URB после отклонения неполного пакета. */
|
||||
dev->last_error = CANDLE_ERR_READ_SIZE; /* Не допускаем чтение неполученных данных из локальной структуры. */
|
||||
return false; /* Повреждённый Classic-пакет не попадает в Python через FD API. */
|
||||
} /* Минимальный размер Classic теперь проверен отдельно от коротких FD. */
|
||||
/* Classic CAN frame — copy into FD struct, fixing the timestamp position */
|
||||
candle_frame_t classic;
|
||||
DWORD copy_len = (bytes_transfered < sizeof(classic)) ? bytes_transfered : sizeof(classic);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
; прикладные регистры SETProtocol.
|
||||
|
||||
EXPORTS
|
||||
candle_dev_get_product ; Имя продукта из USB-дескриптора прошивки для списка адаптеров SETGUI.
|
||||
candle_dev_enter_dfu ; Переход через отдельный DFU runtime-интерфейс того же физического USB-адаптера.
|
||||
candle_list_scan
|
||||
candle_list_free
|
||||
candle_list_length
|
||||
@@ -31,3 +33,13 @@ EXPORTS
|
||||
candle_frame_data
|
||||
candle_frame_timestamp_us
|
||||
candle_dev_last_error
|
||||
candle_channel_start_configured ; Точная маска запуска с управляемыми аппаратными метками.
|
||||
candle_channel_get_data_capabilities ; Пределы тайминга быстрой фазы CAN FD.
|
||||
candle_channel_set_termination ; Переключение встроенного терминатора.
|
||||
candle_channel_get_termination ; Чтение состояния встроенного терминатора.
|
||||
candle_channel_get_diagnostics ; Состояние и счётчики ошибок CAN.
|
||||
candle_channel_set_data_timing ; Тайминг фазы данных CAN FD.
|
||||
candle_fd_frame_send ; Отправка полного кадра CAN FD до 64 байт.
|
||||
candle_fd_frame_read ; Приём FD и Classic без обрезания данных.
|
||||
candle_fd_frame_type ; Различение RX, TX echo и ошибок FD.
|
||||
candle_fd_frame_id ; Получение CAN ID из структуры FD.
|
||||
|
||||
@@ -246,7 +246,9 @@ bool __stdcall DLL candle_list_length(candle_list_handle list, uint8_t *len);
|
||||
bool __stdcall DLL candle_dev_get(candle_list_handle list, uint8_t dev_num, candle_handle *hdev);
|
||||
bool __stdcall DLL candle_dev_get_state(candle_handle hdev, candle_devstate_t *state);
|
||||
wchar_t * __stdcall DLL candle_dev_get_path(candle_handle hdev);
|
||||
bool __stdcall DLL candle_dev_get_product(candle_handle hdev, wchar_t *product, uint32_t capacity); /* Возвращает USB Product String в UTF-16; capacity включает завершающий ноль и измеряется в wchar_t. */
|
||||
bool __stdcall DLL candle_dev_open(candle_handle hdev);
|
||||
uint32_t __stdcall DLL candle_dev_enter_dfu(const wchar_t *can_path, uint8_t status[6]); /* Переводит выбранный физический адаптер в DFU и возвращает Win32-код плюс ответ DFU_GETSTATUS. */
|
||||
bool __stdcall DLL candle_dev_get_timestamp_us(candle_handle hdev, uint32_t *timestamp_us);
|
||||
bool __stdcall DLL candle_dev_close(candle_handle hdev);
|
||||
bool __stdcall DLL candle_dev_free(candle_handle hdev);
|
||||
@@ -259,6 +261,11 @@ bool __stdcall DLL candle_channel_set_timing(candle_handle hdev, uint8_t ch, can
|
||||
bool __stdcall DLL candle_channel_set_bitrate(candle_handle hdev, uint8_t ch, uint32_t bitrate);
|
||||
bool __stdcall DLL candle_channel_start(candle_handle hdev, uint8_t ch, uint32_t flags);
|
||||
bool __stdcall DLL candle_channel_stop(candle_handle hdev, uint8_t ch);
|
||||
bool __stdcall DLL candle_channel_start_configured(candle_handle hdev, uint8_t ch, uint32_t flags); /* Запускаем с точной маской без принудительного включения аппаратных меток. */
|
||||
bool __stdcall DLL candle_channel_get_data_capabilities(candle_handle hdev, uint8_t ch, candle_capability_t *cap); /* Возвращаем пределы тайминга быстрой фазы FD. */
|
||||
bool __stdcall DLL candle_channel_set_termination(candle_handle hdev, uint8_t ch, uint32_t state); /* Состояние терминатора: 0 — выключен, 1 — включён. */
|
||||
bool __stdcall DLL candle_channel_get_termination(candle_handle hdev, uint8_t ch, uint32_t *state); /* Чтение не меняет подключение встроенного резистора. */
|
||||
bool __stdcall DLL candle_channel_get_diagnostics(candle_handle hdev, uint8_t ch, uint32_t *state, uint32_t *rxerr, uint32_t *txerr); /* Передаём состояние CAN и оба счётчика ошибок без потери данных ответа. */
|
||||
|
||||
bool __stdcall DLL candle_frame_send(candle_handle hdev, uint8_t ch, candle_frame_t *frame);
|
||||
bool __stdcall DLL candle_frame_read(candle_handle hdev, candle_frame_t *frame, uint32_t timeout_ms);
|
||||
|
||||
@@ -39,8 +39,10 @@ enum {
|
||||
CANDLE_TIMESTAMP_GET = 6,
|
||||
/* 7: IDENTIFY, 8: GET_USER_ID, 9: SET_USER_ID (not used here) */
|
||||
CANDLE_BREQ_DATA_BITTIMING = 10,
|
||||
/* 11: SET_TERMINATION, not used here */
|
||||
CANDLE_BREQ_GET_STATE = 12,
|
||||
CANDLE_BREQ_BT_CONST_EXT = 11, /* Расширенные пределы номинальной и быстрой фазы согласно gs_usb. */
|
||||
CANDLE_BREQ_SET_TERMINATION = 12, /* Запрос gs_usb 12 переключает встроенный резистор окончания шины. */
|
||||
CANDLE_BREQ_GET_TERMINATION = 13, /* Запрос gs_usb 13 читает текущее состояние терминатора. */
|
||||
CANDLE_BREQ_GET_STATE = 14, /* Стандартный GET_STATE имеет номер 14; номер 12 принадлежит терминатору. */
|
||||
CANDLE_BREQ_BUS_OFF_RECOVERY = 32,
|
||||
};
|
||||
|
||||
@@ -237,3 +239,22 @@ bool candle_ctrl_bus_off_recover(candle_device_t *dev, uint8_t channel)
|
||||
dev->last_error = rc ? CANDLE_ERR_OK : CANDLE_ERR_SET_DEVICE_MODE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool candle_ctrl_data_capability(candle_device_t *dev, uint8_t channel, candle_capability_t *cap) /* Структура gs_usb BT_CONST_EXT содержит десять общих и восемь быстрых полей uint32. */
|
||||
{ /* Используем массив, поскольку протокол содержит только однородные 32-битные значения без отступов. */
|
||||
uint32_t fields[18] = {0}; /* 18 полей по 4 байта образуют стандартный ответ размером 72 байта. */
|
||||
bool rc = usb_control_msg(dev->winUSBHandle, CANDLE_BREQ_BT_CONST_EXT, USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, channel, 0, fields, sizeof(fields)); /* Запрашиваем пределы именно выбранного CAN-канала. */
|
||||
if (rc) { /* Выходная структура должна меняться только после успешного USB-ответа. */
|
||||
memcpy(cap, fields, 2 * sizeof(uint32_t)); /* Маска функций и частота CAN общие для обеих фаз. */
|
||||
memcpy(&cap->tseg1_min, &fields[10], 8 * sizeof(uint32_t)); /* Поля DTSEG1…DBRP_INC заменяют номинальные пределы структуры capability. */
|
||||
} /* При отказе вызывающий код получит false и не использует нулевые пределы. */
|
||||
dev->last_error = rc ? CANDLE_ERR_OK : CANDLE_ERR_GET_BITTIMING_CONST; /* Сохраняем диагностический код чтения аппаратных ограничений. */
|
||||
return rc; /* Успех означает наличие полной структуры пределов быстрой фазы. */
|
||||
} /* Завершение запроса расширенных возможностей FD. */
|
||||
|
||||
bool candle_ctrl_termination(candle_device_t *dev, uint8_t channel, uint32_t *state, bool write) /* Переключение терминатора использует стандартные SET=12 и GET=13. */
|
||||
{ /* Состояние передаётся одним 32-битным словом согласно протоколу gs_usb. */
|
||||
bool rc = usb_control_msg(dev->winUSBHandle, write ? CANDLE_BREQ_SET_TERMINATION : CANDLE_BREQ_GET_TERMINATION, (write ? USB_DIR_OUT : USB_DIR_IN)|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, channel, 0, state, sizeof(*state)); /* Номер CAN-канала передаётся в wValue, а wIndex равен нулю по спецификации. */
|
||||
dev->last_error = rc ? CANDLE_ERR_OK : CANDLE_ERR_SET_DEVICE_MODE; /* Ошибка настройки доступна Python через candle_dev_last_error. */
|
||||
return rc; /* Не выдаём успешное переключение при отказе USB-контроллера. */
|
||||
} /* Завершение управления встроенным окончанием шины. */
|
||||
|
||||
@@ -51,4 +51,6 @@ bool candle_ctrl_set_data_bittiming(candle_device_t *dev, uint8_t channel, candl
|
||||
bool candle_ctrl_get_timestamp(candle_device_t *dev, uint32_t *current_timestamp);
|
||||
bool candle_ctrl_get_state(candle_device_t *dev, uint8_t channel, candle_device_state_t *data);
|
||||
bool candle_ctrl_bus_off_recover(candle_device_t *dev, uint8_t channel);
|
||||
bool candle_ctrl_data_capability(candle_device_t *dev, uint8_t channel, candle_capability_t *cap); /* Читаем пределы быстрой фазы CAN FD отдельным запросом расширенной структуры. */
|
||||
bool candle_ctrl_termination(candle_device_t *dev, uint8_t channel, uint32_t *state, bool write); /* Передаём состояние терминатора: 0 — выключен, 1 — включён. */
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile # Резервирует номер сборки через временный файл на том же диске, как общий итератор ветки 166.
|
||||
|
||||
|
||||
def git_state(repository: Path) -> dict:
|
||||
@@ -36,20 +37,46 @@ def git_state(repository: Path) -> dict:
|
||||
def write_atomic(path: Path, text: str):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
temporary = path.with_name(path.name + ".tmp")
|
||||
temporary.write_text(text, encoding="utf-8", newline="\n")
|
||||
with open(temporary, "w", encoding="utf-8", newline="\n") as stream: # Сохраняет UTF-8 и LF также на Python 3.8, где Path.write_text ещё не принимает newline.
|
||||
stream.write(text) # Полностью записывает заголовок или паспорт перед атомарной заменой целевого файла.
|
||||
temporary.replace(path)
|
||||
|
||||
|
||||
def prepare(repository: Path, templates: Path, config: Path, output: Path) -> dict:
|
||||
settings = json.loads(config.read_text(encoding="utf-8"))
|
||||
version = settings["version"]
|
||||
if (len(version) != 3 or any(type(v) is not int for v in version)
|
||||
or not all(0 <= v <= limit for v, limit in zip(version, (255, 255, 999)))):
|
||||
raise ValueError("version must be [major 0..255, minor 0..255, patch 0..999]")
|
||||
def next_version(version): # Повторяет общий итератор 166 и переносит переполнение младшего разряда в старший.
|
||||
result = list(version) # Не изменяет исходный номер до проверки полного переполнения.
|
||||
for index, limit in ((2, 999), (1, 255), (0, 255)): # Контракт firmware-info v1 допускает patch 0..999 и major/minor 0..255.
|
||||
if result[index] < limit: # Выбирает младший разряд, который ещё допускает увеличение.
|
||||
result[index] += 1 # Занимает следующий номер попытки сборки ровно один раз.
|
||||
return result # Возвращает новый номер с сохранёнными старшими и обнулёнными переполненными младшими разрядами.
|
||||
result[index] = 0 # Переносит единицу к следующему разряду при достижении предела текущего.
|
||||
raise ValueError("Firmware version exhausted at 255.255.999") # Не допускает повторного использования версии после полного переполнения контракта.
|
||||
|
||||
|
||||
def prepare(repository: Path, templates: Path, config: Path, output: Path) -> dict: # Формирует один паспорт текущей попытки после сохранения номера автоматической сборки.
|
||||
settings = json.loads(config.read_text(encoding="utf-8-sig")) # Принимает исходный JSON в UTF-8, включая старые файлы Windows с BOM.
|
||||
version = settings["version"] # Начальный номер берётся из единственного сохраняемого источника проекта.
|
||||
if not isinstance(version, list) or len(version) != 3 or any(type(value) is not int or not 0 <= value <= limit for value, limit in zip(version, (255, 255, 999))): # Проверяет три целых разряда и пределы протокола до изменения JSON.
|
||||
raise ValueError("version must be [major 0..255, minor 0..255, patch 0..999]") # Останавливает prebuild при неверном формате счётчика.
|
||||
if type(settings.get("increment_version", False)) is not bool: # Старые проекты сохраняют ручной режим; автоматический требует настоящего логического true.
|
||||
raise ValueError("increment_version must be true or false") # Не принимает строки и числа вместо явной настройки счётчика.
|
||||
for field in ("product", "target"):
|
||||
if not isinstance(settings.get(field), str) or not settings[field].strip():
|
||||
raise ValueError(f"missing {field}")
|
||||
source, dependency = git_state(repository), git_state(templates)
|
||||
if settings.get("increment_version", False): # Увеличение выполняется только при подготовке основного проекта, а не при упаковке RAM, CAN и Flash.
|
||||
version = settings["version"] = next_version(version) # Один вычисленный номер используется исходным JSON, генерируемым заголовком и паспортом.
|
||||
with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", newline="\n", dir=config.parent, prefix=".firmware-version-", delete=False) as stream: # Временный файл рядом с JSON позволяет атомарную замену счётчика на том же диске.
|
||||
temporary = Path(stream.name) # Запоминает только собственный файл для очистки при отказе сохранения.
|
||||
try: # Ошибка записи должна сохранить исходный JSON и удалить незавершённый временный файл.
|
||||
stream.write(json.dumps(settings, ensure_ascii=False, indent=2) + "\n") # Сохраняет новый номер и все дополнительные настройки проекта в UTF-8.
|
||||
except BaseException: # Освобождает собственный файл также при прерывании процесса записи.
|
||||
stream.close() # Windows разрешает удалить временный файл после закрытия его дескриптора.
|
||||
temporary.unlink() # Удаляет только незавершённый файл этой попытки резервирования номера.
|
||||
raise # Возвращает исходную ошибку вместо продолжения сборки с несохранённой версией.
|
||||
try: # Номер должен быть надёжно занят до генерации выходов и начала компиляции.
|
||||
temporary.replace(config) # Атомарно фиксирует счётчик, чтобы следующая попытка не повторила номер при последующей ошибке сборки.
|
||||
finally: # При неудачной замене исходный JSON остаётся прежним, а собственный временный файл очищается.
|
||||
temporary.unlink(missing_ok=True) # После успешного переименования файла уже нет; Python 3.8 поддерживает missing_ok.
|
||||
source, dependency = git_state(repository), git_state(templates) # Отмечает изменённый счётчик в происхождении текущего выпуска после резервирования номера.
|
||||
# A clean application built with a modified templates checkout is dirty too.
|
||||
known = source["commit"] is not None and dependency["commit"] is not None
|
||||
dirty = bool(source["dirty"] or dependency["dirty"])
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Результаты отдельных конфигураций CCS воспроизводятся установленным TI compiler.
|
||||
/projects/ccs/*/Debug/
|
||||
/projects/ccs/*/Release/
|
||||
# Служебные локальные настройки IDE и launch не входят в переносимый проект.
|
||||
/projects/ccs/*/.settings/
|
||||
/projects/ccs/*/.launches/
|
||||
# Python cache не является исходником общего модуля или проекта.
|
||||
**/__pycache__/
|
||||
@@ -1,6 +1,6 @@
|
||||
# Сборка библиотеки protocan_boot. Состав исходников и публичные include-пути задают
|
||||
# подключение к проекту потребителя. Файл также собирает и регистрирует хостовые проверки;
|
||||
# запускать их следует через CTest из каталога сборки.
|
||||
# Общая C99-библиотека ProtoCAN Boot и аппаратно независимые host-тесты.
|
||||
# Каждый контроллер сохраняет собственное состояние и отдельный аппаратный порт.
|
||||
# Дополнительные проекты CCS находятся в projects/ccs и не требуют CMake для TI-сборки.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(protocan_boot C)
|
||||
@@ -17,7 +17,7 @@ else()
|
||||
target_compile_options(protocan_boot PRIVATE -Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
option(PCAN_BOOT_BUILD_TESTS "Собирать тесты ProtoCAN boot" ON)
|
||||
option(PCAN_BOOT_BUILD_TESTS "Собирать тесты ProtoCAN Boot" ON) # Не включает host-модели в код MCU.
|
||||
if(PCAN_BOOT_BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_executable(test_pcan_boot tests/test_pcan_boot.c)
|
||||
@@ -45,3 +45,12 @@ if(PCAN_BOOT_BUILD_TESTS)
|
||||
add_test(NAME f28335_store_${width} COMMAND test_f28335_store_${width})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(PCAN_BOOT_BUILD_TESTS) # Подключает настоящий аппаратно независимый драйвер NOR F2812 и регрессию длительного BUSY.
|
||||
add_executable(test_f2812_nor tests/test_f2812_nor.c src/pcan_boot.c ports/tms320f2812/nor_flash.c ports/tms320f2812/boot_store.c) # Компилирует production-код вместе с x16 моделью чипа.
|
||||
target_compile_definitions(test_f2812_nor PRIVATE PCAN_BOOT_WIDE_BYTES BOOT2812_HOST) # Октеты C28x широкие; подменяется только физическая шина памяти.
|
||||
add_test(NAME f2812_nor COMMAND test_f2812_nor) # Регистрирует проверки CRC, SCI8, границ, manifest и отказов NOR.
|
||||
add_executable(test_pcan_busy tests/test_pcan_busy.c src/pcan_boot.c) # Использует тот же codec, который обслуживает длинные аппаратные операции.
|
||||
target_compile_definitions(test_pcan_busy PRIVATE PCAN_BOOT_WIDE_BYTES) # Проверяет wire-статус при 16-битном представлении октета C28x.
|
||||
add_test(NAME pcan_busy COMMAND test_pcan_busy) # Регистрирует проверку продления session при живом прогрессе erase.
|
||||
endif() # Включение библиотек без тестов не добавляет host-модель в прошивку.
|
||||
|
||||
@@ -180,8 +180,14 @@ ctest --test-dir build --output-on-failure
|
||||
|
||||
## F28335 / большая EEPROM
|
||||
|
||||
[Порт M95M02](ports/tms320f28335/README.md) подключён в `tms_periph/periph_167`.
|
||||
[Порт M95M02](ports/tms320f28335/README.md) подключён в `28335_periph`, ветка 167.
|
||||
Использует отдельный Flash-загрузчик и два слота EEPROM по 130560 байт.
|
||||
Реализованы readback/CRC, проверка SCI8, журнал метаданных, пробный запуск,
|
||||
CONFIRM/откат, PING/discovery и сервисный паспорт. Первичная установка Flash-
|
||||
загрузчика и выбор Flash boot описаны в README порта.
|
||||
|
||||
## Самостоятельные проекты CCS
|
||||
|
||||
Готовые проекты **F28335_CAN_AB** (M95M02) и **F2812_CAN_NOR** (AM29LV800BT),
|
||||
включая необходимые файлы поддержки TI, находятся в `projects/ccs`.
|
||||
[Импорт, сборка, карты памяти и установка](projects/README.md).
|
||||
|
||||
@@ -52,7 +52,8 @@ typedef enum {
|
||||
PCAN_BOOT_CMD_PING = 0x0CU,
|
||||
PCAN_BOOT_CMD_CAPABILITIES = 0x0DU,
|
||||
PCAN_BOOT_CMD_DEVICE_NAME = 0x0EU,
|
||||
PCAN_BOOT_CMD_MEMORY_INFO = 0x0FU
|
||||
PCAN_BOOT_CMD_MEMORY_INFO = 0x0FU, /* Сохраняет существующий номер постраничного паспорта памяти. */
|
||||
PCAN_BOOT_CMD_SELECT_MEMORY = 0x10U /* Выбирает 0=штатное хранилище, 1=внутренняя Flash до передачи метаданных. */
|
||||
} pcan_boot_command_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -127,6 +128,7 @@ typedef struct {
|
||||
/** Optional precise result, replacing legacy boolean verify_image. */
|
||||
pcan_boot_status_t (*verify_status)(void *user, pcan_boot_byte_t slot,
|
||||
const pcan_boot_manifest_t *manifest);
|
||||
pcan_boot_status_t (*select_memory)(void *user, pcan_boot_byte_t memory, pcan_boot_config_t *config); /* Необязательный порт явно переключает назначение образа до ERASE; старые порты возвращают INVALID_COMMAND. */
|
||||
} pcan_boot_port_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -164,6 +166,9 @@ bool pcan_boot_process(pcan_boot_t *boot, uint32_t can_id,
|
||||
/** Call regularly with a wrapping monotonic millisecond clock. */
|
||||
void pcan_boot_poll(pcan_boot_t *boot, uint32_t now_ms);
|
||||
|
||||
uint32_t pcan_boot_crc32_update(uint32_t crc, const pcan_boot_byte_t *data, size_t length); /* Общий потоковый CRC32 для readback аппаратных хранилищ; начальное состояние равно нулю. */
|
||||
bool pcan_boot_report_busy(pcan_boot_t *boot, pcan_boot_byte_t command, uint32_t now_ms); /* Долгие аппаратные операции сообщают BUSY тем же codec и той же session, что обычный ответ. */
|
||||
|
||||
/** Переносимые операции с 29-битным ProtoCAN ID. */
|
||||
uint32_t pcan_boot_make_id(pcan_boot_byte_t priority, pcan_boot_byte_t route,
|
||||
pcan_boot_byte_t device_type, pcan_boot_byte_t device_id,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# F2812 / AM29LV800BT
|
||||
|
||||
Самостоятельный проект, карта NOR, параметры CAN, установка и ограничения
|
||||
описаны в [общей инструкции CCS](../../projects/README.md).
|
||||
|
||||
- `boot2812.h` — физические CPU word-адреса и отдельная совместимость F2812;
|
||||
- `nor_flash.c` — x16 AMD driver с ID, ограниченными program/sector erase,
|
||||
DQ7/DQ5 polling, readback и BUSY;
|
||||
- `boot_store.c` — упаковка октетов, проверка всей SCI8-таблицы, CRC32,
|
||||
публикация manifest последними magic-словами, проверенная загрузка RAM;
|
||||
- `projects/ccs/f2812/board.c` — подтверждённые линии CPLD и XINTF ПМ67;
|
||||
- `projects/ccs/f2812/main.c` — независимые eCAN/IRQ/очередь/main F2812.
|
||||
|
||||
Протокол и CRC повторно используются из `src/pcan_boot.c`. EEPROM отсутствует;
|
||||
код F28335 и его A/B-журнал не подключаются к этому проекту.
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef BOOT2812_H /* Исключает повторное объявление профиля NOR-загрузчика F2812. */
|
||||
#define BOOT2812_H /* Отделяет основной контроллер ПМ67 от периферийного F28335. */
|
||||
#include "../../include/pcan_boot.h" /* Использует существующий ProtoCAN codec и представление октетов C28x. */
|
||||
#define BOOT2812_NOR_BASE 0x100000UL /* CPU word-адрес AM29LV800BT взят из START_ADR_FLASH действующего flash_tools.h платы. */
|
||||
#define BOOT2812_IMAGE_WORD 0x160000UL /* Новый CAN-образ занимает три полных верхних обычных сектора, выше старого образа и данных FPGA. */
|
||||
#define BOOT2812_IMAGE_BYTES 0x30000UL /* Три сектора по 0x8000 слов дают 196608 октетов полезного SCI8. */
|
||||
#define BOOT2812_META_WORD 0x17E000UL /* Последний top-boot сектор начинается после областей 16K/4K/4K слов и содержит 8192 слова. */
|
||||
#define BOOT2812_PRODUCT 0x2812U /* Отдельный Product Type запрещает запись образа F28335 в основной контроллер F2812. */
|
||||
#define BOOT2812_DEVICE_TYPE 3U /* Тип загрузчика остаётся в том же адресном классе ProtoCAN, что F28335. */
|
||||
#define BOOT2812_DEVICE_ID 6U /* Отдельный ID 6 исключает совпадение с существующим F28335 на адресе 3/7. */
|
||||
#define BOOT2812_RECOVERY_MS 3000UL /* После reset загрузчик три секунды принимает ENTER_BOOT до автоматического запуска сохранённого образа. */
|
||||
unsigned long Boot2812_Now(void); /* Возвращает монотонные миллисекунды Timer1 для CAN и ограниченных ожиданий NOR. */
|
||||
void Boot2812_Busy(void); /* Во время долгого стирания сообщает BUSY через общий codec и обслуживает аппаратный TX ACK. */
|
||||
void Boot2812_BoardInit(void); /* Настраивает действующие линии CPLD и XINTF платы ПМ67. */
|
||||
bool Boot2812_NorIdentify(void); /* До первого erase требует AMD manufacturer 0001 и top-boot device 22DA. */
|
||||
unsigned int Boot2812_NorRead(unsigned long word); /* Читает одно 16-битное слово по CPU-адресу внешней NOR. */
|
||||
bool Boot2812_NorProgram(unsigned long word, unsigned int value); /* Программирует только зарезервированные CAN-области и проверяет прочитанный результат. */
|
||||
bool Boot2812_NorErase(unsigned long word); /* Принимает только начала трёх секторов образа и одного сектора метаданных. */
|
||||
bool Boot2812_Erase(void *user, pcan_boot_byte_t slot); /* Удаляет публикацию до стирания единственного CAN-слота. */
|
||||
bool Boot2812_Write(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length); /* Сохраняет октеты ProtoCAN в x16 NOR младшим байтом вперёд. */
|
||||
pcan_boot_status_t Boot2812_Verify(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image); /* Проверяет CRC прочитанной NOR и все CPU-адреса SCI8 до COMMIT. */
|
||||
bool Boot2812_Commit(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image); /* Публикует manifest только после повторной проверки всей внешней Flash. */
|
||||
bool Boot2812_Load(uint32_t *entry); /* Читает действующий manifest, проверяет образ и переносит только разрешённую RAM. */
|
||||
#endif /* Завершает интерфейс самостоятельного NOR-порта F2812. */
|
||||
@@ -0,0 +1,105 @@
|
||||
#include "boot2812.h" /* Использует отдельные адреса и совместимость внешней NOR F2812. */
|
||||
static unsigned int octet(uint32_t offset) /* Читает октет файла SCI8 из x16 NOR, где младший октет хранится первым. */
|
||||
{ /* Поток CAN остаётся независимым от sizeof(char) на C28x. */
|
||||
unsigned int word = Boot2812_NorRead(BOOT2812_IMAGE_WORD + offset / 2UL); /* Преобразует смещение в октетах в CPU word-адрес слота. */
|
||||
return (offset & 1UL) ? word >> 8 : word & 255U; /* Передаёт младшие восемь бит октета без знакового расширения. */
|
||||
} /* Все дальнейшие поля таблицы собираются из того же порядка октетов. */
|
||||
static unsigned int u16(uint32_t offset) /* Восстанавливает слово TI boot table в little endian. */
|
||||
{ /* Вызывается только после проверки достаточной длины соответствующего поля. */
|
||||
return octet(offset) | (octet(offset + 1UL) << 8); /* Два октета соответствуют одному слову C28x. */
|
||||
} /* Завершает чтение длины секции или данных программы. */
|
||||
static uint32_t address_at(uint32_t offset) /* Адрес TI SCI8 содержит старшее 16-битное слово перед младшим. */
|
||||
{ /* Этот порядок отличается от обычного u32 little endian метаданных ProtoCAN. */
|
||||
return ((uint32_t)u16(offset) << 16) | u16(offset + 2UL); /* Внутри каждого слова по-прежнему сохраняется little endian. */
|
||||
} /* Возвращает CPU-адрес, измеряемый в словах. */
|
||||
static bool allowed(uint32_t first, uint32_t end) /* Разрешает только реальную RAM приложения и исключает RAM работающего загрузчика. */
|
||||
{ /* Новое приложение не должно загружать инициализированные секции в L1 или RAM InitFlash до перехода в runtime. */
|
||||
return end > first && ((first >= 0x8000UL && end <= 0x8F00UL) || (first >= 0x3F8000UL && end <= 0x3FA000UL) || (first >= 0x80000UL && end <= 0x100000UL)); /* L0 до ramfuncs, полный H0 и внешняя SRAM зоны 2; периферия, NOR, стек и внутренние Flash запрещены. */
|
||||
} /* Проверки входа и всех секций выполняются до первой записи приложения в RAM. */
|
||||
static bool table(uint32_t size, bool copy, uint32_t *entry) /* Проверяет целиком SCI8 и при повторном проходе переносит данные в RAM. */
|
||||
{ /* Устойчивость загрузчика не зависит от адресов, заявленных принимаемым файлом. */
|
||||
uint32_t starts[64], ends[64], offset = 22UL, address, end; /* Лимит 64 секции ограничивает стек и число сравнений перекрытий. */
|
||||
unsigned int sections = 0U, count, i; bool entry_loaded = false; /* Требует, чтобы точка входа реально находилась среди загружаемых слов. */
|
||||
if (size < 24UL || (size & 1UL) || u16(0UL) != 0x08AAU) return false; /* Ключ SCI8 AA08, чётный размер и терминатор обязательны. */
|
||||
*entry = address_at(18UL); /* После ключа и восьми резервных слов находится CPU word-адрес C runtime. */
|
||||
while (offset + 2UL <= size) { /* Поле count читается только при наличии обоих октетов. */
|
||||
count = u16(offset); offset += 2UL; /* Размер секции выражен в 16-битных словах, а не октетах файла. */
|
||||
if (!count) return offset == size && entry_loaded; /* Запрещает хвост, незавершённую таблицу и entry вне payload. */
|
||||
if (sections == 64U || size - offset < 4UL) return false; /* Не допускает переполнения ограниченных массивов или усечённого адреса. */
|
||||
address = address_at(offset); offset += 4UL; end = address + count; /* Восстанавливает исключающую верхнюю границу CPU-диапазона секции. */
|
||||
if (!allowed(address, end) || (uint32_t)count * 2UL > size - offset) return false; /* Проверяет адреса и полный payload до обращения к RAM назначения. */
|
||||
for (i = 0; i < sections; ++i) if (address < ends[i] && starts[i] < end) return false; /* Даже правильно переданная CRC не разрешает две секции поверх одного слова. */
|
||||
starts[sections] = address; ends[sections++] = end; /* Сохраняет уже проверенный диапазон для следующих секций. */
|
||||
if (*entry >= address && *entry < end) entry_loaded = true; /* Подтверждает наличие исполняемого слова по адресу входа. */
|
||||
if (copy) { /* Этот проход выполняется только после полной read-only проверки всего образа. */
|
||||
for (i = 0; i < count; ++i) { /* Переносит ровно заявленные и предварительно проверенные слова секции. */
|
||||
#if defined(BOOT2812_HOST) /* Аппаратная модель проверяет тот же диапазон без записи по адресам процесса ПК. */
|
||||
extern void NorModel_LoadWord(uint32_t target, unsigned int value); /* Модель сохраняет каждое слово переноса для независимой проверки. */
|
||||
NorModel_LoadWord(address + i, u16(offset + (uint32_t)i * 2UL)); /* Подменяет только шину RAM назначения. */
|
||||
#else /* На F2812 CPU-адреса уже выражены в 16-битных словах. */
|
||||
*(volatile unsigned int *)(address + i) = u16(offset + (uint32_t)i * 2UL); /* Записывает секцию только в разрешённую RAM приложения. */
|
||||
#endif /* Завершает аппаратную запись либо её host-модель. */
|
||||
} /* Завершает перенос текущей секции. */
|
||||
} /* После проверочного прохода RAM остаётся нетронутой. */
|
||||
offset += (uint32_t)count * 2UL; /* Пропускает полезные октеты до следующего count. */
|
||||
} /* Исчерпание файла без терминатора означает неполный образ. */
|
||||
return false; /* Не запускает незавершённую таблицу. */
|
||||
} /* Образ с ошибкой не публикуется как запускаемый. */
|
||||
bool Boot2812_Erase(void *user, pcan_boot_byte_t slot) /* Реализует single-slot подготовку внешней NOR. */
|
||||
{ /* Существующие legacy-образы и FPGA ниже 160000 не входят в новый CAN-раздел. */
|
||||
unsigned long sector; (void)user; /* Перебирает только три полных обычных сектора нового образа. */
|
||||
if (slot || !Boot2812_NorIdentify() || !Boot2812_NorErase(BOOT2812_META_WORD)) return false; /* Сначала удаляет marker старого CAN-образа; при обрыве стирания сохраняется recovery. */
|
||||
for (sector = BOOT2812_IMAGE_WORD; sector < BOOT2812_IMAGE_WORD + BOOT2812_IMAGE_BYTES / 2UL; sector += 0x8000UL) if (!Boot2812_NorErase(sector)) return false; /* Геометрия x16 допускает erase только по границам обычных секторов 32K слов. */
|
||||
return true; /* Ядро ProtoCAN разрешает DATA только после полного успешного стирания слота. */
|
||||
} /* EEPROM-операции и несуществующий второй слот отсутствуют. */
|
||||
bool Boot2812_Write(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Упаковывает поступившие октеты в x16 слова NOR. */
|
||||
{ /* В одном вызове записывается не более одного classic CAN кадра. */
|
||||
unsigned int i, word; (void)user; /* Счётчик относится к октетам кадра, адрес NOR отдельно делится на два. */
|
||||
if (slot || !length || length > 8U || (offset & 1UL) || offset > BOOT2812_IMAGE_BYTES || length > BOOT2812_IMAGE_BYTES - offset) return false; /* Не допускает выхода из слота либо продолжения слова с неверного октета. */
|
||||
for (i = 0; i < length; i += 2U) { /* Последовательные 8-октетные блоки начинаются на границе x16 слова. */
|
||||
word = (data[i] & 255U) | ((i + 1U < length ? data[i + 1U] & 255U : 255U) << 8); /* Неполное последнее слово сохраняет FF в незанятом старшем октете. */
|
||||
if (!Boot2812_NorProgram(BOOT2812_IMAGE_WORD + (offset + i) / 2UL, word)) return false; /* Аппаратный драйвер проверяет и допустимый адрес, и результат записи каждого слова. */
|
||||
} /* Завершает сохранение текущего CAN-блока. */
|
||||
return true; /* ACK означает проверенную запись, а не только получение кадра. */
|
||||
} /* CRC ядра продвигается только после успешного возврата этого callback. */
|
||||
pcan_boot_status_t Boot2812_Verify(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image) /* Перепроверяет CRC непосредственно из сохранённой NOR. */
|
||||
{ /* Потоковая CRC при приёме не заменяет аппаратный readback полного файла. */
|
||||
uint32_t offset, crc = 0UL, entry; pcan_boot_byte_t bytes[32]; unsigned int count, i; (void)user; /* Небольшой буфер не требует размещать весь образ во внутренней RAM F2812. */
|
||||
if (slot || image->image_size < 24UL || image->image_size > BOOT2812_IMAGE_BYTES || (image->image_size & 1UL)) return PCAN_BOOT_STATUS_INVALID_SIZE; /* SCI8 должен целиком помещаться в выделенных трёх секторах и содержать целые слова. */
|
||||
if (image->product_type != BOOT2812_PRODUCT || image->hardware_revision_min > 1U || image->hardware_revision_max < 1U) return PCAN_BOOT_STATUS_WRONG_DEVICE; /* Образ F28335 или несовместимого изделия не становится загрузочным. */
|
||||
for (offset = 0; offset < image->image_size; offset += count) { /* Проверяет каждый фактически сохранённый октет ровно один раз. */
|
||||
count = image->image_size - offset < 32UL ? (unsigned int)(image->image_size - offset) : 32U; /* Последний буфер ограничен реальной длиной без FF-дополнения CAN. */
|
||||
for (i = 0; i < count; ++i) bytes[i] = octet(offset + i); /* Читает данные из NOR, а не из приёмной очереди CAN. */
|
||||
crc = pcan_boot_crc32_update(crc, bytes, count); /* Использует общий CRC32 ProtoCAN без дублирования полинома в аппаратном порту. */
|
||||
Boot2812_Busy(); /* Большой файл сохраняет ответы клиента при длинной проверке на реальном CPU. */
|
||||
} /* Завершает вычисление CRC readback. */
|
||||
if (crc != image->image_crc32) return PCAN_BOOT_STATUS_CRC_ERROR; /* Различает повреждение памяти и ошибку структуры SCI8. */
|
||||
return table(image->image_size, false, &entry) ? PCAN_BOOT_STATUS_OK : PCAN_BOOT_STATUS_INVALID_STATE; /* Все адреса, перекрытия, терминатор и entry проверяются до COMMIT. */
|
||||
} /* До успеха verifier никакие слова приложения не переносятся в RAM. */
|
||||
bool Boot2812_Commit(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image) /* Публикует загрузочный manifest последней операцией после readback. */
|
||||
{ /* Формат из 12 слов фиксирован и не зависит от sizeof C-структуры. */
|
||||
unsigned int words[12], i; /* Два magic-слова, версия формата, размер, CRC, версия FW и контроль manifest. */
|
||||
pcan_boot_byte_t bytes[20]; uint32_t crc; /* CRC первых десяти слов защищает размер и контрольную сумму самого образа. */
|
||||
if (Boot2812_Verify(user, slot, image) != PCAN_BOOT_STATUS_OK) return false; /* Не публикует файл, испорченный после предыдущего VERIFY. */
|
||||
words[0] = 0x2812U; words[1] = 0xCA7EU; words[2] = 1U; words[3] = 0U; /* Magic 2812/CA7E и версия 1 отличают новый CAN manifest от прежних данных платы. */
|
||||
words[4] = (unsigned int)(image->image_size & 0xFFFFUL); words[5] = (unsigned int)(image->image_size >> 16); /* Длина выражена октетами и хранится младшим словом первой. */
|
||||
words[6] = (unsigned int)(image->image_crc32 & 0xFFFFUL); words[7] = (unsigned int)(image->image_crc32 >> 16); /* Сохраняет точную CRC всего полученного файла. */
|
||||
words[8] = (unsigned int)(image->firmware_version & 0xFFFFUL); words[9] = (unsigned int)(image->firmware_version >> 16); /* Версия кандидата не подменяется версией постоянного загрузчика. */
|
||||
for (i = 0; i < 10U; ++i) { bytes[2U * i] = words[i] & 255U; bytes[2U * i + 1U] = words[i] >> 8; } /* Wire-представление manifest использует октеты независимо от ширины C28x char. */
|
||||
crc = pcan_boot_crc32_update(0UL, bytes, 20U); words[10] = (unsigned int)(crc & 0xFFFFUL); words[11] = (unsigned int)(crc >> 16); /* CRC manifest не позволяет принять частично записанные поля размера и CRC образа. */
|
||||
for (i = 2U; i < 12U; ++i) if (!Boot2812_NorProgram(BOOT2812_META_WORD + i, words[i])) return false; /* Сначала записывает все поля, пока оба magic-слова ещё равны FF. */
|
||||
if (!Boot2812_NorProgram(BOOT2812_META_WORD + 1UL, words[1])) return false; /* Второе magic-слово фиксируется после полного тела manifest. */
|
||||
return Boot2812_NorProgram(BOOT2812_META_WORD, words[0]); /* Первое magic записывается последним: потеря питания раньше оставляет recovery. */
|
||||
} /* Повтор COMMIT обрабатывает идемпотентный автомат общего ядра. */
|
||||
bool Boot2812_Load(uint32_t *entry) /* Проверяет опубликованный образ после reset перед переносом в RAM приложения. */
|
||||
{ /* Пустой или повреждённый manifest оставляет прибор в постоянном CAN recovery. */
|
||||
unsigned int words[12], i; pcan_boot_byte_t bytes[20]; uint32_t crc; pcan_boot_manifest_t image; /* Сериализованные поля читаются явно, без memcpy по ABI структуры. */
|
||||
for (i = 0; i < 12U; ++i) words[i] = Boot2812_NorRead(BOOT2812_META_WORD + i); /* Читает только фиксированные 24 октета manifest. */
|
||||
if (words[0] != 0x2812U || words[1] != 0xCA7EU || words[2] != 1U || words[3]) return false; /* Не интерпретирует старые данные Flash либо неполный commit как запускаемый файл. */
|
||||
for (i = 0; i < 10U; ++i) { bytes[2U * i] = words[i] & 255U; bytes[2U * i + 1U] = words[i] >> 8; } /* Восстанавливает то же октетное представление, что защищалось при COMMIT. */
|
||||
crc = pcan_boot_crc32_update(0UL, bytes, 20U); /* Проверяет метаданные до использования объявленной ими длины. */
|
||||
if (crc != ((uint32_t)words[10] | ((uint32_t)words[11] << 16))) return false; /* Повреждённый размер не может вывести чтение за пределы CAN-слота. */
|
||||
image.image_size = (uint32_t)words[4] | ((uint32_t)words[5] << 16); image.image_crc32 = (uint32_t)words[6] | ((uint32_t)words[7] << 16); /* Размер и CRC файла восстанавливаются только после успешной CRC manifest. */
|
||||
image.firmware_version = (uint32_t)words[8] | ((uint32_t)words[9] << 16); image.product_type = BOOT2812_PRODUCT; image.hardware_revision_min = image.hardware_revision_max = 1U; /* Профиль образа был проверен до публикации manifest. */
|
||||
return Boot2812_Verify(0, 0U, &image) == PCAN_BOOT_STATUS_OK && table(image.image_size, true, entry); /* Сначала полный read-only проход, затем перенос и только после успеха разрешение вызова entry. */
|
||||
} /* Не загружает старые flat BIN автоматически: новый проект использует проверяемую SCI8-таблицу. */
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "boot2812.h" /* Ограничивает аппаратный драйвер разделами обновления конкретного профиля ПМ67. */
|
||||
#if defined(BOOT2812_HOST) /* Host-модель воспроизводит команды NOR без обращения к физическим CPU-адресам. */
|
||||
extern unsigned int NorModel_Read(unsigned long word); /* Модель отдаёт данные, ID и аппаратные биты готовности чипа. */
|
||||
extern void NorModel_Write(unsigned long word, unsigned int value); /* Модель принимает настоящую последовательность unlock/program/erase драйвера. */
|
||||
#define NOR_READ(word) NorModel_Read(word) /* Подменяет только чтение шины, сохраняя алгоритм драйвера. */
|
||||
#define NOR_WRITE(word, value) NorModel_Write(word, value) /* Подменяет физическую запись при проверке границ и отказов. */
|
||||
#else /* Production использует 16-битную параллельную XINTF-шину. */
|
||||
#define NOR_READ(word) (*(volatile unsigned int *)(word)) /* Один CPU-адрес C28x соответствует одному x16 слову AM29LV800BT. */
|
||||
#define NOR_WRITE(word, value) (*(volatile unsigned int *)(word) = (value)) /* Volatile сохраняет каждый командный цикл AMD в исходном порядке. */
|
||||
#endif /* Завершает выбор физической шины либо модели. */
|
||||
static void reset_read(void) /* Выводит чип из autoselect либо неудачной операции в обычный режим чтения. */
|
||||
{ /* Reset не стирает слова памяти и допустим по любому адресу чипа. */
|
||||
NOR_WRITE(BOOT2812_NOR_BASE, 0x00F0U); /* F0 — Read/Reset из таблицы команд AMD Am29LV800B. */
|
||||
} /* Все ошибки возвращают NOR в состояние, пригодное для следующей recovery-сессии. */
|
||||
static void unlock(unsigned int command) /* Выполняет общий префикс x16-команд согласно datasheet AMD. */
|
||||
{ /* Адреса ниже являются смещениями в словах, а не октетными AAA/555 режима x8. */
|
||||
NOR_WRITE(BOOT2812_NOR_BASE + 0x555UL, 0x00AAU); /* Первый unlock-цикл AA по смещению 555h в режиме x16. */
|
||||
NOR_WRITE(BOOT2812_NOR_BASE + 0x2AAUL, 0x0055U); /* Второй unlock-цикл 55 по смещению 2AAh. */
|
||||
NOR_WRITE(BOOT2812_NOR_BASE + 0x555UL, command); /* Третий цикл выбирает autoselect, программирование либо начало стирания. */
|
||||
} /* Последующий цикл данных или адрес сектора выполняет вызывающая операция. */
|
||||
unsigned int Boot2812_NorRead(unsigned long word) /* Читает только физический диапазон установленной NOR ёмкостью 1 МиБ. */
|
||||
{ /* Верхняя исключающая граница равна BASE + 512K слов. */
|
||||
return word >= BOOT2812_NOR_BASE && word < BOOT2812_NOR_BASE + 0x80000UL ? NOR_READ(word) : 0xFFFFU; /* Вне чипа не создаёт шинного чтения по неизвестному адресу. */
|
||||
} /* Возвращает полное x16 слово без перестановки октетов. */
|
||||
bool Boot2812_NorIdentify(void) /* Идентификация обязательна перед разрешением изменяющих операций. */
|
||||
{ /* Не подменяет top-boot геометрию похожим bottom-boot или NAND-чипом. */
|
||||
unsigned int maker, device; /* Хранит два слова autoselect, прежде чем вернуть чип к чтению. */
|
||||
reset_read(); unlock(0x0090U); /* 90h включает чтение manufacturer/device ID после обычного unlock. */
|
||||
maker = NOR_READ(BOOT2812_NOR_BASE); device = NOR_READ(BOOT2812_NOR_BASE + 1UL); /* AMD: offset 0 содержит 0001, offset 1 — 22DA для Am29LV800BT x16. */
|
||||
reset_read(); /* Обычные чтения образа после проверки не должны видеть таблицу autoselect. */
|
||||
return maker == 0x0001U && device == 0x22DAU; /* Отличающийся чип получает отказ до первого sector erase. */
|
||||
} /* Не выполняет разрушительных пробных записей для определения типа памяти. */
|
||||
static bool wait_word(unsigned long word, unsigned int expected, unsigned long timeout) /* Ограничивает DQ7/DQ5 polling временем и числом проходов. */
|
||||
{ /* DQ7 отражает готовность программируемого старшего бита; DQ5 требует завершающего повторного чтения. */
|
||||
unsigned long started = Boot2812_Now(), budget = 50000000UL; /* Итерационный предел обеспечивает выход даже при остановленном Timer1. */
|
||||
unsigned int value; /* Снимок status считывается один раз на основной проход. */
|
||||
do { /* Не вызывает никаких функций из программируемой внешней NOR: код загрузчика находится во внутренней Flash. */
|
||||
value = NOR_READ(word); /* Читает именно адрес программирования либо начало стираемого сектора. */
|
||||
if ((value & 0x0080U) == (expected & 0x0080U)) return NOR_READ(word) == expected; /* После совпадения DQ7 подтверждает все 16 бит результата. */
|
||||
if (value & 0x0020U) { /* DQ5 сообщает превышение внутреннего времени алгоритма AMD. */
|
||||
if ((NOR_READ(word) & 0x0080U) == (expected & 0x0080U)) return NOR_READ(word) == expected; /* Повтор исключает нормальное завершение операции одновременно с чтением DQ5. */
|
||||
break; /* После подтверждённой ошибки больше не ждёт неопределённое время. */
|
||||
} /* Завершает трактовку аппаратного статуса текущего прохода. */
|
||||
Boot2812_Busy(); /* Долгое стирание продолжает давать клиенту живой ответ и не блокирует CAN ISR. */
|
||||
} while (--budget && Boot2812_Now() - started < timeout); /* Беззнаковое вычитание сохраняет корректность при переполнении миллисекунд. */
|
||||
reset_read(); /* Отказ возвращает чип в режим чтения перед следующей recovery-попыткой. */
|
||||
return false; /* Не сообщает успех по одному окончанию тайм-аута. */
|
||||
} /* Завершает ограниченное ожидание аппаратной операции. */
|
||||
bool Boot2812_NorProgram(unsigned long word, unsigned int value) /* Программирует только выделенный CAN-образ либо manifest. */
|
||||
{ /* Старые данные приложения, FPGA и остальные сектора чипа не входят в разрешённые диапазоны. */
|
||||
unsigned int before; /* Предварительное чтение исключает попытку перевода NOR-бита из нуля в единицу. */
|
||||
if (!((word >= BOOT2812_IMAGE_WORD && word < BOOT2812_IMAGE_WORD + BOOT2812_IMAGE_BYTES / 2UL) || (word >= BOOT2812_META_WORD && word < BOOT2812_META_WORD + 0x2000UL))) return false; /* Проверяет word-адрес до любого unlock или командного цикла. */
|
||||
before = NOR_READ(word); /* Проверяет текущее содержимое перед началом операции. */
|
||||
if (before == value) return true; /* Повтор одинакового блока не выполняет лишнее программирование. */
|
||||
if ((before & value) != value) return false; /* Бит 0→1 требует отдельного sector erase и не должен маскироваться чтением старого слова. */
|
||||
unlock(0x00A0U); NOR_WRITE(word, value); /* A0 запускает word program; следующий цикл содержит адрес и полные 16 бит данных. */
|
||||
return wait_word(word, value, 100UL); /* Сто миллисекунд дают ограниченный запас для программирования одного слова. */
|
||||
} /* Каждый успех означает фактическое совпадение прочитанного слова. */
|
||||
bool Boot2812_NorErase(unsigned long word) /* Не принимает произвольный адрес или команду полного стирания чипа. */
|
||||
{ /* Обновление ограничено секторами 12/13/14 и последним top-boot сектором 18. */
|
||||
unsigned long i, count = word == BOOT2812_META_WORD ? 0x2000UL : 0x8000UL; /* AM29LV800BT: обычный сектор 32K слов, последний boot-сектор 8K слов. */
|
||||
if (!(word == BOOT2812_IMAGE_WORD || word == BOOT2812_IMAGE_WORD + 0x8000UL || word == BOOT2812_IMAGE_WORD + 0x10000UL || word == BOOT2812_META_WORD)) return false; /* Только точные разрешённые начала секторов исключают округление в соседнюю область. */
|
||||
unlock(0x0080U); /* 80h начинает шеститактовую последовательность Sector Erase AMD. */
|
||||
NOR_WRITE(BOOT2812_NOR_BASE + 0x555UL, 0x00AAU); NOR_WRITE(BOOT2812_NOR_BASE + 0x2AAUL, 0x0055U); /* Повторяет вторую unlock-пару перед выбором сектора. */
|
||||
NOR_WRITE(word, 0x0030U); /* 30h по sector address выбирает один сектор; команда Chip Erase 10h отсутствует. */
|
||||
if (!wait_word(word, 0xFFFFU, 20000UL)) return false; /* Ограничивает ожидание двадцатью секундами с периодическими BUSY-ответами. */
|
||||
for (i = 0; i < count; ++i) if (NOR_READ(word + i) != 0xFFFFU) return false; /* Проверяет всю стёртую область, а не только её первое слово. */
|
||||
return true; /* Разрешает запись лишь после полного аппаратного readback сектора. */
|
||||
} /* При сбое сохранённый manifest уже недействителен, загрузчик остаётся в recovery. */
|
||||
@@ -1,18 +1,55 @@
|
||||
# F28335 + M95M02: CAN, отдельный загрузчик и A/B
|
||||
|
||||
Реализация состоит из Flash-загрузчика `periph_167/Bootloader`, переносимого
|
||||
Реализация состоит из Flash-загрузчика `projects/ccs/f28335`, переносимого
|
||||
`f28335_boot_store.c`, аппаратного `f28335_boot_hw.c` и адаптера
|
||||
`f28335_can_boot.c`. Приложение подключает их через `Source/Internal/can_boot.c`.
|
||||
`f28335_can_boot.c`. Приложение подключает общий `f28335_can_application.c`
|
||||
прямой ссылкой linked resource из templates в CCS Debug/Release.
|
||||
В сборке `EEPROM_M95M02=0` CAN Boot отключён. Для установленной M95M02 — значение 1.
|
||||
|
||||
## Адрес и формат
|
||||
|
||||
Device Type **3**, Device ID **7**, имя **F28335-M95M02**, Product **0x2833**, HW **1**.
|
||||
Адрес определяется физическим номером **PERIPH 0–31** по новой Excel-таблице:
|
||||
Type = 1 + PERIPH / 16 (целая часть), Device ID = PERIPH mod 16.
|
||||
**УМП1 — 1/5, УМП2 — 1/6, задатчик — 1/8**. Product **0x2833**, HW **1**
|
||||
описывают существующую аппаратную совместимость F28335 и не являются CAN-адресом.
|
||||
Имена паспорта для назначенных плат — `UMP1`, `UMP2`, `Zadatchik`.
|
||||
Приложение передаёт Mode в `F28335CanBoot_Init(Mode)`. Загрузчик независимо
|
||||
читает те же активные низким уровнем GPIO21/20/22/51 с весами 1/2/4/8 и базой 1.
|
||||
Поэтому существующие перемычки ПМ35 задают номера 1–16; номера 0 и 17–31
|
||||
поддерживаются адресным контрактом, но требуют другого источника физического номера.
|
||||
Общий адрес 3/7 больше не принимается. Чужие адреса отбрасываются аппаратным
|
||||
mailbox, ISR и ядром до записи EEPROM, включая данные A/B и управляющие команды.
|
||||
В приложении FW берётся из `firmware_version.h`, формат `major<<24 | minor<<16 | patch`;
|
||||
для версии 1.1.2 это `0x01010002`. Загрузчик сообщает версию подтверждённого образа
|
||||
из журнала, при отсутствии такого образа — 0. Версия кандидата передаётся в BEGIN_COMPAT.
|
||||
CAN **250000 бит/с**, Extended ID, окно **16 блоков по 8 октетов**.
|
||||
ENTER_BOOT для session=1: `0x13790102`, STATUS: `0x1B7C0102`.
|
||||
Для задатчика и session=1: ENTER_BOOT `0x11890102`, STATUS `0x198C0102`.
|
||||
|
||||
## Общий запуск Flash и резервной EEPROM
|
||||
|
||||
Сектор A и аппаратный boot `0x33FFF6` принадлежат постоянному загрузчику.
|
||||
Flash-приложение использует `[0x300000,0x338000)`: первые 16 слов — описание
|
||||
FAB1, остальные — собственные LOAD-секции. `f28335_flash_app.c` проверяет
|
||||
magic/version, entry, границы, инверсию entry, маркеры и CRC32 IEEE всего
|
||||
диапазона после заголовка, включая промежутки, заполненные `0xFFFF`.
|
||||
Python-контракт `python/protocan/f28335_flash.py` заполняет зарезервированные
|
||||
32 октета COFF по смещению, подтверждённому TI OFD, после линковки.
|
||||
|
||||
Загрузчик даёт трёхсекундное окно CAN, затем запускает исправную внутреннюю
|
||||
Flash в приоритете. Отсутствующая/повреждённая Flash ведёт к прежнему выбору
|
||||
EEPROM A/B с trial/CONFIRM/rollback. ENTER_BOOT удерживает CAN recovery.
|
||||
Handoff running=`0xFE` обозначает проверенную внутреннюю Flash; 0/1 — EEPROM
|
||||
A/B, `0xFF` — отсутствие запущенного приложения. Flash-приложение обслуживает
|
||||
PING и ENTER_BOOT, но не подменяет подтверждение EEPROM-кандидата.
|
||||
Обновление EEPROM по CAN не меняет приоритет исправной Flash после reset.
|
||||
|
||||
RS Flash должен стирать только B–H, публиковать FAB1 после проверки остальных
|
||||
данных и запрещать любые адреса сектора A. В SETGUI соответствующие JTAG
|
||||
маски задаются явными TI `FlashSectorA..H`: A для установки boot, B–H для
|
||||
приложения. Полное стирание чипа внешним программатором не ограничивается linker.
|
||||
Старая самостоятельная Flash-сборка с codestart `0x33FFF6` несовместима с этим
|
||||
размещением и не должна передаваться как обновление приложения.
|
||||
|
||||
|
||||
Образ — SCI8 BIN (`AA 08`), чётная длина от 24 до **130560 байт** включительно.
|
||||
Числа в протоколе little endian. Адреса внутри SCI8: сначала старшее 16-битное
|
||||
@@ -106,7 +143,7 @@ Python API: `protocan.can_boot.CanBootServices` — запросы и разбо
|
||||
## Аппаратная интеграция
|
||||
|
||||
MBOX3 — адресные входящие Boot; MBOX4 — ответы; MBOX6 — точный broadcast discovery.
|
||||
MBOX0..2 сохраняют legacy/UMP, MBOX5 остаётся heartbeat. ISR помещает сообщения
|
||||
MBOX0..2 сохраняют legacy/UMP, MBOX5 загрузчик не использует. ISR помещает сообщения
|
||||
в очередь на 31 кадр. Чужие адреса, RTR и неподходящие типы отбрасываются до очереди.
|
||||
При переполнении/потере mailbox сессия отменяется; повторная запись начинается заново.
|
||||
SPI-драйвер загрузчика имеет ограничение ожидания байта и WIP, 24-битный адрес,
|
||||
@@ -118,7 +155,31 @@ SPI-драйвер загрузчика имеет ограничение ожи
|
||||
Его RAM — 0xE000..0xFFFF; стек — 0x400..0x7FF. Приложение M95M02 использует
|
||||
0x8000..0xD7FF для кода, 0xD800..0xDFFF для констант/инициализации,
|
||||
0xE000..0xFFFF для .ebss после перехода в C runtime. Linker резервирует
|
||||
NOINIT handoff в обоих проектах. CAN не содержит операций записи внутренней Flash.
|
||||
NOINIT handoff в обоих проектах. TI Flash API временно использует RAM
|
||||
`0x8000..0x97FF` до запуска приложения. В обновлённом постоянном загрузчике
|
||||
CAN также записывает внутреннюю Flash приложения B–H; сектор A защищён.
|
||||
|
||||
## Внутренняя Flash по CAN
|
||||
|
||||
После ENTER_BOOT клиент явно отправляет SELECT_MEMORY (`0x10`, DLC=1,
|
||||
DATA[0]=1) до BEGIN_IMAGE/BEGIN_COMPAT. Новая сессия по умолчанию использует
|
||||
EEPROM A/B, поэтому старые клиенты сохраняют прежнее поведение. Выбор памяти
|
||||
после метаданных запрещён; старый boot отвечает INVALID_COMMAND до ERASE.
|
||||
CAPABILITIES bit 12 обозначает поддержку записи внутренней Flash.
|
||||
|
||||
Flash SCI8 с FAB1 передаётся в неактивный EEPROM-слот как staging. VERIFY
|
||||
проверяет CRC32 EEPROM, таблицу, непересекающиеся адреса только B–H и FAB1/CRC
|
||||
будущей Flash. COMMIT повторяет проверку staging, вызывает официальный TI API
|
||||
со стиранием `0x00FE`, пишет и проверяет данные порциями до 128 слов, публикует
|
||||
FAB1 последним и проверяет CRC физической Flash. ACK COMMIT приходит после
|
||||
записи; клиент даёт до 180 секунд и затем отправляет отдельный REBOOT.
|
||||
EEPROM active и параметры сохраняются; прежний неактивный образ заменяется staging.
|
||||
|
||||
В SETGUI: «Прошивка → CAN / ProtoCAN Boot → ProtoCAN: память прошивки →
|
||||
Внутренняя Flash F28335», файл `*_flash_rs.bin` существующего выпуска.
|
||||
Сначала требуется обновить постоянный `F28335_CAN_AB.out` через JTAG с маской
|
||||
только сектора A. В Debug/Release подключён установленный TI Flash API v2.10;
|
||||
его код и таблицы копируются в RAM перед занятостью общего банка Flash A–H.
|
||||
|
||||
## Первичная установка
|
||||
|
||||
@@ -126,10 +187,13 @@ NOINIT handoff в обоих проектах. CAN не содержит опе
|
||||
Старые BIN/OUT автоматически не заменены. Приложение должно содержать интеграцию
|
||||
READY/CONFIRM, иначе на следующем reset оно останется неподтверждённым кандидатом.
|
||||
2. Собрать отдельный загрузчик TI C2000 COFF compiler:
|
||||
`Bootloader/build.ps1 -CompilerRoot <путь-к-ti-cgt-c2000>`.
|
||||
Результат — `Bootloader/build/F28335_CAN_AB.out` и MAP.
|
||||
3. Один раз установить этот OUT через JTAG и выбрать аппаратный Flash boot
|
||||
согласно схеме платы. Не загружать поверх него старый application OUT с
|
||||
`python c/protocan-boot/projects/build.py --device f28335 --compiler <путь-к-ti-cgt-c2000>`.
|
||||
Результат — `projects/ccs/f28335/Debug/F28335_CAN_AB.out` и MAP.
|
||||
3. Установить обновлённый OUT через JTAG и выбрать аппаратный Flash boot
|
||||
согласно схеме платы. При переходе с общего адреса 3/7 обновить и приложение,
|
||||
и загрузчик: старый загрузчик не перейдёт на новый адрес после reset сам.
|
||||
В SETCAN выбрать «Прошивка → CAN / ProtoCAN Boot → Устройство PERIPH»
|
||||
и нужное назначение. Не загружать поверх загрузчика старый application OUT с
|
||||
секцией codestart во Flash.
|
||||
4. После reset пустая EEPROM или старая разметка автоматически ведут в CAN recovery.
|
||||
Передать новое приложение через ProtoCAN Boot, дождаться пробного запуска и
|
||||
@@ -145,8 +209,10 @@ NOINIT handoff в обоих проектах. CAN не содержит опе
|
||||
ядро, приложение/загрузчик, wide-octet режим, журнал, обрыв публикации на каждом
|
||||
из 69 возможных положений, пробный запуск, CONFIRM, откат, SCI8 и границы памяти.
|
||||
Python-тесты проверяют клиентские запросы, паспорт, фильтрацию ответов и лимит A/B.
|
||||
Проверка синтаксиса использует настоящие DSP2833x headers. Сборка TI/CCS,
|
||||
раскладка итогового MAP и физические CAN/SPI/reset на плате ещё не подтверждены.
|
||||
Проверка синтаксиса использует настоящие DSP2833x headers. Импорт и сборка TI/CCS,
|
||||
раскладка MAP и реальные COFF LOAD-адреса проверены; физические CAN/SPI/reset
|
||||
на плате требуют стендовой проверки. Отдельные проекты и команды сборки описаны
|
||||
в [инструкции CCS](../../projects/README.md).
|
||||
|
||||
CRC32 защищает от повреждения, криптографической подписи и anti-rollback по
|
||||
версии в этом порту нет. Удалённый CONFIRM подтверждает готовность приложения,
|
||||
@@ -154,3 +220,13 @@ CRC32 защищает от повреждения, криптографичес
|
||||
|
||||
Аппаратный формат SPI boot описан в [TI Boot ROM Reference Guide](https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/2742.Boot-ROM.pdf).
|
||||
В A/B-схеме ROM выбирает Flash, а разбор EEPROM выполняет этот загрузчик.
|
||||
|
||||
Проект предоставляет `f28335_can_application_config.h` в include paths.
|
||||
Он задаёт `F28335_CAN_BOOT_APPLICATION_ENABLED` (0/1) и при включённом модуле
|
||||
`F28335_CAN_BOOT_FIRMWARE_VERSION` из версии приложения. В 167 это ручной
|
||||
`firmware_version.h`; профиль включён только при M95M02 без `FLASH_BOOT`.
|
||||
Локальный `Source/Internal/can_boot.c` содержит только `F28335Boot_Quiesce`
|
||||
со штатной остановкой нагрузки. Общие `.c` повторно включать в него не нужно:
|
||||
они компилируются единственным linked resource общей библиотеки.
|
||||
Постоянный Flash-загрузчик по-прежнему собирается отдельным проектом
|
||||
`projects/ccs/f28335` и не линкуется в RAM-приложение.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef F28335_BOOT_PLATFORM_H
|
||||
#define F28335_BOOT_PLATFORM_H
|
||||
#include "f28335_boot_store.h"
|
||||
#include "f28335_flash_app.h" /* Общий handoff различает EEPROM A/B, защищённое Flash-приложение и неизвестный запуск. */
|
||||
#ifndef F28335_BOOT_LOADER
|
||||
#define F28335_BOOT_LOADER 0
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "f28335_can_application_config.h" /* Получает от проекта разрешение CAN A/B и версию приложения; этот конфигурационный заголовок должен находиться в include paths CCS. */
|
||||
#ifndef F28335_CAN_BOOT_APPLICATION_ENABLED /* Отсутствующее аппаратное решение нельзя трактовать как разрешение записи служебных областей EEPROM. */
|
||||
#error "Define F28335_CAN_BOOT_APPLICATION_ENABLED in f28335_can_application_config.h" /* Останавливает сборку до появления приложения с неполной интеграцией загрузчика. */
|
||||
#endif /* Завершает проверку обязательного конфигурационного признака проекта. */
|
||||
#if F28335_CAN_BOOT_APPLICATION_ENABLED /* Самостоятельный Flash-образ и платы без M95M02 исключают весь CAN A/B-код на этапе компиляции. */
|
||||
#include "../../src/pcan_boot.c" /* Компилирует единственный автомат команд ProtoCAN Boot с его штатными сессиями, CRC32 и проверкой последовательности пакетов. */
|
||||
#include "f28335_boot_store.c" /* Подключает общий A/B-журнал, readback, проверку SCI8 и выбор подтверждённого слота той же версии templates. */
|
||||
#include "f28335_boot_hw.c" /* Предоставляет SPI EEPROM, watchdog и согласованный handoff между приложением и постоянным Flash-загрузчиком. */
|
||||
#include "f28335_can_boot.c" /* В режиме приложения обслуживает вход в boot и READY/CONFIRM, сохраняя служебные mailbox 3/4/6 отдельно от технологического CAN. */
|
||||
#endif /* Постоянный загрузчик собирается отдельным CCS-проектом templates с F28335_BOOT_LOADER=1, а не этим прикладным модулем. */
|
||||
@@ -8,6 +8,21 @@
|
||||
* Сброс сессии не удаляет active/pending из EEPROM. */
|
||||
static pcan_boot_t boot;
|
||||
static f28335_boot_store_t store;
|
||||
static unsigned int healthy; /* Результат открытия EEPROM-журнала известен также функции выбора назначения Flash. */
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* Flash API доступен только постоянному загрузчику с явной поддержкой обновления B–H. */
|
||||
#include "f28335_flash_update.h" /* Подключает проверку Flash SCI8 и аппаратный writer с сохранением сектора A. */
|
||||
#include "f28335_flash_update.c" /* Общий алгоритм компилируется с тем же pcan_boot и разметкой, что этот порт. */
|
||||
static f28335_flash_update_t flash_update; /* Индекс и кеш занимают ограниченную внутреннюю RAM без загрузки приложения поверх boot. */
|
||||
static unsigned int flash_selected, flash_staging; /* Явная цель Flash использует только неактивный EEPROM-слот как временное хранилище. */
|
||||
static pcan_boot_status_t select_memory(void *u, pcan_boot_byte_t memory, pcan_boot_config_t *cfg) /* Выбирает назначение до BEGIN_IMAGE, сохраняя прежний EEPROM-путь по умолчанию. */
|
||||
{ /* Изменения конфигурации разрешены только при исправном EEPROM-журнале. */
|
||||
(void)u; if (!healthy) return PCAN_BOOT_STATUS_FLASH_ERROR; /* Ошибка чтения журнала запрещает выбор staging поверх неизвестного active. */
|
||||
if (memory > 1U) return PCAN_BOOT_STATUS_INVALID_COMMAND; /* Единственные определённые цели: 0=EEPROM A/B и 1=внутренняя Flash. */
|
||||
flash_selected = memory; flash_update.valid = false; /* Новая цель отменяет прежнее разрешение программирования. */
|
||||
cfg->slot_count = memory ? 1U : 2U; cfg->active_slot = memory ? 0U : store.active; /* CAN Flash использует один логический слот A, EEPROM сохраняет выбор неактивного A/B. */
|
||||
return PCAN_BOOT_STATUS_OK; /* Физический staging будет инвалидирован лишь при последующей команде ERASE. */
|
||||
} /* Никакие данные Flash или EEPROM при выборе цели не изменяются. */
|
||||
#endif /* Приложение и старые host-модели не подключают Flash API. */
|
||||
/* Кольцевая очередь: ISR производит кадры, main потребляет. Из 32 элементов
|
||||
* используется 31, чтобы head==tail однозначно означало пустую очередь.
|
||||
* Долгие операции SPI запрещены внутри обработчика CAN. */
|
||||
@@ -16,9 +31,10 @@ static struct { uint32_t id; unsigned int dlc; pcan_boot_byte_t data[8]; } queue
|
||||
/* reset_requested только планирует reset; Service ждёт завершения TX.
|
||||
* ready сообщает об окончании старта приложения, confirmed — о сохранённом
|
||||
* подтверждении слота. healthy отражает результат открытия журнала при Init. */
|
||||
static unsigned int reset_requested,reset_session,ready,healthy,confirmed;
|
||||
static unsigned int reset_requested,reset_session,ready,confirmed; /* Состояние перехода и подтверждения приложения отделено от доступности EEPROM. */
|
||||
static uint32_t sent_at,ready_at;
|
||||
static unsigned int main_passes;
|
||||
static unsigned int addressed; /* Разрешает обслуживание только после проверки номера PERIPH и установки согласованных фильтров CAN. */
|
||||
static int tx_busy,tx_canceling;
|
||||
/* Один исходящий mailbox исключает перезапись ещё передаваемого ответа.
|
||||
* MDL содержит первые четыре октета, MDH — следующие четыре, младшим вперёд.
|
||||
@@ -48,9 +64,19 @@ static bool transmit(void *u, uint32_t id, const pcan_boot_byte_t *d, pcan_boot_
|
||||
* эти callbacks возвращают отказ, даже если им удастся передать команду записи.
|
||||
* ERASE для EEPROM означает инвалидирование manifest выбранного слота. */
|
||||
static bool erase(void *u,pcan_boot_byte_t slot)
|
||||
{ (void)u; return F28335_BOOT_LOADER && healthy && f28335_boot_prepare(&store,slot); }
|
||||
{ /* ERASE подготавливает staging; внутренняя Flash остаётся неизменной до VERIFY и COMMIT. */
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* Новая цель не меняет прежний формат EEPROM A/B. */
|
||||
if (flash_selected) { flash_update.valid = false; flash_staging = store.active == 0U ? 1U : 0U; return healthy && f28335_boot_prepare(&store, flash_staging); } /* Инвалидирует только неактивный слот, сохраняя подтверждённый резерв и параметры. */
|
||||
#endif /* В остальных сборках остаётся штатная подготовка EEPROM-слота. */
|
||||
(void)u; return F28335_BOOT_LOADER && healthy && f28335_boot_prepare(&store,slot); /* Обычный CAN-клиент сохраняет прежний путь обновления RAM-приложения. */
|
||||
} /* Подготовка не вызывает TI Flash_Erase. */
|
||||
static bool write_block(void *u,pcan_boot_byte_t slot,uint32_t offset,const pcan_boot_byte_t *d,pcan_boot_byte_t n)
|
||||
{ (void)u; return F28335_BOOT_LOADER && healthy && f28335_boot_write(&store,slot,offset,d,n); }
|
||||
{ /* CAN ISR только ставит данные в очередь; запись staging выполняет main. */
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* Запись Flash-файла использует тот же проверенный EEPROM writer. */
|
||||
if (flash_selected) return healthy && f28335_boot_write(&store, flash_staging, offset, d, n); /* Логический DATA_A направляется в выбранный неактивный физический слот. */
|
||||
#endif /* Обычные A/B-данные сохраняют исходную адресацию. */
|
||||
(void)u; return F28335_BOOT_LOADER && healthy && f28335_boot_write(&store,slot,offset,d,n); /* Не допускает записи из прикладной сборки. */
|
||||
} /* Внутренняя Flash ещё не затронута. */
|
||||
/* Проверка включает CRC EEPROM и структуру SCI8. Сейчас отказ этого слоя
|
||||
* кодируется CRC_ERROR как общий отказ проверки образа; причины внутри
|
||||
* парсера SCI8 отдельными статусами протокола не различаются. */
|
||||
@@ -58,10 +84,21 @@ static pcan_boot_status_t verify(void *u,pcan_boot_byte_t slot,const pcan_boot_m
|
||||
{
|
||||
(void)u;
|
||||
if(!F28335_BOOT_LOADER || !healthy) return PCAN_BOOT_STATUS_INVALID_STATE;
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* Для внутренней Flash нужен собственный допустимый диапазон SCI8 и обязательный FAB1. */
|
||||
if (flash_selected) return f28335_flash_update_validate(&flash_update, &store.io, flash_staging ? F28335_AB_SLOT_B : F28335_AB_SLOT_A, m) ? PCAN_BOOT_STATUS_OK : PCAN_BOOT_STATUS_CRC_ERROR; /* Повторно читает EEPROM и проверяет транспортную CRC, таблицу и CRC будущей Flash до erase. */
|
||||
#endif /* RAM SCI8 проходит прежнюю проверку приложения EEPROM. */
|
||||
return f28335_boot_verify(&store,slot,m,0)?PCAN_BOOT_STATUS_OK:PCAN_BOOT_STATUS_CRC_ERROR;
|
||||
}
|
||||
static bool commit(void *u,pcan_boot_byte_t slot,const pcan_boot_manifest_t *m)
|
||||
{ (void)u; return F28335_BOOT_LOADER && healthy && f28335_boot_commit(&store,slot,m); }
|
||||
{ /* COMMIT выполняет фактическую запись только после подтверждённой проверки образа. */
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* Постоянный boot остаётся вне обновляемых секторов B–H. */
|
||||
if (flash_selected) { /* Синхронный TI API может работать дольше обычного интервала CAN, не создавая pending EEPROM. */
|
||||
bool result = healthy && F28335Boot_FlashProgram(&flash_update); /* Итог зависит от erase, каждой порции readback и полной CRC физической Flash. */
|
||||
boot.now_ms = F28335Boot_Now(); boot.last_activity_ms = boot.now_ms; return result; /* Обновляет срок сессии после аппаратной операции, чтобы штатный REBOOT не был отклонён из-за времени записи. */
|
||||
} /* Ошибка записи оставляет постоянный boot доступным для нового сеанса. */
|
||||
#endif /* Обычное обновление EEPROM сохраняет trial/CONFIRM. */
|
||||
(void)u; return F28335_BOOT_LOADER && healthy && f28335_boot_commit(&store,slot,m); /* Публикует только RAM-образ в исходном журнале A/B. */
|
||||
} /* Итоговый статус и отдельный REBOOT отправляет существующее ядро ProtoCAN. */
|
||||
/* Подтверждение принадлежит приложению после READY. Загрузчик не может
|
||||
* подтвердить кандидата сам: иначе исчезнет смысл проверки пробного запуска.
|
||||
* Разрешение кормления watchdog из ISR открываем только после записи журнала. */
|
||||
@@ -82,9 +119,14 @@ static unsigned int enter(void *u,pcan_boot_byte_t session)
|
||||
{
|
||||
(void)u;
|
||||
if(!healthy) return 2;
|
||||
if(F28335_BOOT_LOADER) return 0;
|
||||
if(F28335_BOOT_LOADER) { /* Постоянный загрузчик открывает сессию без дополнительного reset. */
|
||||
#if F28335_CAN_FLASH_UPDATE /* Каждая новая сессия должна начинаться со штатного EEPROM-назначения. */
|
||||
if (boot.state == PCAN_BOOT_STATE_IDLE) (void)select_memory(0, 0U, &boot.config); /* Повторный ENTER текущей сессии не меняет уже выбранную Flash. */
|
||||
#endif /* Старые сборки не используют переключение назначения. */
|
||||
return 0; /* Ядро отправит адресный ACK готовности. */
|
||||
} /* Прикладной handoff проверяется ниже. */
|
||||
/* No destructive fallback on boards still starting through the SPI ROM. */
|
||||
if(F28335Boot_RunningSlot()>1 || !confirmed) return 2;
|
||||
if((F28335Boot_RunningSlot()>1 && F28335Boot_RunningSlot()!=F28335_BOOT_FLASH_SLOT) || !confirmed) return 2; /* Только handoff общего загрузчика разрешает переход из EEPROM либо защищённой внутренней Flash; старый SPI-ROM старт остаётся запрещён. */
|
||||
reset_session=session; reset_requested=1; return 1;
|
||||
}
|
||||
static void info32(pcan_boot_byte_t *p,uint32_t v)
|
||||
@@ -95,18 +137,21 @@ static void info32(pcan_boot_byte_t *p,uint32_t v)
|
||||
* 2 — active/pending/attempted/healthy/тайм-аут, 3 — область параметров. */
|
||||
static bool info(void *u,pcan_boot_byte_t command,pcan_boot_byte_t page,pcan_boot_byte_t *out)
|
||||
{
|
||||
static const char name[]=F28335_CAN_BOOT_DEVICE_NAME;
|
||||
unsigned int i,index; (void)u;
|
||||
const char *name=boot.config.device_type==1U && boot.config.device_id==8U?"Zadatchik":boot.config.device_type==1U && boot.config.device_id==5U?"UMP1":boot.config.device_type==1U && boot.config.device_id==6U?"UMP2":F28335_CAN_BOOT_DEVICE_NAME; /* Паспорт различает три назначенных Excel устройства; резервные номера сохраняют аппаратное имя. */
|
||||
unsigned int i,index,name_size=(unsigned int)strlen(name)+1U; (void)u; /* Длина включает завершающий NUL, чтобы последняя страница имени однозначно завершала чтение. */
|
||||
if(command==PCAN_BOOT_CMD_CAPABILITIES && page==0) {
|
||||
/* bits: ping, discovery, identity, name, memory, A/B, confirm, rollback,
|
||||
* separate loader, session timeout, readback, SCI8 validation. */
|
||||
info32(out,(F28335_BOOT_LOADER || F28335Boot_RunningSlot()<2)?0xFFFUL:0x1FUL);
|
||||
info32(out+4,F28335_AB_SLOT_BYTES); return true;
|
||||
info32(out,(F28335_BOOT_LOADER || F28335Boot_RunningSlot()<2 || F28335Boot_RunningSlot()==F28335_BOOT_FLASH_SLOT)?0xFFFUL:0x1FUL); /* Flash-приложение с достоверным handoff поддерживает вход в постоянный CAN Boot так же, как подтверждённый EEPROM-образ. */
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* Дополнительный бит сообщает клиенту поддержку явной внутренней Flash. */
|
||||
out[1] |= 0x10U; /* Бит 12 общего little-endian capability word означает SELECT_MEMORY и запись B–H. */
|
||||
#endif /* Старые приложения продолжают сообщать прежние возможности. */
|
||||
info32(out+4,F28335_AB_SLOT_BYTES); return true; /* Максимальная длина одинакова для staging Flash и EEPROM A/B. */
|
||||
}
|
||||
if(command==PCAN_BOOT_CMD_DEVICE_NAME) {
|
||||
if((unsigned int)page*8U>=sizeof(name)) return false;
|
||||
if((unsigned int)page*8U>=name_size) return false; /* Страница после конца выбранного имени не является допустимой частью паспорта. */
|
||||
for(i=0;i<8;++i) { index=(unsigned int)page*8U+i;
|
||||
out[i]=index<sizeof(name)?(pcan_boot_byte_t)name[index]:0; }
|
||||
out[i]=index<name_size?(pcan_boot_byte_t)name[index]:0; } /* Дополняет последнюю восьмибайтовую страницу нулями без выхода за строку. */
|
||||
return true;
|
||||
}
|
||||
if(command!=PCAN_BOOT_CMD_MEMORY_INFO) return false;
|
||||
@@ -124,14 +169,16 @@ void F28335CanBoot_EarlyInit(void) { confirmed=0; ready=0; }
|
||||
/* Общий Init для приложения и загрузчика: открываем журнал, привязываем
|
||||
* callbacks, задаём идентификацию, ёмкость слота, окно 16 и тайм-аут 30 секунд.
|
||||
* В загрузчике FW берётся из active manifest; приложение сообщает версию сборки. */
|
||||
void F28335CanBoot_Init(void)
|
||||
void F28335CanBoot_Init(unsigned int periph_id) /* Один номер платы преобразуется одинаково в приложении и постоянном загрузчике. */
|
||||
{
|
||||
pcan_boot_config_t cfg; pcan_boot_port_t port;
|
||||
f28335_boot_io_t io; unsigned int running=F28335Boot_RunningSlot();
|
||||
addressed=0U; EALLOW; ECanaRegs.CANME.all&=~88UL; EDIS; /* Закрывает только Boot mailbox 3/4/6 до проверки адреса, включая повторный Init с ошибочным номером. */
|
||||
if(periph_id>=F28335_CAN_BOOT_PERIPH_COUNT) return; /* Номер вне Excel-диапазона 0–31 не подменяется общим адресом и не открывает запись другой платы. */
|
||||
memset(&cfg,0,sizeof(cfg)); memset(&port,0,sizeof(port));
|
||||
io.read=F28335Boot_Read; io.write=F28335Boot_Write; io.user=0;
|
||||
healthy=f28335_boot_open(&store,&io);
|
||||
cfg.device_type=F28335_CAN_BOOT_DEVICE_TYPE; cfg.device_id=F28335_CAN_BOOT_DEVICE_ID;
|
||||
cfg.device_type=1U+periph_id/16U; cfg.device_id=periph_id%16U; /* Excel: PERIPH 0–15 → Type 1, 16–31 → Type 2; младшие четыре бита задают Device ID. */
|
||||
cfg.product_type=F28335_CAN_BOOT_PRODUCT; cfg.hardware_revision=1;
|
||||
#if F28335_BOOT_LOADER
|
||||
cfg.firmware_version=store.active<2?store.image[store.active].firmware_version:0;
|
||||
@@ -139,15 +186,20 @@ void F28335CanBoot_Init(void)
|
||||
cfg.firmware_version=F28335_CAN_BOOT_FIRMWARE_VERSION;
|
||||
#endif
|
||||
head=tail=overflow=reset_requested=reset_session=ready=main_passes=0; tx_busy=tx_canceling=0;
|
||||
confirmed=healthy && running<2 && store.active==running && store.pending==F28335_AB_NONE;
|
||||
confirmed=running==F28335_BOOT_FLASH_SLOT || (healthy && running<2 && store.active==running && store.pending==F28335_AB_NONE); /* Flash уже проверена CRC постоянным boot; пробное подтверждение требуется только EEPROM-кандидату. */
|
||||
cfg.active_slot=store.active;
|
||||
cfg.slot_count=2; cfg.max_image_size=F28335_AB_SLOT_BYTES; cfg.ack_window=16;
|
||||
cfg.session_timeout_ms=30000UL;
|
||||
#if F28335_BOOT_LOADER && F28335_CAN_FLASH_UPDATE /* После reset никакое случайное содержимое RAM не выбирает внутреннюю Flash. */
|
||||
flash_selected = 0U; flash_staging = F28335_AB_NONE; flash_update.valid = false; /* Возвращает исходную цель и отменяет разрешение записи предыдущей сессии. */
|
||||
port.select_memory = select_memory; /* Новая команда доступна только сборке с реально подключённым TI API. */
|
||||
#endif /* Приложение отвечает только через постоянный загрузчик после handoff. */
|
||||
port.send=transmit; port.erase_slot=erase; port.write_slot=write_block;
|
||||
port.verify_status=verify; port.set_pending_slot=commit; port.reboot=reboot;
|
||||
port.confirm_running_slot=confirm; port.enter_boot=enter;
|
||||
port.can_reboot=can_reboot; port.service_info=info;
|
||||
if(!pcan_boot_init(&boot,&cfg,&port,0)) return;
|
||||
addressed=1U; /* Дальнейшие ISR, основной цикл и handoff используют только успешно созданную адресную конфигурацию. */
|
||||
EALLOW;
|
||||
/* Меняем только MBOX3/4/6: маска 88=8+16+64. MBOX0..2 — старый обмен,
|
||||
* MBOX5 — heartbeat. Приём broadcast выделен в отдельный точный mailbox,
|
||||
@@ -181,8 +233,8 @@ static void receive_box(volatile struct MBOX *box,uint32_t mask)
|
||||
type=pcan_boot_id_msg_type(id);
|
||||
if(!(box->MSGID.all&0x80000000UL) || pcan_boot_id_route(id)!=0 ||
|
||||
(type!=9 && type!=10 && type!=11 && type!=13) ||
|
||||
!((pcan_boot_id_device_type(id)==F28335_CAN_BOOT_DEVICE_TYPE &&
|
||||
pcan_boot_id_device_id(id)==F28335_CAN_BOOT_DEVICE_ID) ||
|
||||
!((pcan_boot_id_device_type(id)==boot.config.device_type && /* Сравнивает тип именно этой платы, а не прежнюю общую константу 3. */
|
||||
pcan_boot_id_device_id(id)==boot.config.device_id) || /* Отбрасывает команды соседних PERIPH ещё до очереди и любых операций EEPROM. */
|
||||
(type==13 && pcan_boot_id_device_type(id)==7 && pcan_boot_id_device_id(id)==15 &&
|
||||
pcan_boot_id_msg_body(id)==0))) { ECanaRegs.CANRMP.all=mask; return; }
|
||||
if(next==tail) overflow=1;
|
||||
@@ -199,6 +251,7 @@ static void receive_box(volatile struct MBOX *box,uint32_t mask)
|
||||
|
||||
void F28335CanBoot_RxISR(void)
|
||||
{
|
||||
if(!addressed) return; /* Неверный или ещё не настроенный номер PERIPH не должен принимать даже оставшиеся флаги RX. */
|
||||
receive_box(&ECanaMboxes.MBOX3,8UL);
|
||||
receive_box(&ECanaMboxes.MBOX6,64UL);
|
||||
}
|
||||
@@ -214,9 +267,11 @@ unsigned int F28335CanBoot_WatchdogAllowed(void)
|
||||
/* Неблокирующий диспетчер относительно ожидания CAN: вызывать в каждом проходе main.
|
||||
* Сами callbacks проверки/записи EEPROM синхронные. Порядок здесь важен:
|
||||
* проба приложения -> завершение TX -> reset -> poll -> ошибки RX -> один кадр. */
|
||||
unsigned int F28335CanBoot_Active(void) { return addressed && (boot.state!=PCAN_BOOT_STATE_IDLE || reset_requested); } /* Открытый ENTER_BOOT удерживает recovery; диагностический PING не меняет приоритет Flash и EEPROM. */
|
||||
void F28335CanBoot_Service(void)
|
||||
{
|
||||
uint32_t now=F28335Boot_Now();
|
||||
if(!addressed) return; /* Не обслуживает старую RAM-сессию после отказа повторной инициализации адреса. */
|
||||
if(!F28335_BOOT_LOADER && ready && !confirmed && healthy && F28335Boot_RunningSlot()<2) {
|
||||
/* A trial must keep executing main, not merely a timer ISR. */
|
||||
/* После 100 проходов main и 5 секунд пробуем сохранить CONFIRM.
|
||||
@@ -261,15 +316,16 @@ void F28335CanBoot_Service(void)
|
||||
* или CRC незавершённой передачи: данные сессии через reset не сохраняются. */
|
||||
void F28335CanBoot_Resume(unsigned int session)
|
||||
{
|
||||
if(F28335_BOOT_LOADER && session && session<256)
|
||||
(void)pcan_boot_process(&boot,pcan_boot_make_id(1,0,
|
||||
F28335_CAN_BOOT_DEVICE_TYPE,F28335_CAN_BOOT_DEVICE_ID,9,(session<<8)|2),0,0);
|
||||
if(addressed && F28335_BOOT_LOADER && session && session<256) /* Восстанавливает только допустимую сессию адресованного загрузчика после reset. */
|
||||
(void)pcan_boot_process(&boot,pcan_boot_make_id(1,0, /* ACK относится к тому же физическому PERIPH, который принимал ENTER_BOOT в приложении. */
|
||||
boot.config.device_type,boot.config.device_id,9,(session<<8)|2),0,0); /* MsgType 9, команда 2 и исходный SessionID сохраняют протокол handoff. */
|
||||
}
|
||||
#else
|
||||
void F28335CanBoot_EarlyInit(void) {}
|
||||
void F28335CanBoot_Init(void) {}
|
||||
void F28335CanBoot_Init(unsigned int periph_id) { (void)periph_id; } /* Сборка без M95M02 не занимает CAN-адрес и не открывает сервис записи. */
|
||||
void F28335CanBoot_RxISR(void) {}
|
||||
void F28335CanBoot_Service(void) {}
|
||||
unsigned int F28335CanBoot_Active(void) { return 0U; } /* Профиль без M95M02 не создаёт CAN-сеанс и не удерживает старт общего загрузчика. */
|
||||
void F28335CanBoot_Ready(void) {}
|
||||
unsigned int F28335CanBoot_WatchdogAllowed(void) { return 1; }
|
||||
void F28335CanBoot_Resume(unsigned int session) { (void)session; }
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
#endif
|
||||
/* Адрес ProtoCAN состоит из Device Type (3 бита) и Device ID (4 бита).
|
||||
* ProductType — отдельный код совместимости прошивки; это не CAN ID и не RS-адрес. */
|
||||
#define F28335_CAN_BOOT_DEVICE_TYPE 3U
|
||||
#define F28335_CAN_BOOT_DEVICE_ID 7U
|
||||
#define F28335_CAN_BOOT_PERIPH_COUNT 32U /* Лист «Интерфейс протокола», строки 45–76: PERIPH 0–31 занимают два типа по 16 экземпляров. */
|
||||
#define F28335_CAN_BOOT_PRODUCT 0x2833U
|
||||
#define F28335_CAN_BOOT_DEVICE_NAME "F28335-M95M02"
|
||||
/* Порядок интеграции приложения:
|
||||
@@ -18,10 +17,11 @@
|
||||
* таймера и EEPROM; Ready после старта прикладных подсистем; Service в main.
|
||||
* RxISR вызывается из CAN ISR, WatchdogAllowed проверяется перед кормлением
|
||||
* watchdog таймерным ISR. Resume применяется только отдельным загрузчиком. */
|
||||
void F28335CanBoot_Init(void);
|
||||
void F28335CanBoot_Init(unsigned int periph_id); /* Принимает физический номер PERIPH: 5 — УМП1, 6 — УМП2, 8 — задатчик; общий адрес для всех плат исключён. */
|
||||
void F28335CanBoot_EarlyInit(void);
|
||||
void F28335CanBoot_RxISR(void);
|
||||
void F28335CanBoot_Service(void);
|
||||
unsigned int F28335CanBoot_Active(void); /* Удерживает загрузчик в CAN recovery после ENTER_BOOT, не запуская приложение по окончании стартового окна. */
|
||||
void F28335CanBoot_Ready(void);
|
||||
void F28335CanBoot_Resume(unsigned int session);
|
||||
unsigned int F28335CanBoot_WatchdogAllowed(void);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "f28335_flash_app.h" /* Использует ту же границу сектора A и формат описания, что сборщик и RS-программатор. */
|
||||
bool f28335_flash_app_validate(f28335_flash_read_word_t read_word, void *user, uint32_t *entry) /* Не обращается к EEPROM и подходит для постоянного загрузчика и проверки staging RAM. */
|
||||
{ /* Никакие адреса из непроверенного заголовка не используются для чтения до проверки границ. */
|
||||
uint16_t header[F28335_FLASH_APP_HEADER_WORDS], word, octet, bit, i; /* Малый локальный буфер хранит 16 слов описания FAB1. */
|
||||
uint32_t address, start, end, expected, crc = 0xFFFFFFFFUL, target, inverse; /* CRC32 IEEE начинается со всех единиц и инвертируется после последнего октета. */
|
||||
if (!read_word || !entry) return false; /* Отсутствующий источник или выходной указатель не должен вызывать обращение к памяти. */
|
||||
for (i = 0; i < F28335_FLASH_APP_HEADER_WORDS; ++i) header[i] = read_word(user, F28335_FLASH_APP_START + i); /* Читает только фиксированное описание в секторе H. */
|
||||
if (header[0] != 0x4146U || header[1] != 0x3142U || header[2] != 1U || header[3] != F28335_FLASH_APP_HEADER_WORDS || header[14] != 0x5AA5U || header[15] != 0xA55AU) return false; /* Физические октеты ASCII FAB1, версия 1, размер и два маркера отличают завершённый образ от стёртого либо старого Flash. */
|
||||
target = (uint32_t)header[4] | ((uint32_t)header[5] << 16); /* Точка входа хранится младшим 16-битным словом вперёд внутри описания. */
|
||||
start = (uint32_t)header[6] | ((uint32_t)header[7] << 16); /* Нижняя граница защищённого CRC диапазона должна начинаться сразу после описания. */
|
||||
end = (uint32_t)header[8] | ((uint32_t)header[9] << 16); /* Верхняя граница является исключённым адресом слова, а не длиной в байтах. */
|
||||
expected = (uint32_t)header[10] | ((uint32_t)header[11] << 16); /* Сохранённая CRC32 рассчитана по физическим октетам всех слов диапазона. */
|
||||
inverse = (uint32_t)header[12] | ((uint32_t)header[13] << 16); /* Инверсия адреса выявляет частичную публикацию управляющих полей. */
|
||||
if (start != F28335_FLASH_APP_DATA || end <= start || end > F28335_FLASH_APP_STOP || target < start || target >= end || inverse != ~target) return false; /* Запрещает RAM, сектор загрузчика, пустой код и случайные адреса из повреждённого описания. */
|
||||
for (address = start; address < end; ++address) { /* Проверяет также стёртые промежутки между LOAD-секциями, чтобы JTAG и RS давали одинаковое содержимое. */
|
||||
word = read_word(user, address); /* Получает одно 16-битное слово из Flash либо из модели staging SCI8. */
|
||||
for (i = 0; i < 2U; ++i) { /* Каждый адрес C28x содержит два физических октета: сначала младший, затем старший. */
|
||||
octet = (word >> (8U * i)) & 255U; /* Маска отделяет октет независимо от 16-битного char TI. */
|
||||
crc ^= octet; /* Добавляет очередной октет в отражённое состояние CRC32 IEEE. */
|
||||
for (bit = 0; bit < 8U; ++bit) crc = (crc & 1UL) ? ((crc >> 1) ^ 0xEDB88320UL) : (crc >> 1); /* 0xEDB88320 — отражённый полином IEEE 802.3, совпадающий с zlib.crc32. */
|
||||
} /* Завершает обработку обоих октетов текущего слова. */
|
||||
} /* Завершает чтение только внутри области приложения ниже сектора A. */
|
||||
if ((crc ^ 0xFFFFFFFFUL) != expected) return false; /* Повреждённое или частично записанное приложение остаётся недоступным для запуска. */
|
||||
*entry = target; /* Публикует точку старта только после подтверждения всех адресов и данных. */
|
||||
return true; /* Разрешает загрузчику запустить именно проверенную Flash-программу. */
|
||||
} /* Ошибка никогда не меняет EEPROM, Flash или сохранённый выходной адрес. */
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef F28335_FLASH_APP_H /* Защищает общий контракт Flash-приложения от повторного объявления. */
|
||||
#define F28335_FLASH_APP_H /* Один заголовок используется загрузчиком, RS-проверкой и host-тестами. */
|
||||
#include "../../include/pcan_boot.h" /* Получает переносимые 16- и 32-битные типы и bool для C28x и ПК. */
|
||||
#define F28335_FLASH_APP_START 0x300000UL /* Первые 16 слов сектора H содержат описание FAB1, а не аппаратный boot. */
|
||||
#define F28335_FLASH_APP_HEADER_WORDS 16U /* Размер описания равен 32 октетам при 16-битном адресуемом слове C28x. */
|
||||
#define F28335_FLASH_APP_DATA 0x300010UL /* Код и Flash LOAD-секции следуют после служебного описания. */
|
||||
#define F28335_FLASH_APP_STOP 0x338000UL /* Начало сектора A является исключённой границей приложения. */
|
||||
#define F28335_BOOT_FLASH_SLOT 0xFEU /* Отдельный handoff отличает внутреннюю Flash от EEPROM A/B и неизвестного SPI-ROM запуска. */
|
||||
typedef uint16_t (*f28335_flash_read_word_t)(void *user, uint32_t address); /* Callback читает одно физическое слово без предположения о памяти host-тестов. */
|
||||
bool f28335_flash_app_validate(f28335_flash_read_word_t read_word, void *user, uint32_t *entry); /* Проверяет описание, границы и CRC32 до передачи управления приложению. */
|
||||
#endif /* Завершает единый контракт защищённой области Flash-приложения. */
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "f28335_flash_update.h" /* Разделяет проверяемый алгоритм и аппаратные вызовы TI Flash API. */
|
||||
#include <string.h> /* Явно очищает состояние источника перед разбором нового SCI8. */
|
||||
static unsigned int octet(f28335_flash_update_t *s, uint32_t offset) /* Читает октет через страничный кеш, исключая SPI-транзакцию на каждый байт CRC. */
|
||||
{ /* Все смещения ограничены фактической длиной принятого файла. */
|
||||
if (offset >= s->length) { s->fault = true; return 0U; } /* Обрезанное поле не превращается в данные за концом staging. */
|
||||
if (!s->cache_size || offset < s->cache_at || offset - s->cache_at >= s->cache_size) { /* Загружает новую страницу только при выходе за текущую. */
|
||||
s->cache_at = offset & ~255UL; /* Выравнивает смещение на страницу из 256 физических октетов. */
|
||||
s->cache_size = s->length - s->cache_at > 256UL ? 256U : (unsigned int)(s->length - s->cache_at); /* Последнее чтение не включает паддинг CAN за концом образа. */
|
||||
if (!s->io.read(s->io.user, s->base + s->cache_at, s->cache, s->cache_size)) { s->fault = true; s->cache_size = 0U; return 0U; } /* Любой неполный аппаратный обмен запрещает erase. */
|
||||
} /* После заполнения кеша извлечение октета не обращается к SPI. */
|
||||
return s->cache[offset - s->cache_at] & 255U; /* Маска сохраняет восьмибитный wire-формат на C28x. */
|
||||
} /* Завершает ограниченное чтение октета. */
|
||||
static uint16_t word(f28335_flash_update_t *s, uint32_t offset) /* SCI8 передаёт младший октет каждого 16-битного слова первым. */
|
||||
{ /* Объединяет два октета только через проверяемый источник. */
|
||||
unsigned int low = octet(s, offset); /* Явный порядок вызовов не зависит от порядка вычисления операндов компилятором. */
|
||||
return (uint16_t)(low | (octet(s, offset + 1UL) << 8)); /* Восстанавливает одно слово CPU из двух октетов SCI8. */
|
||||
} /* Завершает декодирование слова. */
|
||||
static uint32_t address_at(f28335_flash_update_t *s, uint32_t offset) /* Адрес таблицы TI содержит старшее слово перед младшим. */
|
||||
{ /* Порядок слов адреса отличается от порядка октетов внутри слова. */
|
||||
uint32_t high = word(s, offset); /* Читает старшие 16 бит адреса раньше младших. */
|
||||
return (high << 16) | word(s, offset + 2UL); /* Получает CPU word-address без перевода в байты. */
|
||||
} /* Завершает восстановление адреса SCI8. */
|
||||
static uint16_t image_word(void *user, uint32_t address) /* Предоставляет общему валидатору будущий вид Flash, включая стёртые промежутки. */
|
||||
{ /* Отсортированный индекс позволяет проверять весь CRC-диапазон последовательно. */
|
||||
f28335_flash_update_t *s = user; f28335_flash_section_t *p; /* Контекст содержит только предварительно проверенные секции. */
|
||||
if (s->cursor >= s->count || address < s->section[s->cursor].address) s->cursor = 0U; /* Возврат от заголовка к началу диапазона корректно перематывает индекс. */
|
||||
while (s->cursor < s->count) { /* Пропускает только секции, целиком лежащие перед запрошенным словом. */
|
||||
p = &s->section[s->cursor]; /* Обращается к существующему элементу проверенного индекса. */
|
||||
if (address < p->address) return 0xFFFFU; /* Flash_Erase оставляет незагружаемый промежуток заполненным единицами. */
|
||||
if (address - p->address < p->words) return word(s, p->offset + 2UL * (address - p->address)); /* Переводит смещение слов секции в октеты SCI8. */
|
||||
++s->cursor; /* Следующий запрос не должен повторно сканировать уже пройденную секцию. */
|
||||
} /* После последней секции остаётся только стёртая Flash. */
|
||||
return 0xFFFFU; /* CRC учитывает также завершающий промежуток диапазона FAB1. */
|
||||
} /* Сам этот callback никогда не читает аппаратную Flash. */
|
||||
bool f28335_flash_update_validate(f28335_flash_update_t *s, const f28335_boot_io_t *io, uint32_t base, const pcan_boot_manifest_t *m) /* Проверяет транспорт, таблицу, допустимые адреса и FAB1 перед erase. */
|
||||
{ /* Любая ошибка оставляет объект непригодным для программирования. */
|
||||
uint32_t offset = 22UL, crc = 0UL, entry, checked_entry, bytes; unsigned int i, j, headers = 0U, have_entry = 0U; /* Заголовок SCI8 занимает 11 слов, то есть 22 октета. */
|
||||
f28335_flash_section_t p; bool ended = false; /* Временная секция нужна для вставки в отсортированный индекс. */
|
||||
if (!s || !io || !io->read || !m) return false; /* Не разыменовывает отсутствующие callbacks и manifest. */
|
||||
memset(s, 0, sizeof(*s)); s->io = *io; s->base = base; s->length = m->image_size; s->crc = m->image_crc32; /* Отбрасывает кеш и разрешение записи предыдущего образа. */
|
||||
if (s->length < 24UL || (s->length & 1UL) || s->length > F28335_AB_SLOT_BYTES || word(s, 0UL) != 0x08AAU) return false; /* Принимает только полный чётный SCI8 в пределах staging-слота. */
|
||||
for (offset = 0UL; offset < s->length; offset += bytes) { /* Независимо проверяет фактически записанную EEPROM, а не только принятые CAN-кадры. */
|
||||
bytes = s->length - offset > 256UL ? 256UL : s->length - offset; /* Делит чтение на ограниченные страницы без выхода за файл. */
|
||||
if (!s->io.read(s->io.user, base + offset, s->cache, (unsigned int)bytes)) return false; /* Аппаратная ошибка запрещает последующий erase. */
|
||||
crc = pcan_boot_crc32_update(crc, s->cache, (size_t)bytes); /* Использует общий CRC32 IEEE, совпадающий с клиентом SETGUI. */
|
||||
} /* Все октеты staging включены в транспортную CRC32. */
|
||||
s->cache_size = 0U; if (crc != s->crc) return false; /* Сбрасывает кеш после прямого чтения и отклоняет повреждённую EEPROM. */
|
||||
entry = address_at(s, 18UL); offset = 22UL; /* Точка входа следует после ключа и восьми резервных слов SCI8. */
|
||||
if (entry < F28335_FLASH_APP_DATA || entry >= F28335_FLASH_APP_STOP) return false; /* Запуск разрешён только из приложения ниже постоянного сектора A. */
|
||||
while (offset + 2UL <= s->length) { /* Для каждой секции сначала проверяет наличие поля длины. */
|
||||
p.words = word(s, offset); offset += 2UL; /* Длина секции выражена адресуемыми словами C28x. */
|
||||
if (!p.words) { ended = offset == s->length; break; } /* Нулевой терминатор обязан завершать файл без лишнего хвоста. */
|
||||
if (s->count == F28335_AB_MAX_SECTIONS || offset + 4UL > s->length) return false; /* Не допускает переполнение индекса либо обрезанный адрес секции. */
|
||||
p.address = address_at(s, offset); offset += 4UL; p.offset = offset; bytes = 2UL * p.words; /* Хранит CPU-адрес и байтовое смещение полезных данных отдельно. */
|
||||
if (bytes > s->length - offset || p.address < F28335_FLASH_APP_START || p.address >= F28335_FLASH_APP_STOP || p.words > F28335_FLASH_APP_STOP - p.address) return false; /* Исключает RAM, сектор A, CSM, OTP и выход за конец staging. */
|
||||
if (p.address == F28335_FLASH_APP_START) { if (p.words < F28335_FLASH_APP_HEADER_WORDS) return false; ++headers; } /* Полные 16 слов FAB1 должны публиковаться одной заключительной операцией. */
|
||||
if (entry >= p.address && entry - p.address < p.words) have_entry = 1U; /* Код entry обязан присутствовать именно в принятой таблице. */
|
||||
for (i = 0U; i < s->count; ++i) if (p.address < s->section[i].address + s->section[i].words && s->section[i].address < p.address + p.words) return false; /* Повторное программирование пересекающихся диапазонов запрещено. */
|
||||
for (j = s->count; j && s->section[j - 1U].address > p.address; --j) s->section[j] = s->section[j - 1U]; /* Сортирует индекс по адресу независимо от порядка секций в SCI8. */
|
||||
s->section[j] = p; ++s->count; offset += bytes; /* Запоминает непересекающуюся секцию и переходит к следующему заголовку. */
|
||||
} /* Структура файла полностью разобрана без записи Flash. */
|
||||
if (!ended || headers != 1U || !have_entry || s->fault) return false; /* Требует терминатор, единственный FAB1 и фактический исполняемый entry. */
|
||||
s->cursor = 0U; if (!f28335_flash_app_validate(image_word, s, &checked_entry) || s->fault || checked_entry != entry) return false; /* Общий валидатор проверяет magic, границы, инверсию entry и CRC будущей Flash. */
|
||||
s->entry = entry; s->valid = true; return true; /* Разрешает программирование только после всех независимых проверок. */
|
||||
} /* Ошибка проверки не меняет текущую Flash и журнал активной EEPROM. */
|
||||
bool f28335_flash_update_program(f28335_flash_update_t *s, const f28335_flash_ops_t *ops) /* Выполняет запись B–H только из полностью проверенного staging. */
|
||||
{ /* Заголовок FAB1 фиксируется после успешной проверки каждой порции данных. */
|
||||
uint16_t buffer[128]; unsigned int i, j, n; uint32_t at, left, entry; pcan_boot_manifest_t m; f28335_boot_io_t io; /* Одна порция содержит не более 128 слов, то есть 256 физических октетов. */
|
||||
if (!s || !s->valid || !ops || !ops->erase || !ops->program || !ops->read) return false; /* Неполный аппаратный контракт не должен начать стирание. */
|
||||
memset(&m, 0, sizeof(m)); m.image_size = s->length; m.image_crc32 = s->crc; io = s->io; at = s->base; /* Сохраняет исходные параметры перед полной повторной проверкой EEPROM. */
|
||||
if (!f28335_flash_update_validate(s, &io, at, &m)) return false; /* Изменение staging между VERIFY и COMMIT обнаруживается до первого erase. */
|
||||
s->valid = false; if (!ops->erase(ops->user)) return false; /* Одно разрешение записи расходуется до изменения Flash; повтор после отказа требует нового VERIFY. */
|
||||
for (i = 0U; i < s->count; ++i) { /* Программирует обычные данные каждой непересекающейся секции. */
|
||||
at = s->section[i].address; left = s->section[i].words; /* CPU-курсор и остаток выражены словами. */
|
||||
if (at == F28335_FLASH_APP_START) { at += F28335_FLASH_APP_HEADER_WORDS; left -= F28335_FLASH_APP_HEADER_WORDS; } /* Пропускает FAB1 до подтверждения всех остальных данных. */
|
||||
while (left) { /* Большие секции разбивает на порции рабочего буфера. */
|
||||
n = left > 128UL ? 128U : (unsigned int)left; /* Последняя порция может быть короче 128 слов. */
|
||||
for (j = 0U; j < n; ++j) buffer[j] = word(s, s->section[i].offset + 2UL * (at + j - s->section[i].address)); /* Распаковывает слова непосредственно из staging EEPROM. */
|
||||
if (s->fault || !ops->program(ops->user, at, buffer, n)) return false; /* Ошибка чтения, записи или readback оставляет FAB1 неопубликованным. */
|
||||
at += n; left -= n; /* Продвигает курсоры только после подтверждённой порции. */
|
||||
} /* Завершает запись данных секции. */
|
||||
} /* Все обычные слова уже записаны и проверены аппаратным портом. */
|
||||
for (i = 0U; i < F28335_FLASH_APP_HEADER_WORDS; ++i) buffer[i] = image_word(s, F28335_FLASH_APP_START + i); /* Собирает единственное проверенное описание FAB1 для заключительной записи. */
|
||||
if (s->fault || !ops->program(ops->user, F28335_FLASH_APP_START, buffer, F28335_FLASH_APP_HEADER_WORDS)) return false; /* Публикует описание только после успешной записи остальных секций. */
|
||||
return f28335_flash_app_validate(ops->read, ops->user, &entry) && entry == s->entry; /* Итоговый успех требует общей CRC уже физической Flash, а не только поблочного сравнения. */
|
||||
} /* Решение о CAN-подтверждении и перезапуске остаётся существующему протоколу. */
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef F28335_FLASH_UPDATE_H /* Один контракт объединяет проверку CAN-образа и аппаратную запись внутренней Flash. */
|
||||
#define F28335_FLASH_UPDATE_H /* Исключает повторное объявление структур при подключении аппаратного порта. */
|
||||
#include "f28335_boot_store.h" /* Использует существующий побайтовый доступ к staging-слоту EEPROM и manifest ProtoCAN. */
|
||||
#include "f28335_flash_app.h" /* Получает границы приложения B–H и проверку завершающего описания FAB1. */
|
||||
typedef struct { uint32_t address, offset; uint16_t words; } f28335_flash_section_t; /* Адрес CPU считается словами, смещение SCI8 — октетами, длина секции — словами. */
|
||||
typedef struct { /* Хранит проверенный индекс SCI8, не размещая целый образ во внутренней RAM загрузчика. */
|
||||
f28335_boot_io_t io; uint32_t base, length, crc, entry; /* Источник EEPROM, начало staging, точная длина, транспортная CRC32 и подтверждённый entry. */
|
||||
f28335_flash_section_t section[F28335_AB_MAX_SECTIONS]; /* Лимит 64 совпадает с ограничением выпуска SCI8 и ограничивает расход RAM. */
|
||||
unsigned int count, cursor, cache_size; bool fault, valid; /* Курсор ускоряет последовательную CRC; fault запрещает принятие неполного чтения EEPROM. */
|
||||
uint32_t cache_at; pcan_boot_byte_t cache[256]; /* Одна страница M95M02 содержит 256 физических октетов, даже при 16-битном char C28x. */
|
||||
} f28335_flash_update_t; /* Объект принадлежит только main постоянного загрузчика, а не CAN ISR. */
|
||||
typedef struct { /* Аппаратные операции отделены от формата SCI8 для испытаний обрыва и ошибок TI API. */
|
||||
bool (*erase)(void *user); /* Стирает только секторы B–H, сохраняя сектор A с постоянным загрузчиком. */
|
||||
bool (*program)(void *user, uint32_t address, uint16_t *data, unsigned int words); /* Записывает и проверяет одну порцию слов по допустимому CPU-адресу. */
|
||||
f28335_flash_read_word_t read; void *user; /* Чтение физической Flash подтверждает общий FAB1/CRC после последней записи. */
|
||||
} f28335_flash_ops_t; /* Никаких неявных операций reset или изменения EEPROM-журнала здесь нет. */
|
||||
bool f28335_flash_update_validate(f28335_flash_update_t *s, const f28335_boot_io_t *io, uint32_t base, const pcan_boot_manifest_t *m); /* Полностью проверяет staging до первого стирания Flash. */
|
||||
bool f28335_flash_update_program(f28335_flash_update_t *s, const f28335_flash_ops_t *ops); /* Повторяет проверку, пишет данные и публикует FAB1 последним. */
|
||||
bool F28335Boot_FlashProgram(f28335_flash_update_t *s); /* Аппаратная реализация подключает официальный TI Flash API только в постоянном загрузчике. */
|
||||
#endif /* Завершает защиту интерфейса CAN-обновления внутренней Flash. */
|
||||
@@ -0,0 +1,156 @@
|
||||
# Отдельные проекты CCS: F28335 и F2812
|
||||
|
||||
Весь комплект находится внутри `templates/c/protocan-boot`: проекты CCS,
|
||||
исходники загрузчиков, аппаратные порты, linker command files, необходимая
|
||||
поддержка TI, CLI-сборка, тесты и документация. Зависимости от исходников
|
||||
`28335_periph` и `BALZAM_167` при сборке отсутствуют. Требуется установленный
|
||||
TI C2000 compiler с поддержкой **COFF ABI**; проверена версия **22.6.0.LTS**.
|
||||
|
||||
| Проект CCS | Контроллер | Обновляемая память | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| `ccs/f28335` — `F28335_CAN_AB` | TMS320F28335 | M95M02, 256 КиБ | A/B, trial, CONFIRM, rollback |
|
||||
| `ccs/f2812` — `F2812_CAN_NOR` | TMS320F2812 / ПМ67 | AM29LV800BT-70EI, 1 МиБ, x16 | Один выделенный NOR-слот, проверяемый manifest, CAN recovery |
|
||||
|
||||
F2812 не использует EEPROM. Его карта, GPIO, частота CAN, допустимые адреса
|
||||
приложения и состояние протокола отделены от F28335.
|
||||
|
||||
## Открытие в Code Composer Studio
|
||||
|
||||
1. **Project → Import CCS Projects**, каталог поиска — `c/protocan-boot/projects/ccs`.
|
||||
2. Выбрать `F28335_CAN_AB` и `F2812_CAN_NOR`. Оставить проекты в исходном
|
||||
расположении: **не включать Copy projects into workspace**, поскольку
|
||||
переносимые ссылки `PCAN_ROOT` ведут к общей библиотеке выше проектов.
|
||||
3. Выбрать **Debug** либо **Release**, затем **Build Project**. Оба проекта
|
||||
содержат собственные `.project`, `.cproject`, `.ccsproject`.
|
||||
4. OUT/MAP появятся в `ccs/<контроллер>/<Debug|Release>/`.
|
||||
|
||||
В `targetConfigs` сохранены существующие конфигурации Sauris SAU510:
|
||||
F28335 — Iso Plus v.2, F2812 — Iso Plus. Для другого адаптера выбрать свой
|
||||
Connection в Target Configuration. Компиляция и импорт не подключаются к JTAG
|
||||
и не программируют плату.
|
||||
|
||||
Для отдельных workspace с ограниченными правами CCS допускает переменную
|
||||
`TI_APPDATA_DIR` с доступным для записи каталогом. Это служебный cache IDE,
|
||||
он не относится к исходникам загрузчиков.
|
||||
|
||||
## Сборка без запуска IDE
|
||||
|
||||
Из корня **templates**:
|
||||
|
||||
```powershell
|
||||
python c/protocan-boot/projects/build.py --device f28335
|
||||
python c/protocan-boot/projects/build.py --device f2812
|
||||
python c/protocan-boot/projects/build.py --device f28335 --configuration Release
|
||||
python c/protocan-boot/projects/build.py --device f2812 --configuration Release
|
||||
```
|
||||
|
||||
Можно передать `--compiler <каталог-ti-cgt-c2000>` и `--output <каталог>`.
|
||||
Скрипт читает состав исходников и настройки из этих же CCS-проектов, полностью
|
||||
пересобирает их и проверяет реальные COFF LOAD-адреса официальным `ofd2000`.
|
||||
Проверка отклоняет загружаемый RAM-код без Flash LOAD, пересечения, отсутствующие
|
||||
boot branch/C entry, запись CSM/OTP и посторонних внутренних секторов.
|
||||
Рядом с OUT сохраняются MAP, `build.log` и manifest с SHA-256.
|
||||
|
||||
Результаты:
|
||||
|
||||
- `ccs/f28335/Debug/F28335_CAN_AB.out`;
|
||||
- `ccs/f2812/Debug/F2812_CAN_NOR.out`.
|
||||
|
||||
OUT — постоянный загрузчик для первоначальной установки через JTAG во
|
||||
**внутреннюю Flash** соответствующего TMS. Образ самого приложения передаётся
|
||||
по CAN в его внешнюю память. Для автоматического запуска должен быть выбран
|
||||
внутренний Flash boot; у ПМ67 необходимо также учитывать штатную логику CPLD
|
||||
выбора источника reset/boot из `big_dsp_module` платы.
|
||||
|
||||
## F28335 / M95M02
|
||||
|
||||
Проект использует существующий порт и формат журнала без изменения адресов:
|
||||
**PERIPH 0–31: Type = 1 + PERIPH / 16, Device ID = PERIPH mod 16**.
|
||||
УМП1 — **1/5**, УМП2 — **1/6**, задатчик — **1/8**.
|
||||
Product **0x2833**, HW **1**, CAN **250000 бит/с**. Приложение и загрузчик
|
||||
используют один аппаратный номер платы; прежний общий адрес **3/7** отменён.
|
||||
Код загрузчика — внутренний сектор A `0x338000..0x33FF7F`, boot — `0x33FFF6`.
|
||||
Слоты M95M02 имеют по **130560 октетов**, параметры — прежние 258 октетов
|
||||
по адресу `0x3FEFC`. Приложение загружается в RAM ниже CPU word-адреса `0xE000`.
|
||||
|
||||
После установки постоянного загрузчика новое приложение 167 передаётся
|
||||
существующим клиентом SETGUI **CAN / ProtoCAN Boot**. Оно обязано содержать
|
||||
hooks READY/CONFIRM и watchdog: пример интеграции реализован в ветке 167.
|
||||
Без CONFIRM следующий reset возвращает подтверждённый active.
|
||||
Полная последовательность — [документация порта F28335](../ports/tms320f28335/README.md).
|
||||
|
||||
## F2812 / AM29LV800BT
|
||||
|
||||
Профиль: **Device Type 3, Device ID 6, Product 0x2812, HW 1,
|
||||
CAN 250000 бит/с, SYSCLKOUT 150 МГц**. CAN находится на **GPIOF6 TX / GPIOF7 RX**.
|
||||
F2812 использует программную арифметику `rts2800_ml.lib`; F28335 — FPU32
|
||||
и `rts2800_fpu32.lib`.
|
||||
|
||||
Внутренний сектор A загрузчика: `0x3F6000..0x3F7F7F`, boot — `0x3F7FF6`.
|
||||
Внешняя NOR подключена по **CPU word-адресу `0x100000`**. Новый CAN-раздел
|
||||
задан явно в `ports/tms320f2812/boot2812.h`:
|
||||
|
||||
| Область | CPU word-адреса включительно | Размер |
|
||||
| --- | --- | ---: |
|
||||
| Существующая нижняя область: прежние образы/параметры/FPGA | `0x100000..0x15FFFF` | 768 КиБ |
|
||||
| Новый SCI8 CAN-образ: обычные сектора 12/13/14 | `0x160000..0x177FFF` | **192 КиБ** |
|
||||
| Неизменяемые этим загрузчиком top-boot сектора 15/16/17 | `0x178000..0x17DFFF` | 48 КиБ |
|
||||
| Новый manifest: последний top-boot сектор 18 | `0x17E000..0x17FFFF` | 16 КиБ |
|
||||
|
||||
Это **новое явное размещение CAN-образа**, а не автоматическое определение
|
||||
свободного места в уже заполненном чипе. Перед первоначальной установкой
|
||||
согласовать эти два выделенных участка с фактической картой NOR конкретной
|
||||
платы. В известном исходнике FPGA начинается с `0x130000`, а новый CAN-слот
|
||||
находится выше; драйвер не изменяет ничего ниже `0x160000` и в секторах 15–17.
|
||||
|
||||
После reset доступно **3 секунды** для ENTER_BOOT. Открытая сессия удерживает
|
||||
загрузчик; пустой/повреждённый manifest оставляет CAN recovery постоянно.
|
||||
Для обновления уже работающего приложения нужно войти в это окно после reset;
|
||||
приложение F2812 само по себе пока не получает обработчик ENTER_BOOT от добавления
|
||||
отдельного проекта загрузчика.
|
||||
|
||||
Перед записью требуется AMD manufacturer **`0x0001`**, device **`0x22DA`**.
|
||||
Сначала стирается сектор manifest, затем три сектора образа. Запись проверяет
|
||||
каждое слово. VERIFY повторно читает NOR, проверяет CRC32, SCI8, entry,
|
||||
перекрытия и запрещённые назначения. COMMIT повторяет проверку, сохраняет
|
||||
manifest с собственной CRC, два magic-слова публикуются последними.
|
||||
Стирание сообщает BUSY каждые 250 мс, продлевая живую сессию.
|
||||
|
||||
Это single-slot схема: при обрыве обновления последнего CAN-образа остаётся
|
||||
recovery, автоматический A/B rollback для F2812 не заявляется. Полное стирание
|
||||
NOR, запись внутренней Flash по CAN и программирование FPGA отсутствуют.
|
||||
|
||||
Образ приложения — **TI SCI8 `AA 08`**, максимум **196608 октетов**. Старый
|
||||
flat BIN основного контроллера автоматически не мигрируется. Допустимый payload:
|
||||
|
||||
- L0 `0x8000..0x8EFF`;
|
||||
- H0 `0x3F8000..0x3F9FFF`;
|
||||
- внешняя SRAM zone2 `0x80000..0xFFFFF`.
|
||||
|
||||
Стек M1, L1 `0x9000..0x9FFF`, RAM InitFlash `0x8F00..0x8FFF`, периферия,
|
||||
внутренняя Flash и NOR не допускаются как назначения SCI8. `.ebss` приложения
|
||||
может занять L1 после перехода в его C runtime; инициализированный payload
|
||||
работающую RAM загрузчика перезаписывать не должен. Настройка приложения
|
||||
F2812/его linker — отдельная от импорта загрузчика операция.
|
||||
|
||||
Геометрия x16, ID и команды AA/55/A0/80/30/F0 взяты из
|
||||
[оригинального datasheet AMD Am29LV800B](https://cms.nacsemi.com/content/AuthDatasheets/FASLS02690-1.pdf).
|
||||
Аппаратные GPIO/CPLD и XINTF-тайминги перенесены из действующих
|
||||
`big_dsp_module.c` / `flash_tools.c` ПМ67, без зависимости от этих файлов при сборке.
|
||||
|
||||
## Проверки
|
||||
|
||||
```powershell
|
||||
$env:CC = 'C:/msys64/ucrt64/bin/gcc.exe'
|
||||
python c/protocan-boot/tests/run_tests.py
|
||||
```
|
||||
|
||||
Проверяются протокол, CRC, сессии/BUSY, A/B F28335 с trial/rollback/CONFIRM,
|
||||
NOR F2812 с настоящими AMD command cycles, ID, readback, запрещёнными секторами,
|
||||
обрывами COMMIT, повреждением CRC/SCI8 и тайм-аутом DQ7.
|
||||
Вариант с CMake/CTest также поддерживается.
|
||||
|
||||
Подтверждены реальные import/build обоих проектов в CCS 12.3, CLI-сборки
|
||||
Debug/Release TI 22.6 COFF и проверки секций OUT. Физические JTAG/CAN/XINTF,
|
||||
режим boot и поведение конкретной платы при отключении питания требуют стенда;
|
||||
физическое программирование этим комплектом автоматически не выполнялось.
|
||||
@@ -0,0 +1,86 @@
|
||||
"""Сборка отдельных CCS-проектов ProtoCAN для F28335/M95M02 и F2812/AM29LV800BT.""" # Требует только Python и установленный TI C2000 COFF compiler.
|
||||
import argparse # Разбирает выбранный контроллер, конфигурацию и пути toolchain.
|
||||
import base64 # Читает настоящие программируемые данные COFF из официального OFD XML.
|
||||
import hashlib # Связывает собранный OUT с контрольной суммой в локальном build manifest.
|
||||
import json # Сохраняет точные команды, происхождение исходников и результаты проверки.
|
||||
from pathlib import Path # Разрешает все зависимости внутри templates относительно расположения проекта.
|
||||
import subprocess # Вызывает установленный TI compiler без shell-интерполяции аргументов.
|
||||
import xml.etree.ElementTree as ET # Использует действующие .project/.cproject как источник состава и опций сборки.
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1] # Корень protocan-boot содержит codec, порты, проекты и vendored TI support.
|
||||
DEFAULT_COMPILER = Path("C:/ti/ccs1230/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS") # Сохраняет проверенную версию установленного C2000 COFF compiler.
|
||||
|
||||
|
||||
def settings(device, configuration, compiler): # Читает те же исходники и пути, которые получает импортированный проект CCS.
|
||||
project = ROOT / "projects/ccs" / device # Каждое семейство контроллера имеет собственный Eclipse projectDescription.
|
||||
config = next(item for item in ET.parse(project / ".cproject").findall(".//configuration") if item.get("name") == configuration) # Не подменяет Debug настройками Release или другого устройства.
|
||||
options = {item.get("superClass", "").rsplit(".", 1)[-1]: item for item in config.findall("folderInfo/toolChain/tool/option")} # Собирает только параметры общего folderInfo без переопределений отдельных файлов.
|
||||
macros = {"${PROJECT_ROOT}": str(project), "${PROJECT_LOC}": str(project), "${CG_TOOL_ROOT}": str(compiler)} # Разрешает только известные пути, не выполняя shell-подстановки.
|
||||
def values(name): # Возвращает listOptionValue после подстановки локальных макросов CCS.
|
||||
result = [] # Порядок include paths и библиотек остаётся тем же, что в проекте.
|
||||
for item in options[name].findall("listOptionValue"): # Обрабатывает каждое явное значение текущей конфигурации.
|
||||
value = item.get("value", "") # Отсутствующее значение не превращается в имя неизвестного каталога.
|
||||
for macro, replacement in macros.items(): value = value.replace(macro, replacement) # Ограничивает подстановки определёнными выше путями.
|
||||
if "${" in value: raise ValueError("Unresolved CCS macro: " + value) # Останавливает сборку вместо поиска случайной зависимости на машине.
|
||||
result.append(value) # Добавляет параметр в исходном порядке конфигурации CCS.
|
||||
return result # Возвращает обычные аргументы без скрытых изменений окружения.
|
||||
sources = sorted(project.glob("*.c")) + sorted(project.glob("*.asm")) # Локальные production-исходники проекта компилируются вместе с аппаратным портом.
|
||||
commands = sorted(project.glob("*.cmd")) # Каждый проект имеет собственную разметку памяти соответствующего F28xx.
|
||||
for link in ET.parse(project / ".project").findall(".//linkedResources/link"): # Добавляет только explicit linkedResources из templates.
|
||||
uri = link.findtext("locationURI", "") # Все общие исходники привязаны к переменной PCAN_ROOT.
|
||||
if not uri.startswith("PCAN_ROOT/"): raise ValueError("Unsupported linked resource: " + uri) # Не допускает зависимость от старого firmware checkout или абсолютного чужого пути.
|
||||
path = ROOT / uri.removeprefix("PCAN_ROOT/") # Разрешает vendor и общие исходники внутри переносимого protocan-boot.
|
||||
if path.suffix.lower() in (".c", ".asm"): sources.append(path) # Заголовки не компилируются самостоятельными единицами трансляции.
|
||||
elif path.suffix.lower() == ".cmd": commands.append(path) # Подключает оригинальное TI размещение регистров выбранного контроллера.
|
||||
flags = ["-v28", "-ml", "-mt", "--abi=coffabi", "-O" + options["OPT_LEVEL"].get("value").rsplit(".", 1)[-1], "--opt_for_speed=" + options["OPT_FOR_SPEED"].get("value").rsplit(".", 1)[-1], "--gen_func_subsections=on"] # Повторяет архитектуру COFF, большие адреса, оптимизацию и сборку отдельных функций проекта CCS.
|
||||
if device == "f28335": flags.append("--float_support=fpu32") # Только F28335 имеет используемый аппаратный FPU32.
|
||||
flags += ["--include_path=" + value for value in values("INCLUDE_PATH")] + ["--define=" + value for value in values("DEFINE")] # Передаёт конкретные аппаратные заголовки и profile defines без потери различий между контроллерами.
|
||||
if configuration == "Debug": flags.append("-g") # Debug OUT сохраняет символы для пошагового JTAG-анализа загрузчика.
|
||||
return project, config.get("artifactName"), flags, sources, commands, values("LIBRARY"), values("SEARCH_PATH") # Возвращает полный воспроизводимый набор исходников и linker inputs.
|
||||
|
||||
|
||||
def verify(device, image, compiler): # Проверяет реальные секции OUT после линковки, а не только текст соседнего MAP.
|
||||
xml = ET.fromstring(subprocess.check_output([str(compiler / "bin/ofd2000.exe"), "-x", str(image)])) # Официальный декодер TI читает COFF текущей завершившейся сборки.
|
||||
coff = xml.find(".//ti_coff") # Загружать через JTAG разрешено именно executable C2000 COFF.
|
||||
if coff is None or coff.findtext("file_header/exec") != "true" or coff.findtext("file_header/target_id") != "0x9d": raise ValueError("Expected executable C2000 COFF") # Не подписывает чужой объект, ELF либо незалинкованный файл.
|
||||
first, end, boot = (0x338000, 0x33FF80, 0x33FFF6) if device == "f28335" else (0x3F6000, 0x3F7F80, 0x3F7FF6) # Адреса внутренних секторов A и аппаратных boot-переходов различаются между F28335/F2812.
|
||||
loaded = set() # Повторная загрузка одного физического слова из двух секций запрещена.
|
||||
for section in coff.findall("section"): # Рассматривает только реальные данные секций после линковки.
|
||||
address = int(section.findtext("virtual_addr", "0"), 0); raw = section.findtext("raw_data") # COFF virtual_addr обозначает LOAD, physical_addr — RUN копируемых ramfuncs.
|
||||
if raw is None or section.findtext("copy") == "true" or section.findtext("name") == ".adc_cal": continue # Исключает только явные COPY/отладочные секции, BSS без raw_data и заводскую ADC-калибровку; загружаемый RAM-код обязан иметь Flash LOAD.
|
||||
data = base64.b64decode(raw) # Читает точные октеты программируемого содержимого из COFF, а не считает по объявленному размеру.
|
||||
if len(data) % 2 or not (first <= address < address + len(data) // 2 <= end or address == boot and len(data) == 4): raise ValueError("Loaded section outside bootloader Flash: " + str(section.findtext("name"))) # Защищает OTP, CSM, внешнюю NOR/EEPROM и остальные внутренние секторы.
|
||||
for word in range(address, address + len(data) // 2): # Контролирует физические 16-битные слова всех программируемых секций.
|
||||
if word in loaded: raise ValueError("Overlapping load sections") # Даже совпадающие данные не разрешают неоднозначную разметку OUT.
|
||||
loaded.add(word) # Фиксирует фактически загружаемый диапазон текущего результата.
|
||||
entry = int(coff.findtext("optional_file_header/entry_point", "0"), 0) # Извлекает реальную точку входа C runtime из заголовка файла.
|
||||
if entry not in loaded or boot not in loaded or boot + 1 not in loaded: raise ValueError("Missing loaded C entry or codestart") # JTAG OUT обязан одновременно содержать C startup и аппаратный Flash boot переход.
|
||||
return {"entry_word": entry, "boot_word": boot, "loaded_words": len(loaded)} # Эти проверенные значения входят в build manifest рядом с SHA-256.
|
||||
|
||||
|
||||
def build(device, configuration, compiler, output=None): # Полностью собирает один из двух самостоятельных проектов без установки на плату.
|
||||
compiler = compiler.resolve(); project, name, flags, sources, commands, libraries, searches = settings(device, configuration, compiler) # Использует абсолютный toolchain и актуальную конфигурацию CCS.
|
||||
output = (output or project / configuration).resolve(); output.mkdir(parents=True, exist_ok=True) # Генерирует результаты только в каталоге выбранной сборки.
|
||||
objects = [] # В линковку входят только успешно пересобранные исходники текущего вызова.
|
||||
with (output / "build.log").open("w", encoding="utf-8") as log: # Журнал содержит полный набор команд и диагностику TI.
|
||||
def run(command): # Не продолжает сборку после ошибки компилятора или linker.
|
||||
log.write(json.dumps([str(arg) for arg in command], ensure_ascii=False) + "\n"); log.flush() # Сохраняет команду до запуска процесса без исполнения как shell-кода.
|
||||
subprocess.run([str(arg) for arg in command], cwd=project, stdout=log, stderr=subprocess.STDOUT, check=True) # Ненулевой статус исключает публикацию ложного успешного результата.
|
||||
for source in sources: # Все локальные и linked TI-файлы пересобираются для выбранного контроллера.
|
||||
obj = output / (source.stem + ".obj"); run([compiler / "bin/cl2000.exe", *flags, "-c", "--output_file=" + str(obj), source]); objects.append(obj) # Объекты F2812 soft-float и F28335 FPU32 не смешиваются.
|
||||
image = output / (name + ".out") # Имя результата совпадает с artifactName импортированного CCS-проекта.
|
||||
link = [compiler / "bin/cl2000.exe", "-v28", "--abi=coffabi"] + (["--float_support=fpu32"] if device == "f28335" else []) # Linker ABI и FPU точно соответствуют скомпилированным объектам.
|
||||
run([*link, "-z", "--rom_model", "--entry_point=_c_int00", "--stack_size=0x3f0", "--warn_sections", "--reread_libs", "-m" + str(image.with_suffix(".map")), "-o", image, *["--search_path=" + value for value in searches], *commands, *objects, *["-l" + value for value in libraries]]) # Подключает только собственный linker и оригинальные peripheral sections выбранного MCU.
|
||||
checked = verify(device, image, compiler) # Физические LOAD-адреса, boot branch и C entry проверяются после каждой CLI-сборки.
|
||||
manifest = {"device": device, "configuration": configuration, "sha256": hashlib.sha256(image.read_bytes()).hexdigest(), "sources": {str(path.relative_to(ROOT)): hashlib.sha256(path.read_bytes()).hexdigest() for path in sources}, **checked} # Связывает OUT с конкретными исходниками и результатом проверки карты.
|
||||
image.with_suffix(".out.manifest.json").write_text(json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", encoding="utf-8") # Не изменяет версии приложения или данные физической памяти.
|
||||
return image # Вызывающий явно решает, когда устанавливать OUT через JTAG.
|
||||
|
||||
|
||||
if __name__ == "__main__": # Импорт для проверки проектов не запускает compiler автоматически.
|
||||
parser = argparse.ArgumentParser(description=__doc__) # Описывает два самостоятельных проекта и отсутствие программирования платы.
|
||||
parser.add_argument("--device", choices=("f2812", "f28335"), required=True) # Не допускает случайной сборки для другого контроллера.
|
||||
parser.add_argument("--configuration", choices=("Debug", "Release"), default="Debug") # Повторяет имена управляемых конфигураций CCS.
|
||||
parser.add_argument("--compiler", type=Path, default=DEFAULT_COMPILER) # Поддерживает другую установленную версию TI с COFF ABI.
|
||||
parser.add_argument("--output", type=Path) # Разрешает изолированную проверочную сборку без загрязнения импортированного CCS-проекта.
|
||||
args = parser.parse_args(); print(build(args.device, args.configuration, args.compiler, args.output)) # Сообщает конкретный успешно проверенный OUT, не инициируя JTAG.
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?ccsproject version="1.0"?>
|
||||
<projectOptions>
|
||||
<!-- Описывает ccsVersion: 12.3.0. -->
|
||||
<ccsVersion value="12.3.0" />
|
||||
<!-- Описывает deviceVariant: TMS320C28XX.TMS320F2812. -->
|
||||
<deviceVariant value="TMS320C28XX.TMS320F2812" />
|
||||
<!-- Описывает deviceFamily: C2000. -->
|
||||
<deviceFamily value="C2000" />
|
||||
<!-- Описывает deviceEndianness: little. -->
|
||||
<deviceEndianness value="little" />
|
||||
<!-- Описывает codegenToolVersion: 22.6.0.LTS. -->
|
||||
<codegenToolVersion value="22.6.0.LTS" />
|
||||
<!-- Описывает isElfFormat: false. -->
|
||||
<isElfFormat value="false" />
|
||||
<!-- Описывает rts: rts2800_ml.lib. -->
|
||||
<rts value="rts2800_ml.lib" />
|
||||
<!-- Описывает isTargetManual: false. -->
|
||||
<isTargetManual value="false" />
|
||||
</projectOptions>
|
||||
@@ -0,0 +1,306 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?fileVersion 4.0.0?>
|
||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<!-- Описывает storageModule: org.eclipse.cdt.core.settings. -->
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<!-- Описывает cconfiguration: cconfiguration. -->
|
||||
<cconfiguration id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f2812">
|
||||
<!-- Описывает storageModule: Debug. -->
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f2812" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<!-- Описывает externalSettings: externalSettings. -->
|
||||
<externalSettings />
|
||||
<!-- Описывает extensions: extensions. -->
|
||||
<extensions>
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.binaryparser.CoffParser.f2812" point="org.eclipse.cdt.core.BinaryParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.CoffErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.AsmErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.LinkErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: cdtBuildSystem. -->
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<!-- Описывает configuration: Debug. -->
|
||||
<configuration artifactExtension="out" artifactName="F2812_CAN_NOR" buildProperties="" cleanCommand="${CG_CLEAN_CMD}" description="" id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f2812" name="Debug" parent="com.ti.ccstudio.buildDefinitions.C2000.Debug" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
||||
<!-- Описывает folderInfo: /. -->
|
||||
<folderInfo id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f2812." name="/" resourcePath="">
|
||||
<!-- Описывает toolChain: TI Build Tools. -->
|
||||
<toolChain id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.DebugToolchain.1656408937.f2812" name="TI Build Tools" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.DebugToolchain" targetTool="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerDebug.1238234098.f2812">
|
||||
<!-- Задаёт параметр сборки: option. -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS.1809066827.f2812" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS" valueType="stringList">
|
||||
<!-- Передаёт значение параметра: DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F2812. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F2812" />
|
||||
<!-- Передаёт значение параметра: DEVICE_ENDIANNESS=little. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_ENDIANNESS=little" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_FORMAT=COFF. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_FORMAT=COFF" />
|
||||
<!-- Передаёт значение параметра: LINKER_COMMAND_FILE=F2812_CAN_NOR.cmd. -->
|
||||
<listOptionValue builtIn="false" value="LINKER_COMMAND_FILE=F2812_CAN_NOR.cmd" />
|
||||
<!-- Передаёт значение параметра: RUNTIME_SUPPORT_LIBRARY=rts2800_ml.lib. -->
|
||||
<listOptionValue builtIn="false" value="RUNTIME_SUPPORT_LIBRARY=rts2800_ml.lib" />
|
||||
<!-- Передаёт значение параметра: CCS_MBS_VERSION=6.1.3. -->
|
||||
<listOptionValue builtIn="false" value="CCS_MBS_VERSION=6.1.3" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_TYPE=executable. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_TYPE=executable" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Compiler version. -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION.1182984787.f2812" name="Compiler version" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION" value="22.6.0.LTS" valueType="string" />
|
||||
<!-- Описывает targetPlatform: Platform. -->
|
||||
<targetPlatform id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformDebug.2023332194.f2812" name="Platform" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformDebug" />
|
||||
<!-- Описывает builder: GNU Make. -->
|
||||
<builder buildPath="${BuildDirectory}" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderDebug.1704049401.f2812" keepEnvironmentInBuildfile="false" name="GNU Make" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderDebug" />
|
||||
<!-- Описывает tool: C2000 Compiler. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerDebug.68471068.f2812" name="C2000 Compiler" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerDebug">
|
||||
<!-- Задаёт параметр сборки: Option deprecated, set by default (- -large_memory_model, -ml). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL.1683926605.f2812" name="Option deprecated, set by default (--large_memory_model, -ml)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Unified memory (- -unified_memory, -mt). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY.884660743.f2812" name="Unified memory (--unified_memory, -mt)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Processor version (- -silicon_version, -v). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.750562333.f2812" name="Processor version (--silicon_version, -v)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.28" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Optimization level (- -opt_level, -O). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.1217592973.f2812" name="Optimization level (--opt_level, -O)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.3" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Place each function in a separate subsection (- -gen_func_subsections, -mo). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.eeprom.40.f2812" name="Place each function in a separate subsection (--gen_func_subsections, -mo)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.on" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Speed vs. size trade-offs (- -opt_for_speed, -mf). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.1885063317.f2812" name="Speed vs. size trade-offs (--opt_for_speed, -mf)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.0" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Add dir to #include search path (- -include_path, -I). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH.24504397.f2812" name="Add dir to #include search path (--include_path, -I)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH" valueType="includePath">
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f2812/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f2812/include" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f2812/common/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f2812/common/include" />
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/include. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/include" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Pre-define NAME (- -define, -D). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE.409484878.f2812" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE" valueType="definedSymbols">
|
||||
<!-- Передаёт значение параметра: LARGE_MODEL. -->
|
||||
<listOptionValue builtIn="false" value="LARGE_MODEL" />
|
||||
<!-- Передаёт значение параметра: _DEBUG. -->
|
||||
<listOptionValue builtIn="false" value="_DEBUG" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Debugging model. -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEBUGGING_MODEL.1803616155.f2812" name="Debugging model" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEBUGGING_MODEL" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEBUGGING_MODEL.SYMDEBUG__DWARF" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number, -pden). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER.362706119.f2812" name="Emit diagnostic identifier numbers (--display_error_number, -pden)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Application binary interface [See 'General' page to edit] (- -abi). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.1036638377.f2812" name="Application binary interface [See 'General' page to edit] (--abi)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.coffabi" valueType="enumerated" />
|
||||
<!-- Описывает inputType: C Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS.413246530.f2812" name="C Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS" />
|
||||
<!-- Описывает inputType: C++ Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS.1626831603.f2812" name="C++ Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS.291886960.f2812" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS.231319110.f2812" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Linker. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerDebug.1238234098.f2812" name="C2000 Linker" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerDebug">
|
||||
<!-- Задаёт параметр сборки: Set C system stack size (- -stack_size, -stack). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE.1288161308.f2812" name="Set C system stack size (--stack_size, -stack)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE" value="0x3f0" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Link information (map) listed into <file> (- -map_file, -m). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE.1478857036.f2812" name="Link information (map) listed into <file> (--map_file, -m)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE" value="F2812_CAN_NOR.map" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify output file name (- -output_file, -o). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE.1263270138.f2812" name="Specify output file name (--output_file, -o)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE" value="F2812_CAN_NOR.out" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Include library file or command file as input (- -library, -l). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY.1967188356.f2812" name="Include library file or command file as input (--library, -l)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY" valueType="libs">
|
||||
<!-- Передаёт значение параметра: rts2800_ml.lib. -->
|
||||
<listOptionValue builtIn="false" value="rts2800_ml.lib" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Add <dir> to library search path (- -search_path, -i). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH.1097407993.f2812" name="Add <dir> to library search path (--search_path, -i)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH" valueType="libPaths">
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/lib. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/lib" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER.2141790994.f2812" name="Emit diagnostic identifier numbers (--display_error_number)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Detailed link information data-base into <file> (- -xml_link_info, -xml_link_info). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO.1355214148.f2812" name="Detailed link information data-base into <file> (--xml_link_info, -xml_link_info)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO" value="F2812_CAN_NOR_linkInfo.xml" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify program entry point for the output module (- -entry_point, -e). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT.862275171.f2812" name="Specify program entry point for the output module (--entry_point, -e)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT" value="_c_int00" valueType="string" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS.1082823352.f2812" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS.1635863502.f2812" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS" />
|
||||
<!-- Описывает inputType: Generated Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS.209596448.f2812" name="Generated Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Hex Utility. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.183039420.f2812" name="C2000 Hex Utility" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex">
|
||||
<!-- Описывает outputType: Binary File. -->
|
||||
<outputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN.139478444.f2812" name="Binary File" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN" />
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<!-- Ограничивает компилируемые исходники проекта: sourceEntries. -->
|
||||
<sourceEntries>
|
||||
<!-- Описывает entry: entry. -->
|
||||
<entry excluding="Debug|Release" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" />
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: org.eclipse.cdt.core.externalSettings. -->
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings" />
|
||||
</cconfiguration>
|
||||
<!-- Описывает cconfiguration: cconfiguration. -->
|
||||
<cconfiguration id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f2812">
|
||||
<!-- Описывает storageModule: Release. -->
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f2812" moduleId="org.eclipse.cdt.core.settings" name="Release">
|
||||
<!-- Описывает externalSettings: externalSettings. -->
|
||||
<externalSettings />
|
||||
<!-- Описывает extensions: extensions. -->
|
||||
<extensions>
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.binaryparser.CoffParser.f2812" point="org.eclipse.cdt.core.BinaryParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.CoffErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.AsmErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.LinkErrorParser.f2812" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: cdtBuildSystem. -->
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<!-- Описывает configuration: Release. -->
|
||||
<configuration artifactExtension="out" artifactName="F2812_CAN_NOR" buildProperties="" cleanCommand="${CG_CLEAN_CMD}" description="" id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f2812" name="Release" parent="com.ti.ccstudio.buildDefinitions.C2000.Release" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
||||
<!-- Описывает folderInfo: /. -->
|
||||
<folderInfo id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f2812." name="/" resourcePath="">
|
||||
<!-- Описывает toolChain: TI Build Tools. -->
|
||||
<toolChain id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.ReleaseToolchain.1656408937.f2812" name="TI Build Tools" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.ReleaseToolchain" targetTool="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerRelease.1238234098.f2812">
|
||||
<!-- Задаёт параметр сборки: option. -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS.1809066827.f2812" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS" valueType="stringList">
|
||||
<!-- Передаёт значение параметра: DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F2812. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F2812" />
|
||||
<!-- Передаёт значение параметра: DEVICE_ENDIANNESS=little. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_ENDIANNESS=little" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_FORMAT=COFF. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_FORMAT=COFF" />
|
||||
<!-- Передаёт значение параметра: LINKER_COMMAND_FILE=F2812_CAN_NOR.cmd. -->
|
||||
<listOptionValue builtIn="false" value="LINKER_COMMAND_FILE=F2812_CAN_NOR.cmd" />
|
||||
<!-- Передаёт значение параметра: RUNTIME_SUPPORT_LIBRARY=rts2800_ml.lib. -->
|
||||
<listOptionValue builtIn="false" value="RUNTIME_SUPPORT_LIBRARY=rts2800_ml.lib" />
|
||||
<!-- Передаёт значение параметра: CCS_MBS_VERSION=6.1.3. -->
|
||||
<listOptionValue builtIn="false" value="CCS_MBS_VERSION=6.1.3" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_TYPE=executable. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_TYPE=executable" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Compiler version. -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION.1182984787.f2812" name="Compiler version" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION" value="22.6.0.LTS" valueType="string" />
|
||||
<!-- Описывает targetPlatform: Platform. -->
|
||||
<targetPlatform id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformRelease.2023332194.f2812" name="Platform" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformRelease" />
|
||||
<!-- Описывает builder: GNU Make. -->
|
||||
<builder buildPath="${BuildDirectory}" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderRelease.1704049401.f2812" keepEnvironmentInBuildfile="false" name="GNU Make" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderRelease" />
|
||||
<!-- Описывает tool: C2000 Compiler. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerRelease.68471068.f2812" name="C2000 Compiler" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerRelease">
|
||||
<!-- Задаёт параметр сборки: Option deprecated, set by default (- -large_memory_model, -ml). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL.1683926605.f2812" name="Option deprecated, set by default (--large_memory_model, -ml)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Unified memory (- -unified_memory, -mt). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY.884660743.f2812" name="Unified memory (--unified_memory, -mt)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Processor version (- -silicon_version, -v). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.750562333.f2812" name="Processor version (--silicon_version, -v)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.28" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Optimization level (- -opt_level, -O). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.1217592973.f2812" name="Optimization level (--opt_level, -O)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.3" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Place each function in a separate subsection (- -gen_func_subsections, -mo). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.eeprom.40.f2812" name="Place each function in a separate subsection (--gen_func_subsections, -mo)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.on" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Speed vs. size trade-offs (- -opt_for_speed, -mf). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.1885063317.f2812" name="Speed vs. size trade-offs (--opt_for_speed, -mf)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.0" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Add dir to #include search path (- -include_path, -I). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH.24504397.f2812" name="Add dir to #include search path (--include_path, -I)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH" valueType="includePath">
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f2812/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f2812/include" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f2812/common/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f2812/common/include" />
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/include. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/include" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Pre-define NAME (- -define, -D). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE.409484878.f2812" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE" valueType="definedSymbols">
|
||||
<!-- Передаёт значение параметра: LARGE_MODEL. -->
|
||||
<listOptionValue builtIn="false" value="LARGE_MODEL" />
|
||||
<!-- Передаёт значение параметра: _DEBUG. -->
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Releaseging model. -->
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number, -pden). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER.362706119.f2812" name="Emit diagnostic identifier numbers (--display_error_number, -pden)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Application binary interface [See 'General' page to edit] (- -abi). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.1036638377.f2812" name="Application binary interface [See 'General' page to edit] (--abi)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.coffabi" valueType="enumerated" />
|
||||
<!-- Описывает inputType: C Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS.413246530.f2812" name="C Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS" />
|
||||
<!-- Описывает inputType: C++ Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS.1626831603.f2812" name="C++ Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS.291886960.f2812" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS.231319110.f2812" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Linker. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerRelease.1238234098.f2812" name="C2000 Linker" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerRelease">
|
||||
<!-- Задаёт параметр сборки: Set C system stack size (- -stack_size, -stack). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE.1288161308.f2812" name="Set C system stack size (--stack_size, -stack)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE" value="0x3f0" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Link information (map) listed into <file> (- -map_file, -m). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE.1478857036.f2812" name="Link information (map) listed into <file> (--map_file, -m)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE" value="F2812_CAN_NOR.map" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify output file name (- -output_file, -o). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE.1263270138.f2812" name="Specify output file name (--output_file, -o)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE" value="F2812_CAN_NOR.out" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Include library file or command file as input (- -library, -l). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY.1967188356.f2812" name="Include library file or command file as input (--library, -l)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY" valueType="libs">
|
||||
<!-- Передаёт значение параметра: rts2800_ml.lib. -->
|
||||
<listOptionValue builtIn="false" value="rts2800_ml.lib" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Add <dir> to library search path (- -search_path, -i). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH.1097407993.f2812" name="Add <dir> to library search path (--search_path, -i)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH" valueType="libPaths">
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/lib. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/lib" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER.2141790994.f2812" name="Emit diagnostic identifier numbers (--display_error_number)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Detailed link information data-base into <file> (- -xml_link_info, -xml_link_info). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO.1355214148.f2812" name="Detailed link information data-base into <file> (--xml_link_info, -xml_link_info)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO" value="F2812_CAN_NOR_linkInfo.xml" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify program entry point for the output module (- -entry_point, -e). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT.862275171.f2812" name="Specify program entry point for the output module (--entry_point, -e)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT" value="_c_int00" valueType="string" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS.1082823352.f2812" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS.1635863502.f2812" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS" />
|
||||
<!-- Описывает inputType: Generated Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS.209596448.f2812" name="Generated Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Hex Utility. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.183039420.f2812" name="C2000 Hex Utility" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex">
|
||||
<!-- Описывает outputType: Binary File. -->
|
||||
<outputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN.139478444.f2812" name="Binary File" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN" />
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<!-- Ограничивает компилируемые исходники проекта: sourceEntries. -->
|
||||
<sourceEntries>
|
||||
<!-- Описывает entry: entry. -->
|
||||
<entry excluding="Release|Release" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" />
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: org.eclipse.cdt.core.externalSettings. -->
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings" />
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: cdtBuildSystem. -->
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<!-- Регистрирует тип самостоятельного C2000-проекта: без этой записи CCS не определяет compiler definition при импорте. -->
|
||||
<project id="F2812_CAN_NOR.com.ti.ccstudio.buildDefinitions.C2000.ProjectType.1" name="C2000" projectType="com.ti.ccstudio.buildDefinitions.C2000.ProjectType" />
|
||||
</storageModule>
|
||||
</cproject>
|
||||
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>F2812_CAN_NOR</name>
|
||||
<!-- Описывает comment: comment. -->
|
||||
<comment>Отдельный постоянный загрузчик ProtoCAN для F2812</comment>
|
||||
<!-- Описывает projects: projects. -->
|
||||
<projects />
|
||||
<!-- Описывает buildSpec: buildSpec. -->
|
||||
<buildSpec>
|
||||
<!-- Описывает buildCommand: buildCommand. -->
|
||||
<buildCommand>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<!-- Описывает arguments: arguments. -->
|
||||
<arguments />
|
||||
</buildCommand>
|
||||
<!-- Описывает buildCommand: buildCommand. -->
|
||||
<buildCommand>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<!-- Описывает arguments: arguments. -->
|
||||
<arguments />
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<!-- Описывает natures: natures. -->
|
||||
<natures>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>com.ti.ccstudio.core.ccsNature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<!-- Описывает linkedResources: linkedResources. -->
|
||||
<linkedResources>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP281x_CpuTimers.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_CpuTimers.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP281x_GlobalVariableDefs.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_GlobalVariableDefs.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP281x_PieCtrl.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_PieCtrl.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP281x_SysCtrl.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_SysCtrl.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP281x_usDelay.asm</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f2812/source/DSP281x_usDelay.asm</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>DSP281x_Headers_nonBIOS.cmd</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f2812/cmd/DSP281x_Headers_nonBIOS.cmd</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
<!-- Описывает variableList: variableList. -->
|
||||
<variableList>
|
||||
<!-- Описывает variable: variable. -->
|
||||
<variable>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>PCAN_ROOT</name>
|
||||
<!-- Описывает value: value. -->
|
||||
<value>$%7BPARENT-3-PROJECT_LOC%7D</value>
|
||||
</variable>
|
||||
</variableList>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,28 @@
|
||||
MEMORY /* Постоянный загрузчик F2812 хранится во внутренней Flash, обновляемые данные — во внешней AM29LV800BT. */
|
||||
{ /* Адреса указаны в 16-битных словах C28x, независимо от размера файлов CAN. */
|
||||
PAGE 0: /* Исполняемый код и его копируемая RAM-часть. */
|
||||
FLASHA : origin = 0x3F6000, length = 0x001F80 /* Сектор A исключает зарезервированные слова CSM в верхних 128 словах. */
|
||||
BEGIN : origin = 0x3F7FF6, length = 0x000002 /* Аппаратный Flash boot F2812 начинает длинный переход из двух слов. */
|
||||
RAMFUNCS : origin = 0x008F00, length = 0x000100 /* Последние 256 слов L0 содержат InitFlash и исключены из SCI8 payload приложения. */
|
||||
RESET : origin = 0x3FFFC0, length = 0x000002 /* ROM reset не программируется при установке загрузчика. */
|
||||
PAGE 1: /* Рабочая RAM постоянно работающего загрузчика не должна входить в загружаемый файл. */
|
||||
RAMM0 : origin = 0x000050, length = 0x0003B0 /* Исключает первые 80 слов Boot ROM scratch. */
|
||||
RAMM1 : origin = 0x000400, length = 0x000400 /* Отдельный стек на 1024 слова совпадает с аппаратным банком M1. */
|
||||
RAMDATA : origin = 0x009000, length = 0x001000 /* Банк L1 хранит очередь CAN и состояния загрузчика до перехода в приложение. */
|
||||
} /* Верхний H0 и внешняя SRAM остаются доступны payload приложения. */
|
||||
SECTIONS /* Ни одна загружаемая секция OUT не записывается во внешнюю NOR автоматически. */
|
||||
{ /* Все команды программирования NOR исполняются из внутреннего сектора A. */
|
||||
codestart : > BEGIN, PAGE = 0 /* Направляет аппаратный boot в watchdog-safe C startup. */
|
||||
.text : > FLASHA, PAGE = 0 /* Размещает общий ProtoCAN, driver NOR и проверку SCI8 в постоянной Flash. */
|
||||
.fast_run : > FLASHA, PAGE = 0 /* Штатный DSP281x_usDelay вызывается ещё из InitSysCtrl до копирования ramfuncs, поэтому его LOAD/RUN должны сразу находиться во Flash. */
|
||||
.cinit : > FLASHA, PAGE = 0 /* Таблицы ROM-модели инициализируют состояние до main. */
|
||||
.pinit : > FLASHA, PAGE = 0 /* Сохраняет стандартный startup для возможных статических конструкторов. */
|
||||
.econst : > FLASHA, PAGE = 0 /* Константы не расходуют ограниченную RAM L1. */
|
||||
.switch : > FLASHA, PAGE = 0 /* Таблицы switch остаются доступны во время erase внешнего чипа. */
|
||||
ramfuncs : LOAD = FLASHA, RUN = RAMFUNCS, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 /* InitFlash копируется в внутреннюю RAM до изменения таймингов Flash. */
|
||||
.stack : > RAMM1, PAGE = 1 /* Стек не пересекает RAM назначения проверяемого образа. */
|
||||
.ebss : > RAMDATA, PAGE = 1 /* Состояния очереди и текущей сессии исключены из разрешённых SCI8 адресов. */
|
||||
.esysmem : > RAMDATA, PAGE = 1 /* Поддерживает стандартную секцию runtime, хотя алгоритм не требует heap. */
|
||||
.fast_vars1 : > RAMDATA, PAGE = 1 /* Подключает штатный HSPCLK выбранного TI SDK без размещения случайной orphan-секции. */
|
||||
.reset : > RESET, PAGE = 0, TYPE = DSECT /* Не выдаёт ROM reset за программируемую часть OUT. */
|
||||
} /* Не создаёт секции OTP или паролей CSM. */
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "DSP281x_Device.h" /* Использует оригинальные TI определения GPIO и XINTF F2812. */
|
||||
#include "../../../ports/tms320f2812/boot2812.h" /* Получает отдельный аппаратный профиль внешней NOR ПМ67. */
|
||||
static void operation(unsigned int a, unsigned int b, unsigned int c, unsigned int d) /* Повторяет управляющую защёлку CPLD из big_dsp_module.c штатной платы. */
|
||||
{ /* GPIOA13/A14/A15 и GPIOB13 задают код, GPIOB15 формирует строб. */
|
||||
EALLOW; /* Разрешает запись системных GPIO платы. */
|
||||
GpioDataRegs.GPADAT.bit.GPIOA13 = a; GpioDataRegs.GPADAT.bit.GPIOA14 = b; /* Первые два бита аппаратной команды соответствуют oper_mode1/2. */
|
||||
GpioDataRegs.GPADAT.bit.GPIOA15 = c; GpioDataRegs.GPBDAT.bit.GPIOB13 = d; /* Третий и четвёртый биты повторяют штатный write_oper. */
|
||||
asm(" NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 0; /* Снимает строб после установки всех четырёх битов команды. */
|
||||
asm(" RPT #2 || NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 1; /* Даёт защёлке время установления и формирует активный фронт. */
|
||||
asm(" RPT #2 || NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 0; /* Возвращает строб в исходное состояние с выдержкой как в рабочем драйвере. */
|
||||
asm(" RPT #2 || NOP"); EDIS; /* Завершает длительность импульса до следующей команды CPLD. */
|
||||
} /* Команда не изменяет выбранные аппаратные boot-перемычки контроллера. */
|
||||
void Boot2812_BoardInit(void) /* Настраивает подтверждённую схему ПМ67 с AM29LV800BT на XINTF zone6. */
|
||||
{ /* Значения линий взяты из setup_oper_line/init_flash/xintf_zone6and7_timing действующего проекта BALZAM_167. */
|
||||
EALLOW; /* GPIO mux/direction и XINTF изменяются в разрешённом защищённом контексте. */
|
||||
GpioMuxRegs.GPAMUX.bit.C1TRIP_GPIOA13 = 0; GpioMuxRegs.GPAMUX.bit.C2TRIP_GPIOA14 = 0; GpioMuxRegs.GPAMUX.bit.C3TRIP_GPIOA15 = 0; /* Выбирает GPIO для трёх командных линий CPLD вместо функций event manager. */
|
||||
GpioMuxRegs.GPBMUX.bit.C4TRIP_GPIOB13 = 0; GpioMuxRegs.GPBMUX.bit.C6TRIP_GPIOB15 = 0; /* Освобождает четвёртый бит команды и строб CPLD. */
|
||||
GpioMuxRegs.GPADIR.bit.GPIOA13 = 1; GpioMuxRegs.GPADIR.bit.GPIOA14 = 1; GpioMuxRegs.GPADIR.bit.GPIOA15 = 1; /* Переводит командные линии A в выходы, как рабочий драйвер платы. */
|
||||
GpioMuxRegs.GPBDIR.bit.GPIOB13 = 1; GpioMuxRegs.GPBDIR.bit.GPIOB15 = 1; /* Разрешает выдачу четвёртого бита и импульса защёлки. */
|
||||
XintfRegs.XINTCNF2.bit.XTIMCLK = 1; XintfRegs.XINTCNF2.bit.WRBUFF = 0; /* XTIMCLK=SYSCLKOUT/2; отключённая буферизация сохраняет порядок unlock-циклов AMD. */
|
||||
XintfRegs.XINTCNF2.bit.CLKOFF = 0; XintfRegs.XINTCNF2.bit.CLKMODE = 0; XintfRegs.XINTCNF2.bit.MPNMC = 0; /* Повторяет штатный режим XCLKOUT и микроконтроллерный boot платы. */
|
||||
XintfRegs.XTIMING6.bit.XWRLEAD = 3; XintfRegs.XTIMING6.bit.XWRACTIVE = 7; XintfRegs.XTIMING6.bit.XWRTRAIL = 3; /* Времена записи NOR повторяют проверенный flash_tools/init_flash платы в единицах XTIMCLK. */
|
||||
XintfRegs.XTIMING6.bit.XRDLEAD = 3; XintfRegs.XTIMING6.bit.XRDACTIVE = 3; XintfRegs.XTIMING6.bit.XRDTRAIL = 3; /* Времена чтения соответствуют штатному профилю AM29LV800BT-70EI. */
|
||||
XintfRegs.XTIMING6.bit.X2TIMING = 0; XintfRegs.XTIMING6.bit.USEREADY = 0; XintfRegs.XTIMING6.bit.READYMODE = 0; XintfRegs.XTIMING6.bit.XSIZE = 3; /* Выбирает 16-битную зону без внешнего READY и без дополнительного удвоения тактов. */
|
||||
XintfRegs.XTIMING2.bit.XWRLEAD = 3; XintfRegs.XTIMING2.bit.XWRACTIVE = 7; XintfRegs.XTIMING2.bit.XWRTRAIL = 3; /* Консервативный x16 режим внешней SRAM позволяет загружать приложение в zone2. */
|
||||
XintfRegs.XTIMING2.bit.XRDLEAD = 3; XintfRegs.XTIMING2.bit.XRDACTIVE = 7; XintfRegs.XTIMING2.bit.XRDTRAIL = 3; /* Удлинённое чтение SRAM не зависит от коротких прикладных таймингов. */
|
||||
XintfRegs.XTIMING2.bit.X2TIMING = 0; XintfRegs.XTIMING2.bit.USEREADY = 0; XintfRegs.XTIMING2.bit.READYMODE = 0; XintfRegs.XTIMING2.bit.XSIZE = 3; /* Не включает неподтверждённую линию READY платы. */
|
||||
asm(" RPT #7 || NOP"); EDIS; /* Сбрасывает pipeline после изменения XINTF до первого внешнего чтения. */
|
||||
operation(1U, 1U, 1U, 1U); operation(1U, 0U, 1U, 0U); operation(0U, 0U, 0U, 0U); /* Штатные select_nothing, select_strob_67_for_flash, select_work_with_flash выбирают CPU-доступ к NOR. */
|
||||
} /* Изменение схемы CPLD требует отдельного профиля платы, а не другого размера EEPROM. */
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../../ports/tms320f2812/boot_store.c" /* Подключает проверку SCI8 и публикацию NOR manifest без копирования кода в проект CCS. */
|
||||
@@ -0,0 +1,12 @@
|
||||
.ref _c_int00 ; Стандартный COFF startup применяет .cinit и вызывает main после отключения раннего watchdog.
|
||||
.sect "codestart" ; Boot ROM передаёт управление двухсловному переходу по аппаратному адресу слова 0x33FFF6.
|
||||
LB flash_boot_start ; Переходит к короткой подготовке C28x во Flash, сохраняя точный размер аппаратного входа два слова.
|
||||
.text ; Последовательность взята из штатного TI DSP2833x_CodeStartBranch.asm и размещается в секторе основного кода.
|
||||
flash_boot_start: ; Отключает watchdog до возможной длительной обработки таблиц инициализации C, а не только после входа в main.
|
||||
SETC OBJMODE ; Выбирает C28x object mode, требуемый стандартным COFF startup процессора F28335.
|
||||
EALLOW ; Разрешает запись защищённого регистра WDCR перед запуском C runtime.
|
||||
MOVZ DP, #7029h>>6 ; Адрес слова WDCR=0x7029 из карты F28335; DP выбирает соответствующую страницу по 64 слова.
|
||||
MOV @7029h, #0068h ; Значение 0x0068 содержит контрольные биты WDCHK=101 и WDDIS=1, как официальный TI startup.
|
||||
EDIS ; Возвращает защиту системных регистров перед переходом в библиотечную инициализацию.
|
||||
LB _c_int00 ; Применяет штатную ROM-модель инициализации и затем запускает текущий main 167.
|
||||
.end ; Завершает модуль, не добавляя произвольных данных рядом с CSM-паролями сектора A.
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
#include "../../../ports/tms320f2812/nor_flash.c" /* Собирает канонический драйвер AM29LV800BT из templates, сохраняя hardware callbacks отдельно от протокола. */
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../../src/pcan_boot.c" /* Подключает общий ProtoCAN codec, сессии и CRC32 без второй реализации протокола. */
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<configurations XML_version="1.2" id="configurations_0">
|
||||
<configuration XML_version="1.2" id="configuration_0">
|
||||
<instance XML_version="1.2" desc="Sauris SAU510-USB Iso Plus Emulator" href="connections/SAU510USBIsoPlus_Connection.xml" id="Sauris SAU510-USB Iso Plus Emulator" xml="SAU510USBIsoPlus_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Sauris SAU510-USB Iso Plus Emulator">
|
||||
<instance XML_version="1.2" href="drivers/sau510c28x.xml" id="drivers" xml="sau510c28x.xml" xmlpath="drivers"/>
|
||||
<platform XML_version="1.2" id="platform_0">
|
||||
<instance XML_version="1.2" desc="TMS320F2812" href="devices/f2812.xml" id="TMS320F2812" xml="f2812.xml" xmlpath="devices"/>
|
||||
</platform>
|
||||
</connection>
|
||||
</configuration>
|
||||
</configurations>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?ccsproject version="1.0"?>
|
||||
<projectOptions>
|
||||
<!-- Описывает ccsVersion: 12.3.0. -->
|
||||
<ccsVersion value="12.3.0" />
|
||||
<!-- Описывает deviceVariant: TMS320C28XX.TMS320F28335. -->
|
||||
<deviceVariant value="TMS320C28XX.TMS320F28335" />
|
||||
<!-- Описывает deviceFamily: C2000. -->
|
||||
<deviceFamily value="C2000" />
|
||||
<!-- Описывает deviceEndianness: little. -->
|
||||
<deviceEndianness value="little" />
|
||||
<!-- Описывает codegenToolVersion: 22.6.0.LTS. -->
|
||||
<codegenToolVersion value="22.6.0.LTS" />
|
||||
<!-- Описывает isElfFormat: false. -->
|
||||
<isElfFormat value="false" />
|
||||
<!-- Описывает rts: rts2800_fpu32.lib. -->
|
||||
<rts value="rts2800_fpu32.lib" />
|
||||
<!-- Описывает isTargetManual: false. -->
|
||||
<isTargetManual value="false" />
|
||||
</projectOptions>
|
||||
@@ -0,0 +1,326 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?fileVersion 4.0.0?>
|
||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<!-- Описывает storageModule: org.eclipse.cdt.core.settings. -->
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<!-- Описывает cconfiguration: cconfiguration. -->
|
||||
<cconfiguration id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f28335">
|
||||
<!-- Описывает storageModule: Debug. -->
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f28335" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<!-- Описывает externalSettings: externalSettings. -->
|
||||
<externalSettings />
|
||||
<!-- Описывает extensions: extensions. -->
|
||||
<extensions>
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.binaryparser.CoffParser.f28335" point="org.eclipse.cdt.core.BinaryParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.CoffErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.AsmErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.LinkErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: cdtBuildSystem. -->
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<!-- Описывает configuration: Debug. -->
|
||||
<configuration artifactExtension="out" artifactName="F28335_CAN_AB" buildProperties="" cleanCommand="${CG_CLEAN_CMD}" description="" id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f28335" name="Debug" parent="com.ti.ccstudio.buildDefinitions.C2000.Debug" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
||||
<!-- Описывает folderInfo: /. -->
|
||||
<folderInfo id="com.ti.ccstudio.buildDefinitions.C2000.Debug.952393063.f28335." name="/" resourcePath="">
|
||||
<!-- Описывает toolChain: TI Build Tools. -->
|
||||
<toolChain id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.DebugToolchain.1656408937.f28335" name="TI Build Tools" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.DebugToolchain" targetTool="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerDebug.1238234098.f28335">
|
||||
<!-- Задаёт параметр сборки: option. -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS.1809066827.f28335" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS" valueType="stringList">
|
||||
<!-- Передаёт значение параметра: DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F28335. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F28335" />
|
||||
<!-- Передаёт значение параметра: DEVICE_ENDIANNESS=little. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_ENDIANNESS=little" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_FORMAT=COFF. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_FORMAT=COFF" />
|
||||
<!-- Передаёт значение параметра: LINKER_COMMAND_FILE=F28335_CAN_AB.cmd. -->
|
||||
<listOptionValue builtIn="false" value="LINKER_COMMAND_FILE=F28335_CAN_AB.cmd" />
|
||||
<!-- Передаёт значение параметра: RUNTIME_SUPPORT_LIBRARY=rts2800_fpu32.lib. -->
|
||||
<listOptionValue builtIn="false" value="RUNTIME_SUPPORT_LIBRARY=rts2800_fpu32.lib" />
|
||||
<!-- Передаёт значение параметра: CCS_MBS_VERSION=6.1.3. -->
|
||||
<listOptionValue builtIn="false" value="CCS_MBS_VERSION=6.1.3" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_TYPE=executable. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_TYPE=executable" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Compiler version. -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION.1182984787.f28335" name="Compiler version" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION" value="22.6.0.LTS" valueType="string" />
|
||||
<!-- Описывает targetPlatform: Platform. -->
|
||||
<targetPlatform id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformDebug.2023332194.f28335" name="Platform" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformDebug" />
|
||||
<!-- Описывает builder: GNU Make. -->
|
||||
<builder buildPath="${BuildDirectory}" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderDebug.1704049401.f28335" keepEnvironmentInBuildfile="false" name="GNU Make" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderDebug" />
|
||||
<!-- Описывает tool: C2000 Compiler. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerDebug.68471068.f28335" name="C2000 Compiler" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerDebug">
|
||||
<!-- Задаёт параметр сборки: Option deprecated, set by default (- -large_memory_model, -ml). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL.1683926605.f28335" name="Option deprecated, set by default (--large_memory_model, -ml)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Unified memory (- -unified_memory, -mt). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY.884660743.f28335" name="Unified memory (--unified_memory, -mt)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Processor version (- -silicon_version, -v). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.750562333.f28335" name="Processor version (--silicon_version, -v)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.28" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Specify floating point support (- -float_support). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.FLOAT_SUPPORT.1723304888.f28335" name="Specify floating point support (--float_support)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.FLOAT_SUPPORT" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.FLOAT_SUPPORT.fpu32" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Optimization level (- -opt_level, -O). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.1217592973.f28335" name="Optimization level (--opt_level, -O)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.3" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Place each function in a separate subsection (- -gen_func_subsections, -mo). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.eeprom.40.f28335" name="Place each function in a separate subsection (--gen_func_subsections, -mo)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.on" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Speed vs. size trade-offs (- -opt_for_speed, -mf). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.1885063317.f28335" name="Speed vs. size trade-offs (--opt_for_speed, -mf)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.0" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Add dir to #include search path (- -include_path, -I). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH.24504397.f28335" name="Add dir to #include search path (--include_path, -I)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH" valueType="includePath">
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f28335/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f28335/include" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f28335/common/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f28335/common/include" />
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/include. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/include" />
|
||||
<listOptionValue builtIn="false" value="C:/ti/controlSUITE/libs/utilities/flash_api/2833x/28335/v210/include" /> <!-- Подключает официальный TI Flash API v2.10 F28335 для обновления секторов B–H по CAN. -->
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Pre-define NAME (- -define, -D). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE.409484878.f28335" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE" valueType="definedSymbols">
|
||||
<!-- Передаёт значение параметра: LARGE_MODEL. -->
|
||||
<listOptionValue builtIn="false" value="LARGE_MODEL" />
|
||||
<!-- Передаёт значение параметра: EEPROM_M95M02=1. -->
|
||||
<listOptionValue builtIn="false" value="EEPROM_M95M02=1" />
|
||||
<!-- Передаёт значение параметра: F28335_BOOT_LOADER=1. -->
|
||||
<listOptionValue builtIn="false" value="F28335_BOOT_LOADER=1" />
|
||||
<listOptionValue builtIn="false" value="F28335_CAN_FLASH_UPDATE=1" /> <!-- Разрешает выбор внутренней Flash только при реально подключённом TI API. -->
|
||||
<!-- Передаёт значение параметра: _DEBUG. -->
|
||||
<listOptionValue builtIn="false" value="_DEBUG" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Debugging model. -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEBUGGING_MODEL.1803616155.f28335" name="Debugging model" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEBUGGING_MODEL" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEBUGGING_MODEL.SYMDEBUG__DWARF" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number, -pden). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER.362706119.f28335" name="Emit diagnostic identifier numbers (--display_error_number, -pden)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Application binary interface [See 'General' page to edit] (- -abi). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.1036638377.f28335" name="Application binary interface [See 'General' page to edit] (--abi)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.coffabi" valueType="enumerated" />
|
||||
<!-- Описывает inputType: C Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS.413246530.f28335" name="C Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS" />
|
||||
<!-- Описывает inputType: C++ Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS.1626831603.f28335" name="C++ Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS.291886960.f28335" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS.231319110.f28335" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Linker. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerDebug.1238234098.f28335" name="C2000 Linker" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerDebug">
|
||||
<!-- Задаёт параметр сборки: Set C system stack size (- -stack_size, -stack). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE.1288161308.f28335" name="Set C system stack size (--stack_size, -stack)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE" value="0x3f0" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Link information (map) listed into <file> (- -map_file, -m). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE.1478857036.f28335" name="Link information (map) listed into <file> (--map_file, -m)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE" value="F28335_CAN_AB.map" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify output file name (- -output_file, -o). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE.1263270138.f28335" name="Specify output file name (--output_file, -o)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE" value="F28335_CAN_AB.out" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Include library file or command file as input (- -library, -l). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY.1967188356.f28335" name="Include library file or command file as input (--library, -l)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY" valueType="libs">
|
||||
<!-- Передаёт значение параметра: rts2800_fpu32.lib. -->
|
||||
<listOptionValue builtIn="false" value="rts2800_fpu32.lib" />
|
||||
<listOptionValue builtIn="false" value="Flash28335_API_V210.lib" /> <!-- Официальные erase/program/verify копируются в RAM перед занятостью общего банка Flash. -->
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Add <dir> to library search path (- -search_path, -i). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH.1097407993.f28335" name="Add <dir> to library search path (--search_path, -i)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH" valueType="libPaths">
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/lib. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/lib" />
|
||||
<listOptionValue builtIn="false" value="C:/ti/controlSUITE/libs/utilities/flash_api/2833x/28335/v210/lib" /> <!-- Находит установленную библиотеку TI без добавления её двоичного содержимого в проект. -->
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER.2141790994.f28335" name="Emit diagnostic identifier numbers (--display_error_number)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Detailed link information data-base into <file> (- -xml_link_info, -xml_link_info). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO.1355214148.f28335" name="Detailed link information data-base into <file> (--xml_link_info, -xml_link_info)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO" value="F28335_CAN_AB_linkInfo.xml" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify program entry point for the output module (- -entry_point, -e). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT.862275171.f28335" name="Specify program entry point for the output module (--entry_point, -e)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT" value="_c_int00" valueType="string" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS.1082823352.f28335" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS.1635863502.f28335" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS" />
|
||||
<!-- Описывает inputType: Generated Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS.209596448.f28335" name="Generated Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Hex Utility. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.183039420.f28335" name="C2000 Hex Utility" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex">
|
||||
<!-- Описывает outputType: Binary File. -->
|
||||
<outputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN.139478444.f28335" name="Binary File" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN" />
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<!-- Ограничивает компилируемые исходники проекта: sourceEntries. -->
|
||||
<sourceEntries>
|
||||
<!-- Описывает entry: entry. -->
|
||||
<entry excluding="Debug|Release" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" />
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: org.eclipse.cdt.core.externalSettings. -->
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings" />
|
||||
</cconfiguration>
|
||||
<!-- Описывает cconfiguration: cconfiguration. -->
|
||||
<cconfiguration id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f28335">
|
||||
<!-- Описывает storageModule: Release. -->
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f28335" moduleId="org.eclipse.cdt.core.settings" name="Release">
|
||||
<!-- Описывает externalSettings: externalSettings. -->
|
||||
<externalSettings />
|
||||
<!-- Описывает extensions: extensions. -->
|
||||
<extensions>
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.binaryparser.CoffParser.f28335" point="org.eclipse.cdt.core.BinaryParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.CoffErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.AsmErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
<!-- Описывает extension: extension. -->
|
||||
<extension id="com.ti.ccstudio.errorparser.LinkErrorParser.f28335" point="org.eclipse.cdt.core.ErrorParser" />
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: cdtBuildSystem. -->
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<!-- Описывает configuration: Release. -->
|
||||
<configuration artifactExtension="out" artifactName="F28335_CAN_AB" buildProperties="" cleanCommand="${CG_CLEAN_CMD}" description="" id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f28335" name="Release" parent="com.ti.ccstudio.buildDefinitions.C2000.Release" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
||||
<!-- Описывает folderInfo: /. -->
|
||||
<folderInfo id="com.ti.ccstudio.buildDefinitions.C2000.Release.952393063.f28335." name="/" resourcePath="">
|
||||
<!-- Описывает toolChain: TI Build Tools. -->
|
||||
<toolChain id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.ReleaseToolchain.1656408937.f28335" name="TI Build Tools" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.ReleaseToolchain" targetTool="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerRelease.1238234098.f28335">
|
||||
<!-- Задаёт параметр сборки: option. -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS.1809066827.f28335" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_TAGS" valueType="stringList">
|
||||
<!-- Передаёт значение параметра: DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F28335. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_CONFIGURATION_ID=TMS320C28XX.TMS320F28335" />
|
||||
<!-- Передаёт значение параметра: DEVICE_ENDIANNESS=little. -->
|
||||
<listOptionValue builtIn="false" value="DEVICE_ENDIANNESS=little" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_FORMAT=COFF. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_FORMAT=COFF" />
|
||||
<!-- Передаёт значение параметра: LINKER_COMMAND_FILE=F28335_CAN_AB.cmd. -->
|
||||
<listOptionValue builtIn="false" value="LINKER_COMMAND_FILE=F28335_CAN_AB.cmd" />
|
||||
<!-- Передаёт значение параметра: RUNTIME_SUPPORT_LIBRARY=rts2800_fpu32.lib. -->
|
||||
<listOptionValue builtIn="false" value="RUNTIME_SUPPORT_LIBRARY=rts2800_fpu32.lib" />
|
||||
<!-- Передаёт значение параметра: CCS_MBS_VERSION=6.1.3. -->
|
||||
<listOptionValue builtIn="false" value="CCS_MBS_VERSION=6.1.3" />
|
||||
<!-- Передаёт значение параметра: OUTPUT_TYPE=executable. -->
|
||||
<listOptionValue builtIn="false" value="OUTPUT_TYPE=executable" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Compiler version. -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION.1182984787.f28335" name="Compiler version" superClass="com.ti.ccstudio.buildDefinitions.core.OPT_CODEGEN_VERSION" value="22.6.0.LTS" valueType="string" />
|
||||
<!-- Описывает targetPlatform: Platform. -->
|
||||
<targetPlatform id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformRelease.2023332194.f28335" name="Platform" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.targetPlatformRelease" />
|
||||
<!-- Описывает builder: GNU Make. -->
|
||||
<builder buildPath="${BuildDirectory}" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderRelease.1704049401.f28335" keepEnvironmentInBuildfile="false" name="GNU Make" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.builderRelease" />
|
||||
<!-- Описывает tool: C2000 Compiler. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerRelease.68471068.f28335" name="C2000 Compiler" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.compilerRelease">
|
||||
<!-- Задаёт параметр сборки: Option deprecated, set by default (- -large_memory_model, -ml). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL.1683926605.f28335" name="Option deprecated, set by default (--large_memory_model, -ml)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.LARGE_MEMORY_MODEL" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Unified memory (- -unified_memory, -mt). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY.884660743.f28335" name="Unified memory (--unified_memory, -mt)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.UNIFIED_MEMORY" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Processor version (- -silicon_version, -v). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.750562333.f28335" name="Processor version (--silicon_version, -v)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.SILICON_VERSION.28" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Specify floating point support (- -float_support). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.FLOAT_SUPPORT.1723304888.f28335" name="Specify floating point support (--float_support)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.FLOAT_SUPPORT" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.FLOAT_SUPPORT.fpu32" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Optimization level (- -opt_level, -O). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.1217592973.f28335" name="Optimization level (--opt_level, -O)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_LEVEL.3" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Place each function in a separate subsection (- -gen_func_subsections, -mo). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.eeprom.40.f28335" name="Place each function in a separate subsection (--gen_func_subsections, -mo)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.GEN_FUNC_SUBSECTIONS.on" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Speed vs. size trade-offs (- -opt_for_speed, -mf). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.1885063317.f28335" name="Speed vs. size trade-offs (--opt_for_speed, -mf)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.OPT_FOR_SPEED.0" valueType="enumerated" />
|
||||
<!-- Задаёт параметр сборки: Add dir to #include search path (- -include_path, -I). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH.24504397.f28335" name="Add dir to #include search path (--include_path, -I)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH" valueType="includePath">
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f28335/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f28335/include" />
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}/../../../vendor/ti/f28335/common/include. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../../../vendor/ti/f28335/common/include" />
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/include. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/include" />
|
||||
<listOptionValue builtIn="false" value="C:/ti/controlSUITE/libs/utilities/flash_api/2833x/28335/v210/include" /> <!-- Подключает официальный TI Flash API v2.10 F28335 для обновления секторов B–H по CAN. -->
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Pre-define NAME (- -define, -D). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE.409484878.f28335" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DEFINE" valueType="definedSymbols">
|
||||
<!-- Передаёт значение параметра: LARGE_MODEL. -->
|
||||
<listOptionValue builtIn="false" value="LARGE_MODEL" />
|
||||
<!-- Передаёт значение параметра: EEPROM_M95M02=1. -->
|
||||
<listOptionValue builtIn="false" value="EEPROM_M95M02=1" />
|
||||
<!-- Передаёт значение параметра: F28335_BOOT_LOADER=1. -->
|
||||
<listOptionValue builtIn="false" value="F28335_BOOT_LOADER=1" />
|
||||
<listOptionValue builtIn="false" value="F28335_CAN_FLASH_UPDATE=1" /> <!-- Разрешает выбор внутренней Flash только при реально подключённом TI API. -->
|
||||
<!-- Передаёт значение параметра: _DEBUG. -->
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Releaseging model. -->
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number, -pden). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER.362706119.f28335" name="Emit diagnostic identifier numbers (--display_error_number, -pden)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Application binary interface [See 'General' page to edit] (- -abi). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.1036638377.f28335" name="Application binary interface [See 'General' page to edit] (--abi)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI" value="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.ABI.coffabi" valueType="enumerated" />
|
||||
<!-- Описывает inputType: C Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS.413246530.f28335" name="C Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__C_SRCS" />
|
||||
<!-- Описывает inputType: C++ Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS.1626831603.f28335" name="C++ Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__CPP_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS.291886960.f28335" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM_SRCS" />
|
||||
<!-- Описывает inputType: Assembly Sources. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS.231319110.f28335" name="Assembly Sources" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compiler.inputType__ASM2_SRCS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Linker. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerRelease.1238234098.f28335" name="C2000 Linker" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exe.linkerRelease">
|
||||
<!-- Задаёт параметр сборки: Set C system stack size (- -stack_size, -stack). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE.1288161308.f28335" name="Set C system stack size (--stack_size, -stack)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.STACK_SIZE" value="0x3f0" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Link information (map) listed into <file> (- -map_file, -m). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE.1478857036.f28335" name="Link information (map) listed into <file> (--map_file, -m)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.MAP_FILE" value="F28335_CAN_AB.map" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify output file name (- -output_file, -o). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE.1263270138.f28335" name="Specify output file name (--output_file, -o)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.OUTPUT_FILE" value="F28335_CAN_AB.out" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Include library file or command file as input (- -library, -l). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY.1967188356.f28335" name="Include library file or command file as input (--library, -l)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.LIBRARY" valueType="libs">
|
||||
<!-- Передаёт значение параметра: rts2800_fpu32.lib. -->
|
||||
<listOptionValue builtIn="false" value="rts2800_fpu32.lib" />
|
||||
<listOptionValue builtIn="false" value="Flash28335_API_V210.lib" /> <!-- Официальные erase/program/verify копируются в RAM перед занятостью общего банка Flash. -->
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Add <dir> to library search path (- -search_path, -i). -->
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH.1097407993.f28335" name="Add <dir> to library search path (--search_path, -i)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.SEARCH_PATH" valueType="libPaths">
|
||||
<!-- Передаёт значение параметра: ${CG_TOOL_ROOT}/lib. -->
|
||||
<listOptionValue builtIn="false" value="${CG_TOOL_ROOT}/lib" />
|
||||
<listOptionValue builtIn="false" value="C:/ti/controlSUITE/libs/utilities/flash_api/2833x/28335/v210/lib" /> <!-- Находит установленную библиотеку TI без добавления её двоичного содержимого в проект. -->
|
||||
<!-- Передаёт значение параметра: ${PROJECT_ROOT}. -->
|
||||
<listOptionValue builtIn="false" value="${PROJECT_ROOT}" />
|
||||
</option>
|
||||
<!-- Задаёт параметр сборки: Emit diagnostic identifier numbers (- -display_error_number). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER.2141790994.f28335" name="Emit diagnostic identifier numbers (--display_error_number)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.DISPLAY_ERROR_NUMBER" value="true" valueType="boolean" />
|
||||
<!-- Задаёт параметр сборки: Detailed link information data-base into <file> (- -xml_link_info, -xml_link_info). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO.1355214148.f28335" name="Detailed link information data-base into <file> (--xml_link_info, -xml_link_info)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.XML_LINK_INFO" value="F28335_CAN_AB_linkInfo.xml" valueType="string" />
|
||||
<!-- Задаёт параметр сборки: Specify program entry point for the output module (- -entry_point, -e). -->
|
||||
<option id="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT.862275171.f28335" name="Specify program entry point for the output module (--entry_point, -e)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.linkerID.ENTRY_POINT" value="_c_int00" valueType="string" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS.1082823352.f28335" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD_SRCS" />
|
||||
<!-- Описывает inputType: Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS.1635863502.f28335" name="Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__CMD2_SRCS" />
|
||||
<!-- Описывает inputType: Generated Linker Command Files. -->
|
||||
<inputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS.209596448.f28335" name="Generated Linker Command Files" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.exeLinker.inputType__GEN_CMDS" />
|
||||
</tool>
|
||||
<!-- Описывает tool: C2000 Hex Utility. -->
|
||||
<tool id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.183039420.f28335" name="C2000 Hex Utility" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex">
|
||||
<!-- Описывает outputType: Binary File. -->
|
||||
<outputType id="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN.139478444.f28335" name="Binary File" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.hex.outputType__BIN" />
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<!-- Ограничивает компилируемые исходники проекта: sourceEntries. -->
|
||||
<sourceEntries>
|
||||
<!-- Описывает entry: entry. -->
|
||||
<entry excluding="Release|Release" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" />
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: org.eclipse.cdt.core.externalSettings. -->
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings" />
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<!-- Описывает storageModule: cdtBuildSystem. -->
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<!-- Регистрирует тип самостоятельного C2000-проекта: без этой записи CCS не определяет compiler definition при импорте. -->
|
||||
<project id="F28335_CAN_AB.com.ti.ccstudio.buildDefinitions.C2000.ProjectType.1" name="C2000" projectType="com.ti.ccstudio.buildDefinitions.C2000.ProjectType" />
|
||||
</storageModule>
|
||||
</cproject>
|
||||
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>F28335_CAN_AB</name>
|
||||
<!-- Описывает comment: comment. -->
|
||||
<comment>Отдельный постоянный загрузчик ProtoCAN для F28335</comment>
|
||||
<!-- Описывает projects: projects. -->
|
||||
<projects />
|
||||
<!-- Описывает buildSpec: buildSpec. -->
|
||||
<buildSpec>
|
||||
<!-- Описывает buildCommand: buildCommand. -->
|
||||
<buildCommand>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<!-- Описывает arguments: arguments. -->
|
||||
<arguments />
|
||||
</buildCommand>
|
||||
<!-- Описывает buildCommand: buildCommand. -->
|
||||
<buildCommand>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<!-- Описывает arguments: arguments. -->
|
||||
<arguments />
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<!-- Описывает natures: natures. -->
|
||||
<natures>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>com.ti.ccstudio.core.ccsNature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<!-- Описывает nature: nature. -->
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<!-- Описывает linkedResources: linkedResources. -->
|
||||
<linkedResources>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP2833x_ADC_cal.asm</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_ADC_cal.asm</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP2833x_CpuTimers.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_CpuTimers.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP2833x_GlobalVariableDefs.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_GlobalVariableDefs.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP2833x_PieCtrl.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_PieCtrl.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP2833x_SysCtrl.c</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_SysCtrl.c</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>ti/DSP2833x_usDelay.asm</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_usDelay.asm</locationURI>
|
||||
</link>
|
||||
<!-- Подключает исходник или linker из общей библиотеки: link. -->
|
||||
<link>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>DSP2833x_Headers_nonBIOS.cmd</name>
|
||||
<!-- Описывает type: type. -->
|
||||
<type>1</type>
|
||||
<!-- Описывает locationURI: locationURI. -->
|
||||
<locationURI>PCAN_ROOT/vendor/ti/f28335/cmd/DSP2833x_Headers_nonBIOS.cmd</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
<!-- Описывает variableList: variableList. -->
|
||||
<variableList>
|
||||
<!-- Описывает variable: variable. -->
|
||||
<variable>
|
||||
<!-- Описывает name: name. -->
|
||||
<name>PCAN_ROOT</name>
|
||||
<!-- Описывает value: value. -->
|
||||
<value>$%7BPARENT-3-PROJECT_LOC%7D</value>
|
||||
</variable>
|
||||
</variableList>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,32 @@
|
||||
MEMORY /* Отделяет постоянный загрузчик от адресов RAM payload приложения 167. */
|
||||
{ /* Все адреса и длины указаны в 16-битных словах CPU C28x. */
|
||||
PAGE 0: /* Исполняемые секции и их Flash LOAD-адреса. */
|
||||
FLASHA : origin = 0x338000, length = 0x007F80 /* Сектор A до зарезервированной CSM-области содержит постоянный загрузчик. */
|
||||
BEGIN : origin = 0x33FFF6, length = 0x000002 /* Два слова аппаратного Flash boot перехода; пароли CSM не выделяются. */
|
||||
RAMFUNCS : origin = 0x00F800, length = 0x000800 /* Верхние 2048 слов RAM загрузчика нужны InitFlash и не входят в SCI8 payload приложения. */
|
||||
RAMAPI : origin = 0x008000, length = 0x001800 /* 6144 слова временно принадлежат TI Flash API; приложение использует эту RAM только после выхода загрузчика. */
|
||||
ADC_CAL : origin = 0x380080, length = 0x000009 /* Заводская калибровка TI используется без записи/стирания. */
|
||||
RESET : origin = 0x3FFFC0, length = 0x000002 /* Аппаратный reset находится в ROM и не программируется. */
|
||||
PAGE 1: /* Рабочие данные не пересекают код RAM-приложения ниже E000. */
|
||||
BOOT_SHARED : origin = 0x000050, length = 0x000008 /* Общие с приложением восемь слов NOINIT handoff после ROM scratch 0..4F. */
|
||||
RAMM0 : origin = 0x000058, length = 0x0003A8 /* Малый банк доступен служебным неинициализированным данным. */
|
||||
RAMM1 : origin = 0x000400, length = 0x000400 /* Стек на 1024 слова не меняет расположение при переходе в приложение. */
|
||||
RAMDATA : origin = 0x00E000, length = 0x001800 /* 6144 слова store/очереди; приложение использует их только после перехода в C startup. */
|
||||
} /* Завершает физическую карту постоянного загрузчика. */
|
||||
SECTIONS /* Не выделяет ни одного загружаемого слова в RAM приложения. */
|
||||
{ /* Инициализированные Flash-секции остаются в секторе A. */
|
||||
codestart : > BEGIN, PAGE = 0 /* Аппаратный переход передаёт управление watchdog-safe C startup. */
|
||||
flash_api : { -lFlash28335_API_V210.lib(.text) -lFlash28335_API_V210.lib(.econst) } LOAD = FLASHA, RUN = RAMAPI, LOAD_START(_FlashApiLoadStart), LOAD_END(_FlashApiLoadEnd), RUN_START(_FlashApiRunStart), PAGE = 0 /* Код и таблицы TI API выполняются из RAM, пока общий банк Flash занят изменением B–H. */
|
||||
.text : > FLASHA, PAGE = 0 /* Весь постоянный алгоритм и библиотеки исполняются из Flash A. */
|
||||
.cinit : > FLASHA, PAGE = 0 /* Таблицы ROM-модели подготавливают данные загрузчика до main. */
|
||||
.pinit : > FLASHA, PAGE = 0 /* Сохраняет стандартный порядок C runtime, если компилятор создаст эту секцию. */
|
||||
.econst : > FLASHA, PAGE = 0 /* Константы протокола и имена сервиса не расходуют рабочую RAM. */
|
||||
.switch : > FLASHA, PAGE = 0 /* Таблицы переходов находятся в постоянной области загрузчика. */
|
||||
ramfuncs : LOAD = FLASHA, RUN = RAMFUNCS, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 /* InitFlash копируется до изменения настроек самой Flash. */
|
||||
.boot_shared : > BOOT_SHARED, PAGE = 1, TYPE = NOINIT /* Не обнуляет session/slot, полученные через watchdog reset. */
|
||||
.stack : > RAMM1, PAGE = 1 /* Стек не пересекает ни handoff, ни загружаемые секции SCI8. */
|
||||
.ebss : > RAMDATA, PAGE = 1 /* Размещает очередь, журнал и структуры драйвера вне RAM payload. */
|
||||
.esysmem : > RAMDATA, PAGE = 1 /* Поддерживает стандартную секцию runtime без использования heap в алгоритме. */
|
||||
.reset : > RESET, PAGE = 0, TYPE = DSECT /* Reset-вектор ROM описывается, но не попадает в программируемый OUT. */
|
||||
.adc_cal : > ADC_CAL, PAGE = 0, TYPE = NOLOAD /* Сохраняет заводские данные ADC TI при установке загрузчика. */
|
||||
} /* Не создаёт секций CSM, OTP или паролей. */
|
||||
@@ -0,0 +1,12 @@
|
||||
.ref _c_int00 ; Стандартный COFF startup применяет .cinit и вызывает main после отключения раннего watchdog.
|
||||
.sect "codestart" ; Boot ROM передаёт управление двухсловному переходу по аппаратному адресу слова 0x33FFF6.
|
||||
LB flash_boot_start ; Переходит к короткой подготовке C28x во Flash, сохраняя точный размер аппаратного входа два слова.
|
||||
.text ; Последовательность взята из штатного TI DSP2833x_CodeStartBranch.asm и размещается в секторе основного кода.
|
||||
flash_boot_start: ; Отключает watchdog до возможной длительной обработки таблиц инициализации C, а не только после входа в main.
|
||||
SETC OBJMODE ; Выбирает C28x object mode, требуемый стандартным COFF startup процессора F28335.
|
||||
EALLOW ; Разрешает запись защищённого регистра WDCR перед запуском C runtime.
|
||||
MOVZ DP, #7029h>>6 ; Адрес слова WDCR=0x7029 из карты F28335; DP выбирает соответствующую страницу по 64 слова.
|
||||
MOV @7029h, #0068h ; Значение 0x0068 содержит контрольные биты WDCHK=101 и WDDIS=1, как официальный TI startup.
|
||||
EDIS ; Возвращает защиту системных регистров перед переходом в библиотечную инициализацию.
|
||||
LB _c_int00 ; Применяет штатную ROM-модель инициализации и затем запускает текущий main 167.
|
||||
.end ; Завершает модуль, не добавляя произвольных данных рядом с CSM-паролями сектора A.
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "DSP2833x_Device.h" /* Предоставляет реальные типы C28x, частоту SYSCLKOUT, CSM и маскирование IRQ. */
|
||||
#include "../../../ports/tms320f28335/f28335_flash_update.h" /* Подключает проверяемый алгоритм staging SCI8 и аппаратный контракт записи. */
|
||||
#include "Flash2833x_API_Library.h" /* Использует официальный TI Flash API v2.10 для F28335, а не запись Flash обычным указателем. */
|
||||
#include <string.h> /* Копирует код и таблицы TI API из постоянного сектора A во внутреннюю RAM до операции Flash. */
|
||||
extern Uint16 FlashApiLoadStart, FlashApiLoadEnd, FlashApiRunStart; /* Символы LOAD/RUN задаёт linker в адресуемых словах CPU. */
|
||||
static FLASH_ST flash_status; /* Диагностика TI хранится во внутренней RAM во время стирания и программирования. */
|
||||
static bool erase_flash(void *user) /* Стирает только область приложения, сохраняя постоянный загрузчик. */
|
||||
{ /* Даже IRQ из сектора A запрещены, поскольку F28335 имеет общий банк Flash для A–H. */
|
||||
Uint16 saved, status; (void)user; /* Сохраняет прежнее состояние IRQ и точный результат TI API. */
|
||||
saved = __disable_interrupts(); status = Flash_Erase(0x00FEU, &flash_status); __restore_interrupts(saved); /* Бит 0 — сектор A; маска FE выбирает только B–H согласно TI API v2.10. */
|
||||
return status == STATUS_SUCCESS; /* Ошибка erase запрещает любую последующую публикацию FAB1. */
|
||||
} /* После возврата TI API банк Flash снова доступен коду постоянного загрузчика. */
|
||||
static bool program_flash(void *user, uint32_t address, uint16_t *data, unsigned int words) /* Записывает и проверяет одну ограниченную порцию Flash. */
|
||||
{ /* Аппаратный слой повторно защищает сектор A независимо от валидатора SCI8. */
|
||||
Uint16 saved, status; (void)user; /* Результат API и маска IRQ не размещаются в обновляемой Flash. */
|
||||
if (!words || address < F28335_FLASH_APP_START || address >= F28335_FLASH_APP_STOP || words > F28335_FLASH_APP_STOP - address) return false; /* Не допускает даже частичного выхода за B–H, включая CSM и аппаратный boot. */
|
||||
saved = __disable_interrupts(); status = Flash_Program((Uint16 *)address, data, words, &flash_status); /* Во время программирования процессор выполняет только скопированный в RAM TI API. */
|
||||
if (!status) status = Flash_Verify((Uint16 *)address, data, words, &flash_status); /* Проверяет фактические слова до подтверждения этой порции. */
|
||||
__restore_interrupts(saved); return status == STATUS_SUCCESS; /* Возвращает исходное состояние IRQ даже при отказе записи или readback. */
|
||||
} /* Общий writer опубликует FAB1 лишь после успешной записи остальных порций. */
|
||||
static uint16_t read_flash(void *user, uint32_t address) /* Читает физическую Flash для итоговой проверки FAB1/CRC. */
|
||||
{ /* Этот callback вызывается только после окончания аппаратных операций TI API. */
|
||||
(void)user; return *(volatile Uint16 *)address; /* Адрес уже ограничен общим валидатором диапазоном приложения B–H. */
|
||||
} /* Программирование не подменяется чтением staging EEPROM. */
|
||||
bool F28335Boot_FlashProgram(f28335_flash_update_t *s) /* Единственная точка фактической записи внутренней Flash из CAN COMMIT. */
|
||||
{ /* Постоянный загрузчик может вернуться к CAN recovery при любой ошибке. */
|
||||
f28335_flash_ops_t ops; /* Аппаратные операции передаются проверяемому транспортно-независимому writer. */
|
||||
if (CsmRegs.CSMSCR.bit.SECURE) return false; /* Защищённый CSM запрещает стирание до любого вызова TI API. */
|
||||
memcpy(&FlashApiRunStart, &FlashApiLoadStart, &FlashApiLoadEnd - &FlashApiLoadStart); /* API и его константы должны быть в RAM даже при сохранении сектора A. */
|
||||
Flash_CPUScaleFactor = (Uint32)(1048576.0L * (200.0L * (long double)SYSCLKOUT / 1000000000.0L)); /* Формула TI IQ20 использует реальную частоту SYSCLKOUT в герцах. */
|
||||
Flash_CallbackPtr = 0; ops.erase = erase_flash; ops.program = program_flash; ops.read = read_flash; ops.user = 0; /* Исключает callback во Flash во время занятости общего банка A–H. */
|
||||
return f28335_flash_update_program(s, &ops); /* Итоговый ACK COMMIT появляется только после CRC физической Flash; REBOOT остаётся отдельной командой клиента. */
|
||||
} /* Постоянный boot, handoff и EEPROM-параметры не программируются. */
|
||||
@@ -0,0 +1,127 @@
|
||||
#include "DSP2833x_Device.h" /* Использует действующую частоту и штатную карту регистров той же платы 167. */
|
||||
#include "DSP2833x_Examples.h" /* Предоставляет InitSysCtrl, InitPieCtrl, InitFlash и управление Timer1. */
|
||||
#include "../../../ports/tms320f28335/f28335_can_boot.h" /* Подключает адрес, сервисы и очередь существующего загрузчика. */
|
||||
#include "../../../ports/tms320f28335/f28335_boot_platform.h" /* Использует общий handoff, SPI и энергонезависимый A/B-журнал. */
|
||||
#include <string.h> /* Копирует ramfuncs до настройки времен доступа Flash. */
|
||||
extern Uint16 RamfuncsLoadStart, RamfuncsLoadEnd, RamfuncsRunStart; /* Адреса LOAD/RUN задаёт отдельный linker загрузчика в словах C28x. */
|
||||
static f28335_boot_store_t image_store; /* Журнал загрузки остаётся в RAM E000..FFFF до перехода в приложение. */
|
||||
interrupt void boot_tick(void) /* Timer1 продолжает миллисекундные тайм-ауты общего CAN/SPI порта. */
|
||||
{ /* Этот ISR принадлежит постоянному загрузчику, а не кандидату приложения. */
|
||||
CpuTimer1.InterruptCount++; /* Один тик равен одной миллисекунде согласно ConfigCpuTimer ниже. */
|
||||
ServiceDog(); /* Длительные CRC/SPI операции загрузчика не должны сбрасывать аппарат во время обновления. */
|
||||
} /* Возвращает управление основному циклу загрузчика. */
|
||||
interrupt void boot_can_rx(void) /* CAN IRQ выполняет только короткий перенос принятых кадров в общую очередь. */
|
||||
{ /* Запись EEPROM, CRC и публикация pending остаются в главном цикле. */
|
||||
F28335CanBoot_RxISR(); /* Читает только выделенные mailbox 3 и 6 существующего адаптера. */
|
||||
PieCtrlRegs.PIEACK.all = 0x0100U; /* Бит 8 подтверждает группу PIE9, в которой находится ECAN0INTA. */
|
||||
} /* Позволяет принять следующее окно CAN, пока main занят SPI. */
|
||||
static void boot_can_init(void) /* Настраивает тот же физический CAN-A и 250 кбит/с, что приложение 167. */
|
||||
{ /* Загрузчик не использует прикладные mailbox 0..2 и не меняет адрес общего порта. */
|
||||
Uint32 shadow; /* Защищённые eCAN-регистры изменяются только полными 32-битными обращениями. */
|
||||
EALLOW; /* Разрешает настройку мультиплексора, eCAN и таблицы векторов. */
|
||||
GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; /* GPIO30 служит CANRXA, как в штатном InitCan проекта. */
|
||||
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; /* GPIO31 служит CANTXA того же трансивера. */
|
||||
ECanaRegs.CANTIOC.all = 8UL; /* Бит TXFUNC включает функцию CAN у выхода контроллера. */
|
||||
ECanaRegs.CANRIOC.all = 8UL; /* Бит RXFUNC включает аппаратный вход CAN. */
|
||||
ECanaRegs.CANME.all = 0UL; /* Изменяет mailbox и фильтры только при выключенных ящиках. */
|
||||
ECanaRegs.CANMIM.all = 0UL; /* Ни один старый mailbox не должен создавать IRQ во время настройки. */
|
||||
ECanaRegs.CANMIL.all = 0UL; /* Направляет служебные mailbox на ECAN0INTA группы PIE9. */
|
||||
ECanaRegs.CANMC.all = 0x00003080UL; /* SCB=1 выбирает eCAN, ABO=1 автоматическое восстановление, CCR=1 режим настройки битового времени; SRES остаётся нулём. */
|
||||
while (!ECanaRegs.CANES.bit.CCE) {} /* Не пишет CANBTC до аппаратного подтверждения режима настройки. */
|
||||
shadow = ((Uint32)(CLKMULT * 3L - 1L) << 16) | 0x0000017AUL; /* BRP=CLKMULT*3-1, SJW=1, TSEG1=15, TSEG2=2 как в приложении: 250000 бит/с при текущем SYSCLKOUT. */
|
||||
ECanaRegs.CANBTC.all = shadow; /* Передаёт параметры одним 32-битным обращением к eCAN. */
|
||||
ECanaRegs.CANMC.all &= ~0x00001000UL; /* Снимает CCR после настройки тактов CAN. */
|
||||
while (ECanaRegs.CANES.bit.CCE) {} /* Ждёт возврата контроллера к обычной работе перед включением фильтров. */
|
||||
ECanaRegs.CANTA.all = 0xFFFFFFFFUL; /* Удаляет старые TX ACK, которые не относятся к новой сессии. */
|
||||
ECanaRegs.CANRMP.all = 0xFFFFFFFFUL; /* Удаляет старые RX-флаги до включения IRQ. */
|
||||
ECanaRegs.CANRML.all = 0xFFFFFFFFUL; /* Начинает контроль потери mailbox с чистого состояния. */
|
||||
ECanaRegs.CANGIF0.all = 0xFFFFFFFFUL; /* Снимает накопленные флаги линии CAN0. */
|
||||
ECanaRegs.CANGIM.all = 1UL; /* I0EN разрешает mailbox IRQ по линии 0; ошибки не требуют прикладного ISR. */
|
||||
PieVectTable.ECAN0INTA = &boot_can_rx; /* Использует постоянный обработчик загрузчика вместо кода RAM-приложения. */
|
||||
PieCtrlRegs.PIEIER9.bit.INTx5 = 1; /* Разрешает ECAN0INTA в группе PIE9. */
|
||||
EDIS; /* Возвращает защиту аппаратной конфигурации. */
|
||||
IER |= M_INT9; /* Разрешает группе CAN доставлять IRQ ядру после общего EINT. */
|
||||
} /* Общий порт затем настроит адресные mailbox 3/4/6. */
|
||||
static unsigned int boot_periph_id(void) /* Повторяет аппаратное чтение Mode из peripher.c, чтобы после reset адрес загрузчика совпадал с приложением. */
|
||||
{ /* Четыре активных низким уровнем перемычки существующей ПМ35 задают номера 1–16. */
|
||||
unsigned int periph_id; /* Номер является ID PERIPH из Excel, а не уменьшенным на единицу индексом старого CAN. */
|
||||
EALLOW; /* Разрешает настройку только четырёх входов адресных перемычек. */
|
||||
GpioCtrlRegs.GPAMUX2.bit.GPIO20=0; /* GPIO20 работает входом адреса с весом 2, как в get_Mode приложения. */
|
||||
GpioCtrlRegs.GPAMUX2.bit.GPIO21=0; /* GPIO21 работает входом адреса с весом 1, а не альтернативной периферией. */
|
||||
GpioCtrlRegs.GPAMUX2.bit.GPIO22=0; /* GPIO22 работает входом адреса с весом 4. */
|
||||
GpioCtrlRegs.GPBMUX2.bit.GPIO51=0; /* GPIO51 работает входом адреса с весом 8. */
|
||||
GpioCtrlRegs.GPADIR.bit.GPIO20=0; /* Запрещает выходной драйвер, чтобы загрузчик не воздействовал на перемычку. */
|
||||
GpioCtrlRegs.GPADIR.bit.GPIO21=0; /* Оставляет младшую адресную перемычку входом. */
|
||||
GpioCtrlRegs.GPADIR.bit.GPIO22=0; /* Оставляет третий разряд аппаратного номера входом. */
|
||||
GpioCtrlRegs.GPBDIR.bit.GPIO51=0; /* Оставляет старшую перемычку входом порта B. */
|
||||
EDIS; /* Восстанавливает защиту конфигурации GPIO до чтения физического номера. */
|
||||
periph_id=1U+!GpioDataRegs.GPADAT.bit.GPIO21; /* Штатный Mode начинается с 1; замкнутая GPIO21 добавляет единицу. */
|
||||
periph_id+=2U*!GpioDataRegs.GPADAT.bit.GPIO20; /* Замкнутая GPIO20 добавляет два к номеру платы. */
|
||||
periph_id+=4U*!GpioDataRegs.GPADAT.bit.GPIO22; /* Замкнутая GPIO22 добавляет четыре к номеру платы. */
|
||||
periph_id+=8U*!GpioDataRegs.GPBDAT.bit.GPIO51; /* Замкнутая GPIO51 добавляет восемь; аппаратный диапазон заканчивается на 16. */
|
||||
return periph_id; /* Общий CAN-порт преобразует номер 16 в Type 2 / Device 0 согласно Excel. */
|
||||
} /* Приложение и recovery используют один и тот же физический адрес без общего значения 3/7. */
|
||||
static bool ram_word(void *user, uint32_t address, uint16_t value) /* Аппаратная запись одного слова уже проверенной таблицы SCI8. */
|
||||
{ /* Повторяет нижнюю защиту RAM даже при ошибке вызывающего слоя. */
|
||||
(void)user; /* Контекст не нужен для единственной внутренней RAM данного F28335. */
|
||||
if (address < 0x8000UL || address >= 0xE000UL) return false; /* Не позволяет таблице затронуть периферию, handoff, стек или RAM загрузчика. */
|
||||
*(volatile Uint16 *)address = value; /* Адрес измеряется в 16-битных словах C28x, значение уже декодировано из SCI8. */
|
||||
return true; /* Сообщает полную запись слова, а не частичное выполнение секции. */
|
||||
} /* После загрузки всех слов общий store вернёт проверенную точку входа. */
|
||||
static uint16_t flash_word(void *user, uint32_t address) /* Читает только фиксированный заголовок и проверенный диапазон приложения ниже сектора A. */
|
||||
{ /* Загрузчик остаётся во Flash A, поэтому чтение H–B не меняет выполняемый код. */
|
||||
(void)user; /* Единственная внутренняя Flash не требует отдельного контекста источника. */
|
||||
return *(volatile Uint16 *)address; /* C28x адресует Flash 16-битными словами; разбиение на октеты выполняет общий валидатор CRC. */
|
||||
} /* Никакая запись или стирание Flash при выборе источника запуска не выполняется. */
|
||||
static void start_application(uint32_t entry, unsigned int source) /* Передаёт управление Flash либо EEPROM только после проверки соответствующего образа. */
|
||||
{ /* Останавливает собственные IRQ до C startup приложения, который заново настроит периферию и рабочую RAM. */
|
||||
DINT; IER = 0U; IFR = 0U; /* Старые прерывания не должны войти в очередь или стек завершённого загрузчика. */
|
||||
CpuTimer1Regs.TCR.bit.TSS = 1; /* Прекращает миллисекундные IRQ до запуска прикладного InitSysCtrl. */
|
||||
ECanaRegs.CANMIM.all = 0UL; /* Не доставляет CAN IRQ во время смены векторов приложения. */
|
||||
F28335Boot_SetRunning(source); /* Сохраняет достоверный источник: 0/1 для EEPROM A/B либо FE для проверенной Flash. */
|
||||
((void (*)(void))entry)(); /* Вызывает watchdog-safe startup Flash или проверенную точку C runtime RAM-образа. */
|
||||
for (;;) {} /* Ошибочный возврат приложения не использует перезаписанное состояние загрузчика. */
|
||||
} /* Возврат к boot происходит только аппаратным reset с согласованным handoff. */
|
||||
void F28335Boot_Quiesce(void) /* Перед повторным входом загрузчика его собственные IRQ будут отключены общим Reset. */
|
||||
{ /* Силовые выходы загрузчик не включает; прикладная остановка выполняется до входа в него. */
|
||||
CpuTimer2Regs.TCR.bit.TSS = 1; /* Удерживает старый SPI Timer2 остановленным перед watchdog reset. */
|
||||
} /* Общий аппаратный слой сохранит session и включит watchdog. */
|
||||
void main(void) /* Постоянный загрузчик запускается аппаратным Flash boot по адресу 33FFF6. */
|
||||
{ /* Пустая EEPROM и неподтверждённый кандидат оставляют доступным CAN recovery. */
|
||||
f28335_boot_io_t io; /* Доступ к M95M02 предоставляет существующий переносимый SPI-порт. */
|
||||
unsigned int slot, session, periph_id; /* Слот, сессия handoff и физический номер PERIPH сохраняются отдельно от адресов памяти. */
|
||||
uint32_t entry, started; /* Адрес запуска измеряется словами CPU; started хранит миллисекунды стартового окна CAN. */
|
||||
InitSysCtrl(); /* Повторяет PLL и SYSCLKOUT проекта 167, отключая watchdog на раннем старте. */
|
||||
DINT; /* Не использует IRQ до настройки таблицы векторов и Timer1. */
|
||||
IER = 0U; IFR = 0U; /* Исключает доставку старых прерываний после watchdog reset. */
|
||||
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, &RamfuncsLoadEnd - &RamfuncsLoadStart); /* Переносит InitFlash в RAM до изменения времен доступа Flash. */
|
||||
InitFlash(); /* Настраивает доступ к постоянному коду по штатной процедуре TI. */
|
||||
InitPieCtrl(); /* Очищает разрешения и флаги всех групп PIE перед установкой двух собственных векторов. */
|
||||
InitCpuTimers(); /* Останавливает Timer0/1/2 и сбрасывает их управляющие структуры. */
|
||||
ConfigCpuTimer(&CpuTimer1, SYSCLKOUT / 1000000L, 1000UL); /* Период 1000 мкс даёт единый миллисекундный tick для протокола и SPI WIP. */
|
||||
EALLOW; PieVectTable.XINT13 = &boot_tick; EDIS; /* Привязывает прямое прерывание Timer1 к постоянному ISR загрузчика. */
|
||||
CpuTimer1Regs.TCR.all = 0x4020U; /* Разрешает прерывание Timer1 и запускает счётчик, как приложение 167. */
|
||||
IER |= M_INT13; /* Разрешает миллисекундные прерывания ядра. */
|
||||
periph_id=boot_periph_id(); /* Читает реальные перемычки до адресных mailbox и до ответа на ENTER_BOOT после reset. */
|
||||
boot_can_init(); /* Настраивает трансивер и физическую скорость до общих фильтров и первой передачи. */
|
||||
session = F28335Boot_RequestedSession(); /* Потребляет только достоверный запрос приложения с magic и XOR-контролем. */
|
||||
F28335CanBoot_Init(periph_id); /* Открывает журнал и адресные Boot mailbox только для физического PERIPH данной платы. */
|
||||
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; /* Разрешает таблицу PIE после записи обоих используемых векторов. */
|
||||
EINT; /* Приём окна CAN продолжается во время синхронных SPI-транзакций main. */
|
||||
if (session) F28335CanBoot_Resume(session); /* Отвечает ENTER_BOOT после reset с той же session и остаётся в recovery. */
|
||||
else { /* Обычный reset даёт CAN окно, затем предпочитает проверенную внутреннюю Flash и использует EEPROM как резерв. */
|
||||
started = F28335Boot_Now(); /* Отсчитывает три секунды от готового CAN, а не от начала настройки PLL и SPI. */
|
||||
while ((uint32_t)(F28335Boot_Now()-started)<3000UL && !F28335CanBoot_Active()) { F28335CanBoot_Service(); ServiceDog(); } /* ENTER_BOOT удерживает recovery; обычный PING не изменяет выбранный источник запуска. */
|
||||
F28335CanBoot_Service(); /* Разбирает кадр на границе трёхсекундного окна до последней проверки активного сеанса. */
|
||||
if (!F28335CanBoot_Active()) { /* Не запускает основную или резервную программу поверх открытого сеанса CAN Boot. */
|
||||
if (f28335_flash_app_validate(flash_word, 0, &entry)) start_application(entry, F28335_BOOT_FLASH_SLOT); /* Flash приоритетна только при правильном FAB1, допустимых адресах и совпавшей CRC всех LOAD-секций. */
|
||||
io.read = F28335Boot_Read; io.write = F28335Boot_Write; io.user = 0; /* Передаёт store ту же аппаратную реализацию, что обслуживает CAN. */
|
||||
if (f28335_boot_open(&image_store, &io) && f28335_boot_select(&image_store, &slot) && slot < 2U && f28335_boot_load(&image_store, slot, ram_word, 0, &entry)) { /* Проверяет CRC/SCI8, сохраняет attempted до пробного запуска и копирует только допустимую RAM. */
|
||||
start_application(entry, slot); /* Резервный EEPROM-образ получает прежние trial/CONFIRM и автоматический откат A/B. */
|
||||
} /* При ошибке чтения, CRC, таблицы или журнала не выполняет неизвестный entry. */
|
||||
F28335CanBoot_Init(periph_id); /* При переходе в recovery перечитывает журнал, сохраняя прежний физический адрес платы. */
|
||||
} /* Открытый CAN-сеанс сохраняет метаданные, выбранный слот и подтверждения без повторного Init. */
|
||||
} /* Завершает выбор между адресным входом и обычным запуском приложения. */
|
||||
F28335Boot_SetRunning(F28335_AB_NONE); /* Отмечает режим загрузчика, сохраняя уже восстановленную session в RAM автомата. */
|
||||
for (;;) { F28335CanBoot_Service(); ServiceDog(); } /* Обслуживает обновления и остаётся доступным при пустой/повреждённой EEPROM. */
|
||||
} /* Нормальный выход выполняется только через запуск RAM-приложения либо watchdog reset. */
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "../../../src/pcan_boot.c" /* Подключает единственный общий автомат ProtoCAN Boot и CRC32. */
|
||||
#include "../../../ports/tms320f28335/f28335_boot_store.c" /* Использует проверенный A/B-журнал, readback, SCI8 и откат. */
|
||||
#include "../../../ports/tms320f28335/f28335_flash_app.c" /* Проверяет FAB1 и CRC приложения ниже сектора A перед выбором основного Flash либо резервной EEPROM. */
|
||||
#include "../../../ports/tms320f28335/f28335_boot_hw.c" /* Подключает те же SPI, watchdog и handoff, что RAM-приложение. */
|
||||
#include "../../../ports/tms320f28335/f28335_can_boot.c" /* F28335_BOOT_LOADER=1 разрешает запись слотов только постоянному загрузчику. */
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<configurations XML_version="1.2" id="configurations_0">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<configuration XML_version="1.2" id="Sauris SAU510-USB Iso Plus v.2 Emulator_0">
|
||||
|
||||
|
||||
|
||||
|
||||
<instance XML_version="1.2" desc="Sauris SAU510-USB Iso Plus v.2 Emulator_0" href="connections/SAU510USBIsoPlusV2_Connection.xml" id="Sauris SAU510-USB Iso Plus v.2 Emulator_0" xml="SAU510USBIsoPlusV2_Connection.xml" xmlpath="connections"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<connection XML_version="1.2" id="Sauris SAU510-USB Iso Plus v.2 Emulator_0">
|
||||
|
||||
|
||||
|
||||
|
||||
<instance XML_version="1.2" href="drivers/sau510c28x.xml" id="drivers" xml="sau510c28x.xml" xmlpath="drivers"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<platform XML_version="1.2" id="platform_0">
|
||||
|
||||
|
||||
|
||||
|
||||
<instance XML_version="1.2" desc="TMS320F28335_0" href="devices/f28335.xml" id="TMS320F28335_0" xml="f28335.xml" xmlpath="devices"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</platform>
|
||||
|
||||
|
||||
|
||||
|
||||
</connection>
|
||||
|
||||
|
||||
|
||||
|
||||
</configuration>
|
||||
|
||||
|
||||
|
||||
|
||||
</configurations>
|
||||
@@ -89,6 +89,17 @@ static bool send_status(pcan_boot_t *boot, pcan_boot_byte_t command, pcan_boot_b
|
||||
return send_frame(boot, PCAN_BOOT_MSG_STATUS, body, data, 8U);
|
||||
}
|
||||
|
||||
uint32_t pcan_boot_crc32_update(uint32_t crc, const pcan_boot_byte_t *data, size_t length) /* Публичный readback использует тот же полином и отражение, что приём DATA. */
|
||||
{ /* Не создаёт второго аппаратно зависимого варианта CRC в портах NOR/EEPROM. */
|
||||
return crc32_update(crc, data, length); /* Продолжает ранее полученное состояние либо начинает с нуля. */
|
||||
} /* Сохраняет существующую wire-совместимость всех портов. */
|
||||
bool pcan_boot_report_busy(pcan_boot_t *boot, pcan_boot_byte_t command, uint32_t now_ms) /* Позволяет синхронному erase отвечать, пока аппаратная операция ещё не завершена. */
|
||||
{ /* Порт вызывает функцию только в контексте main с живым экземпляром сессии. */
|
||||
if (boot == NULL) return false; /* Не обращается к неинициализированному экземпляру аппаратного порта. */
|
||||
boot->now_ms = boot->last_activity_ms = now_ms; /* Продвижение erase/verify считается живой активностью: длинная операция не должна сама истечь по тайм-ауту сессии. */
|
||||
return send_status(boot, command, PCAN_BOOT_STATUS_BUSY); /* Номер следующего блока и CRC берутся из настоящего состояния ядра. */
|
||||
} /* Окончательный OK/ошибку по завершении callback отправляет обычный автомат. */
|
||||
|
||||
/* IDENTIFY имеет отдельный тип сообщения DISCOVERY и Body=1. Он доступен
|
||||
* без открытия сессии, поэтому обнаружение устройства не должно запускать обновление. */
|
||||
static bool send_identity(pcan_boot_t *boot)
|
||||
@@ -205,7 +216,7 @@ static bool process_control(pcan_boot_t *boot, uint16_t body,
|
||||
pcan_boot_byte_t command = (pcan_boot_byte_t)(body & 0xFFU);
|
||||
|
||||
if (dlc != ((command == PCAN_BOOT_CMD_BEGIN_IMAGE || command == PCAN_BOOT_CMD_BEGIN_COMPAT) ? 8U :
|
||||
(command == PCAN_BOOT_CMD_DEVICE_NAME || command == PCAN_BOOT_CMD_MEMORY_INFO) ? 1U : 0U)) {
|
||||
(command == PCAN_BOOT_CMD_DEVICE_NAME || command == PCAN_BOOT_CMD_MEMORY_INFO || command == PCAN_BOOT_CMD_SELECT_MEMORY) ? 1U : 0U)) { /* Выбор памяти имеет ровно один октет и не может читать отсутствующий payload. */
|
||||
return send_status(boot, command, PCAN_BOOT_STATUS_INVALID_SIZE);
|
||||
}
|
||||
if (command == PCAN_BOOT_CMD_PING) {
|
||||
@@ -258,6 +269,13 @@ static bool process_control(pcan_boot_t *boot, uint16_t body,
|
||||
|
||||
boot->last_activity_ms=boot->now_ms;
|
||||
switch (command) {
|
||||
case PCAN_BOOT_CMD_SELECT_MEMORY: { /* Явное назначение Flash не меняет поведение прежних клиентов без этой команды. */
|
||||
pcan_boot_status_t status; /* Точный отказ порта передаётся клиенту без подмены успешным ACK. */
|
||||
if (boot->state != PCAN_BOOT_STATE_METADATA || boot->have_image || boot->have_compat) return send_status(boot, command, PCAN_BOOT_STATUS_INVALID_STATE); /* После начала метаданных, приёма либо проверки запрещает менять цель записи. */
|
||||
if (!boot->port.select_memory) return send_status(boot, command, PCAN_BOOT_STATUS_INVALID_COMMAND); /* Старый загрузчик отклоняет новую цель до ERASE и передачи образа. */
|
||||
status = boot->port.select_memory(boot->port_user, data[0], &boot->config); /* Порт проверяет поддержку выбранной физической памяти и задаёт её режим. */
|
||||
return send_status(boot, command, status); /* Ответ защищён исходной адресацией и текущей ненулевой сессией. */
|
||||
} /* Остальные команды используют выбранную конфигурацию слотов. */
|
||||
case PCAN_BOOT_CMD_BEGIN_IMAGE:
|
||||
if(boot->state==PCAN_BOOT_STATE_READY_TO_ERASE && boot->manifest.image_size==get_u32(data) &&
|
||||
boot->manifest.image_crc32==get_u32(data+4)) return send_status(boot,command,PCAN_BOOT_STATUS_OK);
|
||||
|
||||
@@ -9,5 +9,5 @@ static struct { struct MBOX MBOX3, MBOX4, MBOX6; } ECanaMboxes;
|
||||
static struct { struct test_reg CANME,CANMD,CANRMP,CANRML,CANMIM,CANTA,CANAA,CANTRS,CANTRR; } ECanaRegs;
|
||||
static struct { struct test_reg LAM3,LAM6; } ECanaLAMRegs;
|
||||
static struct { unsigned long InterruptCount; } CpuTimer1;
|
||||
static struct { unsigned WDCR; } SysCtrlRegs;
|
||||
/* Watchdog/reset моделируются callbacks; неиспользуемая глобальная копия SysCtrlRegs не требуется. */
|
||||
#endif
|
||||
|
||||
@@ -12,16 +12,18 @@ if not cc:
|
||||
store = 'ports/tms320f28335/f28335_boot_store.c'
|
||||
cases = [
|
||||
('core', [], ['src/pcan_boot.c', 'tests/test_pcan_boot.c']),
|
||||
('busy', ['-DPCAN_BOOT_WIDE_BYTES'], ['src/pcan_boot.c', 'tests/test_pcan_busy.c']), # Длительный NOR erase с BUSY продлевает session и сохраняет wire-поля ответа.
|
||||
('store_native', [], [store, 'tests/test_f28335_boot_store.c']),
|
||||
('store_wide', ['-DPCAN_BOOT_WIDE_BYTES'], [store, 'tests/test_f28335_boot_store.c']),
|
||||
('loader', ['-DPCAN_BOOT_WIDE_BYTES'], [store, 'src/pcan_boot.c', 'tests/test_f28335_can_boot.c']),
|
||||
('application', ['-DPCAN_BOOT_WIDE_BYTES', '-DF28335_BOOT_LOADER=0'],
|
||||
[store, 'src/pcan_boot.c', 'tests/test_f28335_can_boot.c']),
|
||||
('f2812_nor', ['-DPCAN_BOOT_WIDE_BYTES', '-DBOOT2812_HOST'], ['src/pcan_boot.c', 'ports/tms320f2812/nor_flash.c', 'ports/tms320f2812/boot_store.c', 'tests/test_f2812_nor.c']), # Проверяет настоящий AMD driver, NOR manifest, SCI8 и восстановление после обрывов записи.
|
||||
]
|
||||
with tempfile.TemporaryDirectory(prefix='f28335-ab-') as tmp:
|
||||
for name, defines, sources in cases:
|
||||
exe = Path(tmp) / (name + '.exe')
|
||||
subprocess.run([cc, '-std=c99', '-Wall', '-Wextra', '-Werror', '-Iinclude',
|
||||
subprocess.run([cc, '-std=c99', '-Wall', '-Wextra', '-Werror', '-Wno-misleading-indentation', '-Iinclude', # GCC допускает существующие однострочные циклы старых аппаратных моделей без подавления остальных ошибок.
|
||||
'-Itests/f28335_stubs', *defines, *sources, '-o', str(exe)], cwd=root, check=True)
|
||||
sample = os.environ.get('F28335_SAMPLE_IMAGE') if name == 'store_wide' else None
|
||||
subprocess.run([str(exe), *([sample] if sample else [])], check=True, timeout=30)
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "../ports/tms320f2812/boot2812.h" /* Проверяет реальные callbacks NOR и общий ProtoCAN codec в wide-octet режиме. */
|
||||
#include <assert.h> /* Любое нарушение границ, публикации или CRC завершает тест ошибкой. */
|
||||
#include <stdint.h> /* Модель физической x16 памяти использует ровно 16 бит на слово даже на ПК. */
|
||||
#include <stdio.h> /* Сообщает результат поведенческих сценариев без физического JTAG. */
|
||||
#include <string.h> /* Подготавливает память и отдельные структуры C-ядра перед серией. */
|
||||
static uint16_t memory[0x80000]; /* AM29LV800BT содержит 512K слов x16, то есть 1 МиБ. */
|
||||
static unsigned int state, selected, bad_id, erases, programmed, busy_calls, loaded_words, stuck; /* Состояния относятся только к модели командной шины AMD. */
|
||||
static long budget = -1; /* Отрицательное значение разрешает записи, ноль моделирует исчезновение питания перед очередным word program. */
|
||||
static unsigned long clock_ms; /* Детерминированные часы позволяют проверить ограниченный выход из polling. */
|
||||
unsigned long Boot2812_Now(void) { return clock_ms++; } /* Продвигает миллисекунды без зависимости теста от wall clock ПК. */
|
||||
void Boot2812_Busy(void) { ++busy_calls; } /* Подтверждает, что длительное ожидание вызывает разрешённый сервис BUSY. */
|
||||
void NorModel_LoadWord(uint32_t target, unsigned int value) /* Получает только реальные записи валидатора в разрешённую RAM приложения. */
|
||||
{ /* Тестовый образ ниже содержит пять слов H0. */
|
||||
assert(target >= 0x3F8000UL && target < 0x3F8005UL); assert(value == 0U); ++loaded_words; /* Неверный адрес либо повреждённый payload не может скрыться в аппаратной заглушке. */
|
||||
} /* Запись в адресное пространство процесса ПК отсутствует. */
|
||||
unsigned int NorModel_Read(unsigned long word) /* Имитирует обычное чтение либо режим autoselect чипа. */
|
||||
{ /* Все обращения обязаны оставаться внутри установленной физической NOR. */
|
||||
assert(word >= BOOT2812_NOR_BASE && word < BOOT2812_NOR_BASE + 0x80000UL); /* Выход на соседнюю XINTF-память является ошибкой драйвера. */
|
||||
if (selected) return word == BOOT2812_NOR_BASE ? (bad_id ? 2U : 1U) : 0x22DAU; /* Модель отличает правильный AMD от неподходящего производителя. */
|
||||
if (stuck && word >= BOOT2812_IMAGE_WORD) return 0U; /* DQ7=0/DQ5=0 удерживают erase busy до программного тайм-аута. */
|
||||
return memory[word - BOOT2812_NOR_BASE]; /* Возвращает настоящие 16-битные данные модели. */
|
||||
} /* Чтение не выполняет скрытых записей и не исправляет повреждённые данные. */
|
||||
void NorModel_Write(unsigned long word, unsigned int value) /* Проверяет настоящий unlock state machine драйвера, а не принимает готовые запросы erase. */
|
||||
{ /* Командные адреса трактуются как x16 смещения согласно datasheet AMD. */
|
||||
assert(word >= BOOT2812_NOR_BASE && word < BOOT2812_NOR_BASE + 0x80000UL); /* Любой командный цикл ограничен физическим чипом. */
|
||||
if (state == 3U) { /* После A0 следующий цикл обязательно содержит программируемое слово данных. */
|
||||
if (budget != 0) { memory[word - BOOT2812_NOR_BASE] &= (uint16_t)value; ++programmed; if (budget > 0) --budget; } /* NOR программирует только переходы 1→0; обрыв питания оставляет прежнее слово. */
|
||||
state = 0U; return; /* Программирование одного слова завершает командную последовательность. */
|
||||
} /* Значение F0 в payload не должно ошибочно интерпретироваться как отдельная команда Reset. */
|
||||
if (value == 0xF0U) { state = selected = 0U; return; } /* Reset возвращает обычное чтение независимо от предыдущей незавершённой команды. */
|
||||
if (state == 0U) { assert(word == BOOT2812_NOR_BASE + 0x555UL && value == 0xAAU); state = 1U; } /* Первый unlock-цикл проверяется вместе с адресом. */
|
||||
else if (state == 1U) { assert(word == BOOT2812_NOR_BASE + 0x2AAUL && value == 0x55U); state = 2U; } /* Второй цикл исключает ошибочную x8 адресацию. */
|
||||
else if (state == 2U) { /* Третий цикл выбирает только одну из поддерживаемых безопасных команд. */
|
||||
assert(word == BOOT2812_NOR_BASE + 0x555UL); /* Командный регистр находится по x16 смещению 555h. */
|
||||
if (value == 0x90U) { selected = 1U; state = 0U; } /* Autoselect не изменяет содержимое памяти. */
|
||||
else if (value == 0xA0U) state = 3U; /* Следующий цикл будет word program. */
|
||||
else { assert(value == 0x80U); state = 4U; } /* Стирание требует второй unlock-пары, а не одного произвольного слова. */
|
||||
} /* Завершает декодирование третьего такта AMD. */
|
||||
else if (state == 4U) { assert(word == BOOT2812_NOR_BASE + 0x555UL && value == 0xAAU); state = 5U; } /* Проверяет четвёртый цикл Sector Erase. */
|
||||
else if (state == 5U) { assert(word == BOOT2812_NOR_BASE + 0x2AAUL && value == 0x55U); state = 6U; } /* Проверяет пятый цикл Sector Erase. */
|
||||
else { /* Шестой цикл выбирает только разрешённый отдельный сектор. */
|
||||
unsigned long count = word == BOOT2812_META_WORD ? 0x2000UL : 0x8000UL, i; /* Модель различает обычные и последние top-boot сектора. */
|
||||
assert(value == 0x30U); assert(word == BOOT2812_META_WORD || word == BOOT2812_IMAGE_WORD || word == BOOT2812_IMAGE_WORD + 0x8000UL || word == BOOT2812_IMAGE_WORD + 0x10000UL); /* Запрещает Chip Erase и любые соседние секторы legacy/FPGA. */
|
||||
for (i = 0; i < count; ++i) memory[word - BOOT2812_NOR_BASE + i] = 0xFFFFU; /* Реально стирает все слова выбранного сектора модели. */
|
||||
++erases; state = 0U; /* Сохраняет число аппаратных sector erase для проверки отказов до разрушительных циклов. */
|
||||
} /* Завершает разрешённую операцию command bus. */
|
||||
} /* Модель не предоставляет драйверу обходного пути прямой записи массива. */
|
||||
static pcan_boot_byte_t image[40]; /* Небольшой полный SCI8: заголовок 22, секция 6+10, терминатор 2 октета. */
|
||||
static pcan_boot_manifest_t manifest; /* Metadata используют те же размеры и совместимость, что настоящий клиент. */
|
||||
static void make_image(void) /* Создаёт независимо определённый SCI8 с entry=3F8000 и пятью нулевыми словами H0. */
|
||||
{ /* Нулевой payload облегчает точную проверку каждого перенесённого слова. */
|
||||
memset(image, 0, sizeof(image)); image[0] = 0xAAU; image[1] = 8U; image[18] = 0x3FU; image[21] = 0x80U; image[22] = 5U; image[24] = 0x3FU; image[27] = 0x80U; /* Адрес TI передаётся старшим словом вперёд, внутри слова — little endian. */
|
||||
memset(&manifest, 0, sizeof(manifest)); manifest.image_size = 40UL; manifest.image_crc32 = pcan_boot_crc32_update(0UL, image, 40U); /* Начальная CRC вычисляется общим codec по независимому массиву файла. */
|
||||
manifest.product_type = BOOT2812_PRODUCT; manifest.hardware_revision_min = manifest.hardware_revision_max = 1U; /* Проверяет исключительно совместимый профиль F2812. */
|
||||
} /* Последующие сценарии меняют данные с новой CRC, чтобы отделить ошибки структуры от ошибок передачи. */
|
||||
static void save_image(void) /* Заполняет слоты через настоящие production callbacks, а не memcpy в образ. */
|
||||
{ /* Каждая порция соответствует одному восьмиоктетному CAN DATA. */
|
||||
unsigned int i; assert(Boot2812_Erase(0, 0U)); /* Перед каждой полной передачей удаляет marker и три полных сектора образа. */
|
||||
for (i = 0; i < 40U; i += 8U) assert(Boot2812_Write(0, 0U, i, image + i, 8U)); /* Проверяет упаковку октетов и readback каждого x16 слова. */
|
||||
} /* Только после завершения записи разрешены VERIFY и COMMIT. */
|
||||
int main(void) /* Проверяет драйвер, SCI8, publication и независимость соседних данных платы. */
|
||||
{ /* Все операции используют модель, физический CAN/JTAG не открывается. */
|
||||
unsigned long i; uint32_t entry; unsigned int before, cut; /* Счётчики контролируют защищённые диапазоны и обрывы manifest. */
|
||||
for (i = 0; i < 0x80000UL; ++i) memory[i] = 0x5AA5U; make_image(); /* Заполняет весь чип контрольным значением, включая старые данные и FPGA. */
|
||||
bad_id = 1U; before = erases; assert(!Boot2812_Erase(0, 0U) && erases == before); bad_id = 0U; /* Неподходящий производитель блокируется до первого sector erase. */
|
||||
assert(!Boot2812_NorErase(0x100000UL) && !Boot2812_NorErase(BOOT2812_IMAGE_WORD + 1UL)); /* Не разрешает старую область либо адрес внутри разрешённого сектора вместо его точного начала. */
|
||||
assert(!Boot2812_NorProgram(0x130000UL, 0U)); /* FPGA-образ запрещён даже при ошибочном прямом вызове нижнего драйвера. */
|
||||
save_image(); assert(Boot2812_Verify(0, 0U, &manifest) == PCAN_BOOT_STATUS_OK); /* Реальный NOR readback и формат SCI8 должны совпасть с входом. */
|
||||
assert(!Boot2812_Load(&entry)); assert(Boot2812_Commit(0, 0U, &manifest)); loaded_words = 0U; assert(Boot2812_Load(&entry) && entry == 0x3F8000UL && loaded_words == 5U); /* До COMMIT загрузка запрещена, после него переносятся ровно проверенные слова H0. */
|
||||
before = programmed; assert(!Boot2812_NorProgram(BOOT2812_IMAGE_WORD, 0xFFFFU) && programmed == before); /* Перевод 0→1 отклоняется без лишней попытки аппаратного program. */
|
||||
for (cut = 0; cut <= 12U; ++cut) { /* Проверяет публикацию при обрыве на каждом месте manifest из двенадцати слов. */
|
||||
bool committed; save_image(); budget = (long)cut; committed = Boot2812_Commit(0, 0U, &manifest); budget = -1; /* Останавливает только циклы NOR word program, не подменяя механизм публикации. */
|
||||
loaded_words = 0U; assert(Boot2812_Load(&entry) == committed); /* Незавершённая публикация остаётся recovery; полностью опубликованный образ запускается. */
|
||||
} /* Предыдущие legacy-данные всё время остаются за пределами разрешённого erase. */
|
||||
save_image(); memory[BOOT2812_IMAGE_WORD - BOOT2812_NOR_BASE + 15UL] ^= 1U; assert(Boot2812_Verify(0, 0U, &manifest) == PCAN_BOOT_STATUS_CRC_ERROR); /* Порча физической NOR обнаруживается независимо от принятой потоковой CRC. */
|
||||
make_image(); image[18] = 0U; image[21] = 0x90U; image[24] = 0U; image[27] = 0x90U; manifest.image_crc32 = pcan_boot_crc32_update(0UL, image, 40U); save_image(); /* Формирует целостную, но опасную секцию в L1 работающего загрузчика. */
|
||||
assert(Boot2812_Verify(0, 0U, &manifest) == PCAN_BOOT_STATUS_INVALID_STATE && !Boot2812_Commit(0, 0U, &manifest)); /* Корректная CRC не разрешает перезапись очереди и состояния сессии. */
|
||||
make_image(); stuck = 1U; before = busy_calls; assert(!Boot2812_NorErase(BOOT2812_IMAGE_WORD) && busy_calls > before); stuck = 0U; /* Постоянный DQ7 busy даёт ограниченный отказ и вызывает живой сервис BUSY. */
|
||||
for (i = 0; i < 0x60000UL; ++i) assert(memory[i] == 0x5AA5U); /* Сохраняет весь нижний участок старого firmware, параметров и FPGA, а не одну контрольную точку. */
|
||||
for (i = 0x78000UL; i < 0x7E000UL; ++i) assert(memory[i] == 0x5AA5U); /* Промежуточные top-boot сектора 15/16/17 также не стираются. */
|
||||
puts("F2812 NOR: AMD commands, ID, bounds, CRC, SCI8, torn commit, timeout and legacy/FPGA preservation: OK"); /* Перечисляет программно проверенные свойства аппаратного порта. */
|
||||
return 0; /* Успех означает завершение всех граничных и отказных сценариев. */
|
||||
} /* Политика аппаратного boot/CPLD дополнительно проверяется на реальной плате. */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user