226 lines
7.8 KiB
C
226 lines
7.8 KiB
C
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "setp_tms2812_boot.h"
|
|
|
|
#define NODE_ID 13U
|
|
#define IMAGE_SIZE 100U
|
|
|
|
typedef struct {
|
|
uint8_t flash[512];
|
|
setp_can_rx_t response_rx;
|
|
setp_can_packet_t response_packet;
|
|
uint32_t now_ms;
|
|
unsigned int response_complete;
|
|
unsigned int erased;
|
|
unsigned int rebooted;
|
|
} fake_t;
|
|
|
|
typedef struct {
|
|
setp_tms2812_boot_t *boot;
|
|
fake_t *fake;
|
|
} request_context_t;
|
|
|
|
static bool fake_send_response(const setp_can_frame_t *frame, void *user)
|
|
{
|
|
fake_t *fake = (fake_t *)user;
|
|
setp_can_rx_result_t result = setp_can_rx_feed(
|
|
&fake->response_rx, frame, fake->now_ms++, &fake->response_packet);
|
|
if (result == SETP_CAN_RX_COMPLETE) fake->response_complete++;
|
|
return result == SETP_CAN_RX_NONE || result == SETP_CAN_RX_COMPLETE;
|
|
}
|
|
|
|
static bool fake_erase(void *user, uint32_t image_size)
|
|
{
|
|
fake_t *fake = (fake_t *)user;
|
|
if (image_size > sizeof(fake->flash)) return false;
|
|
(void)memset(fake->flash, 0xFF, sizeof(fake->flash));
|
|
fake->erased++;
|
|
return true;
|
|
}
|
|
|
|
static bool fake_write(void *user, uint32_t offset,
|
|
const uint8_t *data, uint16_t length)
|
|
{
|
|
fake_t *fake = (fake_t *)user;
|
|
if (offset + length > sizeof(fake->flash)) return false;
|
|
(void)memcpy(&fake->flash[offset], data, length);
|
|
return true;
|
|
}
|
|
|
|
static bool fake_read(void *user, uint32_t offset,
|
|
uint8_t *data, uint16_t length)
|
|
{
|
|
fake_t *fake = (fake_t *)user;
|
|
if (offset + length > sizeof(fake->flash)) return false;
|
|
(void)memcpy(data, &fake->flash[offset], length);
|
|
return true;
|
|
}
|
|
|
|
static void fake_reboot(void *user)
|
|
{
|
|
((fake_t *)user)->rebooted++;
|
|
}
|
|
|
|
static bool send_request_frame(const setp_can_frame_t *frame, void *user)
|
|
{
|
|
request_context_t *context = (request_context_t *)user;
|
|
return setp_tms2812_boot_process(context->boot, frame,
|
|
context->fake->now_ms++);
|
|
}
|
|
|
|
static setp_frame_t transact(setp_tms2812_boot_t *boot, fake_t *fake,
|
|
uint16_t sequence, uint16_t type,
|
|
const uint8_t *payload, uint16_t payload_length)
|
|
{
|
|
uint8_t packet[SETP_FRAME_MAX];
|
|
setp_frame_t request;
|
|
setp_frame_t response;
|
|
setp_can_id_t id;
|
|
request_context_t context;
|
|
size_t packet_length;
|
|
fake->response_complete = 0U;
|
|
setp_can_rx_init(&fake->response_rx);
|
|
request.flags = SETP_FLAG_ACK_REQUIRED | SETP_FLAG_PRIORITY;
|
|
request.message_type = type;
|
|
request.source = 0U;
|
|
request.destination = NODE_ID;
|
|
request.sequence = sequence;
|
|
request.payload_length = payload_length;
|
|
request.payload = payload;
|
|
packet_length = setp_frame_encode(&request, packet, sizeof(packet));
|
|
assert(packet_length != 0U);
|
|
id.destination = NODE_ID;
|
|
id.source = 0U;
|
|
id.priority = 1U;
|
|
id.channel = 1U;
|
|
context.boot = boot;
|
|
context.fake = fake;
|
|
assert(setp_can_segment(packet, (uint16_t)packet_length,
|
|
setp_can_id_pack(&id), send_request_frame, &context));
|
|
assert(fake->response_complete == 1U);
|
|
assert(setp_frame_decode_datagram(fake->response_packet.data,
|
|
fake->response_packet.length, &response));
|
|
assert(response.flags & SETP_FLAG_RESPONSE);
|
|
assert(response.message_type == type);
|
|
assert(response.sequence == sequence);
|
|
assert(response.source == NODE_ID);
|
|
assert(response.destination == 0U);
|
|
return response;
|
|
}
|
|
|
|
static void assert_ok(const setp_frame_t *response)
|
|
{
|
|
assert(response->payload_length >= 2U);
|
|
assert(setp_get_u16(response->payload) == SETP_STATUS_OK);
|
|
assert((response->flags & SETP_FLAG_ERROR) == 0U);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
static const uint8_t model[] = "BALZAM-166";
|
|
static const uint8_t expected_sha[SETP_SHA256_SIZE] = {
|
|
0xBC, 0xE0, 0xAF, 0xF1, 0x9C, 0xF5, 0xAA, 0x6A,
|
|
0x74, 0x69, 0xA3, 0x0D, 0x61, 0xD0, 0x4E, 0x43,
|
|
0x76, 0xE4, 0xBB, 0xF6, 0x38, 0x10, 0x52, 0xEE,
|
|
0x9E, 0x7F, 0x33, 0x92, 0x5C, 0x95, 0x4D, 0x52
|
|
};
|
|
uint8_t image[IMAGE_SIZE];
|
|
uint8_t payload[SETP_MAX_PAYLOAD];
|
|
setp_tms2812_boot_t boot;
|
|
setp_tms2812_boot_config_t config;
|
|
setp_tms2812_boot_port_t port;
|
|
setp_fw_begin_t begin;
|
|
setp_fw_end_t end;
|
|
setp_fw_status_t status;
|
|
setp_frame_t response;
|
|
size_t length;
|
|
uint32_t offset;
|
|
uint16_t sequence = 1U;
|
|
fake_t fake;
|
|
unsigned int i;
|
|
|
|
(void)memset(&fake, 0, sizeof(fake));
|
|
(void)memset(&config, 0, sizeof(config));
|
|
(void)memset(&port, 0, sizeof(port));
|
|
for (i = 0U; i < IMAGE_SIZE; i++) image[i] = (uint8_t)i;
|
|
config.node_id = NODE_ID;
|
|
config.device_class = 0x0166U;
|
|
config.hardware_version = 1U;
|
|
config.firmware_version = 2U;
|
|
config.model = model;
|
|
config.model_length = (uint8_t)(sizeof(model) - 1U);
|
|
config.app_base_address = 0x00100000UL;
|
|
config.max_image_size = sizeof(fake.flash);
|
|
config.max_block_size = 32U;
|
|
config.active_slot = 0U;
|
|
port.send_can = fake_send_response;
|
|
port.erase_image = fake_erase;
|
|
port.write_image = fake_write;
|
|
port.read_image = fake_read;
|
|
port.reboot = fake_reboot;
|
|
assert(setp_tms2812_boot_init(&boot, &config, &port, &fake));
|
|
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_PING, NULL, 0U);
|
|
assert_ok(&response);
|
|
assert(response.payload_length == 6U);
|
|
|
|
(void)memset(&begin, 0, sizeof(begin));
|
|
begin.image_size = IMAGE_SIZE;
|
|
begin.image_crc32 = setp_crc32(image, sizeof(image));
|
|
begin.image_version = 0x01020304UL;
|
|
begin.base_address = config.app_base_address;
|
|
begin.slot = 0U;
|
|
begin.flags = SETP_FW_FLAG_RESUME | SETP_FW_FLAG_ERASE_SLOT;
|
|
begin.block_size = 32U;
|
|
(void)memcpy(begin.sha256, expected_sha, sizeof(expected_sha));
|
|
length = setp_fw_begin_encode(&begin, payload, sizeof(payload));
|
|
assert(length != 0U);
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_FW_BEGIN,
|
|
payload, (uint16_t)length);
|
|
assert_ok(&response);
|
|
assert(fake.erased == 1U);
|
|
|
|
for (offset = 0U; offset < IMAGE_SIZE;) {
|
|
uint16_t chunk = (uint16_t)(IMAGE_SIZE - offset);
|
|
if (chunk > begin.block_size) chunk = begin.block_size;
|
|
length = setp_fw_data_encode(offset, 0U, &image[offset], chunk,
|
|
payload, sizeof(payload));
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_FW_DATA,
|
|
payload, (uint16_t)length);
|
|
assert_ok(&response);
|
|
assert(setp_get_u32(&response.payload[2]) == offset + chunk);
|
|
if (offset == 0U) {
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_FW_DATA,
|
|
payload, (uint16_t)length);
|
|
assert_ok(&response);
|
|
assert(setp_get_u32(&response.payload[2]) == chunk);
|
|
}
|
|
offset += chunk;
|
|
}
|
|
assert(memcmp(fake.flash, image, sizeof(image)) == 0);
|
|
|
|
end.image_size = begin.image_size;
|
|
end.image_crc32 = begin.image_crc32;
|
|
(void)memcpy(end.sha256, expected_sha, sizeof(expected_sha));
|
|
length = setp_fw_end_encode(&end, payload, sizeof(payload));
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_FW_END,
|
|
payload, (uint16_t)length);
|
|
assert_ok(&response);
|
|
assert(boot.state == SETP_FW_READY);
|
|
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_FW_STATUS, NULL, 0U);
|
|
assert_ok(&response);
|
|
assert(setp_fw_status_decode(&response.payload[2],
|
|
(uint16_t)(response.payload_length - 2U), &status));
|
|
assert(status.state == SETP_FW_READY);
|
|
assert(status.next_offset == IMAGE_SIZE);
|
|
|
|
response = transact(&boot, &fake, sequence++, SETP_MSG_FW_ACTIVATE, NULL, 0U);
|
|
assert_ok(&response);
|
|
assert(fake.rebooted == 1U);
|
|
puts("SETProtocol v2 TMS320F2812 firmware port tests passed");
|
|
return 0;
|
|
}
|