Добавить загрузку F28335 по ProtoCAN и сервисные команды клиента

This commit is contained in:
2026-10-11 03:24:44 +03:00
parent f1a7bcd8bc
commit 3c0f6fd9e6
23 changed files with 1702 additions and 97 deletions

View File

@@ -11,6 +11,13 @@
#include <stddef.h>
#include <stdint.h>
/* C28x has 16-bit addressable chars; wire octets use the low eight bits. */
#if defined(__TMS320C28XX__) || defined(PCAN_BOOT_WIDE_BYTES)
typedef unsigned int pcan_boot_byte_t;
#else
typedef uint8_t pcan_boot_byte_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -41,7 +48,11 @@ typedef enum {
PCAN_BOOT_CMD_CONFIRM = 0x08U,
PCAN_BOOT_CMD_REBOOT = 0x09U,
PCAN_BOOT_CMD_ABORT = 0x0AU,
PCAN_BOOT_CMD_QUERY_PROGRESS = 0x0BU
PCAN_BOOT_CMD_QUERY_PROGRESS = 0x0BU,
PCAN_BOOT_CMD_PING = 0x0CU,
PCAN_BOOT_CMD_CAPABILITIES = 0x0DU,
PCAN_BOOT_CMD_DEVICE_NAME = 0x0EU,
PCAN_BOOT_CMD_MEMORY_INFO = 0x0FU
} pcan_boot_command_t;
typedef enum {
@@ -66,7 +77,8 @@ typedef enum {
PCAN_BOOT_STATE_READY_TO_ERASE,
PCAN_BOOT_STATE_RECEIVING,
PCAN_BOOT_STATE_VERIFIED,
PCAN_BOOT_STATE_FAILED
PCAN_BOOT_STATE_FAILED,
PCAN_BOOT_STATE_COMMITTED
} pcan_boot_state_t;
typedef struct {
@@ -74,36 +86,47 @@ typedef struct {
uint32_t image_crc32;
uint32_t firmware_version;
uint16_t product_type;
uint8_t hardware_revision_min;
uint8_t hardware_revision_max;
pcan_boot_byte_t hardware_revision_min;
pcan_boot_byte_t hardware_revision_max;
} pcan_boot_manifest_t;
typedef struct {
uint8_t device_type;
uint8_t device_id;
pcan_boot_byte_t device_type;
pcan_boot_byte_t device_id;
uint16_t product_type;
uint8_t hardware_revision;
pcan_boot_byte_t hardware_revision;
uint32_t firmware_version;
uint8_t active_slot;
pcan_boot_byte_t active_slot;
/** 1 for an in-place/single-slot target, 2 for A/B. Zero keeps legacy A/B. */
uint8_t slot_count;
pcan_boot_byte_t slot_count;
/** Writable image capacity. Zero uses PCAN_BOOT_SLOT_SIZE. */
uint32_t max_image_size;
uint8_t ack_window; /**< 1 — ACK каждого блока, 16 — ACK каждых 16 блоков. */
pcan_boot_byte_t ack_window; /**< 1 — ACK каждого блока, 16 — ACK каждых 16 блоков. */
uint32_t session_timeout_ms; /**< 0 disables timeout for legacy ports. */
} pcan_boot_config_t;
typedef struct {
bool (*send)(void *user, uint32_t can_id, const uint8_t *data, uint8_t dlc);
bool (*erase_slot)(void *user, uint8_t slot);
bool (*write_slot)(void *user, uint8_t slot, uint32_t offset,
const uint8_t *data, uint8_t length);
bool (*send)(void *user, uint32_t can_id, const pcan_boot_byte_t *data, pcan_boot_byte_t dlc);
bool (*erase_slot)(void *user, pcan_boot_byte_t slot);
bool (*write_slot)(void *user, pcan_boot_byte_t slot, uint32_t offset,
const pcan_boot_byte_t *data, pcan_boot_byte_t length);
bool (*authorize)(void *user, const pcan_boot_manifest_t *manifest);
bool (*verify_image)(void *user, uint8_t slot,
bool (*verify_image)(void *user, pcan_boot_byte_t slot,
const pcan_boot_manifest_t *manifest);
bool (*set_pending_slot)(void *user, uint8_t slot,
/** A/B metadata, or optional single-slot activation after verification. */
bool (*set_pending_slot)(void *user, pcan_boot_byte_t slot,
const pcan_boot_manifest_t *manifest);
bool (*confirm_running_slot)(void *user);
void (*reboot)(void *user);
/** ENTER: 0 ready, 1 deferred ACK after reset, 2 denied. NULL = legacy ready. */
unsigned int (*enter_boot)(void *user, pcan_boot_byte_t session);
bool (*can_reboot)(void *user);
/** Eight-octet service response, addressed by command + page. */
bool (*service_info)(void *user, pcan_boot_byte_t command,
pcan_boot_byte_t page, pcan_boot_byte_t *out);
/** 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_port_t;
typedef struct {
@@ -115,11 +138,13 @@ typedef struct {
uint32_t running_crc32;
uint32_t bytes_received;
uint16_t next_block;
uint8_t session_id;
uint8_t target_slot;
uint8_t last_status;
pcan_boot_byte_t session_id;
pcan_boot_byte_t target_slot;
pcan_boot_byte_t last_status;
bool have_image;
bool have_compat;
uint32_t now_ms, last_activity_ms, discovery_at;
bool discovery_pending;
} pcan_boot_t;
/** Инициализирует экземпляр. Все обязательные callbacks должны быть заданы. */
@@ -134,16 +159,19 @@ void pcan_boot_abort(pcan_boot_t *boot);
* Возвращает true, если кадр принадлежал загрузочному сервису этого прибора.
*/
bool pcan_boot_process(pcan_boot_t *boot, uint32_t can_id,
const uint8_t *data, uint8_t dlc);
const pcan_boot_byte_t *data, pcan_boot_byte_t dlc);
/** Call regularly with a wrapping monotonic millisecond clock. */
void pcan_boot_poll(pcan_boot_t *boot, uint32_t now_ms);
/** Переносимые операции с 29-битным ProtoCAN ID. */
uint32_t pcan_boot_make_id(uint8_t priority, uint8_t route,
uint8_t device_type, uint8_t device_id,
uint8_t msg_type, uint16_t msg_body);
uint8_t pcan_boot_id_route(uint32_t can_id);
uint8_t pcan_boot_id_device_type(uint32_t can_id);
uint8_t pcan_boot_id_device_id(uint32_t can_id);
uint8_t pcan_boot_id_msg_type(uint32_t can_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,
pcan_boot_byte_t msg_type, uint16_t msg_body);
pcan_boot_byte_t pcan_boot_id_route(uint32_t can_id);
pcan_boot_byte_t pcan_boot_id_device_type(uint32_t can_id);
pcan_boot_byte_t pcan_boot_id_device_id(uint32_t can_id);
pcan_boot_byte_t pcan_boot_id_msg_type(uint32_t can_id);
uint16_t pcan_boot_id_msg_body(uint32_t can_id);
#ifdef __cplusplus