#ifndef RS485_BOOT_H #define RS485_BOOT_H #include #include #include #ifdef __cplusplus extern "C" { #endif #define RS485_BOOT_VERSION 1U #define RS485_BOOT_MAX_PAYLOAD 512U #define RS485_BOOT_MAX_FRAME (8U + RS485_BOOT_MAX_PAYLOAD + 4U) #define RS485_BOOT_DATA_HEADER_SIZE 8U #define RS485_BOOT_MAX_BLOCK (RS485_BOOT_MAX_PAYLOAD - RS485_BOOT_DATA_HEADER_SIZE) typedef enum { RS485_BOOT_IDLE = 0U, RS485_BOOT_RECEIVING = 1U, RS485_BOOT_READY = 2U, RS485_BOOT_FAILED = 3U } rs485_boot_state_t; typedef enum { RS485_BOOT_OK = 0U, RS485_BOOT_INVALID_ARGUMENT = 1U, RS485_BOOT_INVALID_LENGTH = 2U, RS485_BOOT_BUSY = 5U, RS485_BOOT_INTERNAL = 7U, RS485_BOOT_UNSUPPORTED = 0x11U } rs485_boot_result_t; typedef struct { uint32_t app_address; uint32_t app_size; uint16_t max_block_size; } rs485_boot_config_t; typedef struct { bool (*transmit)(void *user, const uint8_t *data, uint16_t length); bool (*erase)(void *user, uint32_t image_size); bool (*write)(void *user, uint32_t offset, const uint8_t *data, uint16_t length); bool (*read)(void *user, uint32_t offset, uint8_t *data, uint16_t length); bool (*image_valid)(void *user, uint32_t image_size, uint32_t image_crc32); void (*reboot)(void *user); } rs485_boot_port_t; typedef struct { rs485_boot_config_t config; rs485_boot_port_t port; void *port_user; uint8_t parser[RS485_BOOT_MAX_FRAME]; uint16_t parser_length; uint8_t tx[RS485_BOOT_MAX_FRAME]; uint8_t scratch[32]; uint32_t image_size; uint32_t image_crc32; uint32_t next_offset; uint32_t crc_errors; rs485_boot_state_t state; } rs485_boot_t; bool rs485_boot_init(rs485_boot_t *boot, const rs485_boot_config_t *config, const rs485_boot_port_t *port, void *port_user); void rs485_boot_feed(rs485_boot_t *boot, const uint8_t *data, size_t length); void rs485_boot_abort(rs485_boot_t *boot); uint32_t rs485_boot_crc32(const uint8_t *data, size_t length); #ifdef __cplusplus } #endif #endif