Files
templates/c/set-protocol/tests/test_tms2812_boot.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;
}