Объединить разработки CAN и STM32 в master

This commit is contained in:
2026-09-15 15:57:48 +03:00
68 changed files with 3585 additions and 122 deletions

View File

@@ -23,6 +23,8 @@
{"name":"db_gain","op":7,"input":[1,10],"output":[20]},
{"name":"db_attenuation","op":7,"input":[10,1],"output":[-20]},
{"name":"db_zero_reference","op":7,"input":[0,1],"output":null},
{"name":"absolute_limits","op":8,"input":[0,500,-2,2],"output":[0,500,-2,2]},
{"name":"reversed_x_limits","op":8,"input":[1,1,-2,2],"output":null},
{"name":"zero_range","op":2,"input":[1,1,1,0],"output":null},
{"name":"zero_pixels","op":4,"input":[0,1,0,0,1,0],"output":null},
{"name":"bad_viewport","op":0,"input":[0,0,0,1,2,1,0,0,0.5,0.5],"output":null}

View File

@@ -0,0 +1,32 @@
#include <stdio.h>
#include <string.h>
#include "periph28335.h"
int main(void)
{
uint8_t request[PERIPH28335_REQUEST_SIZE];
static const uint8_t read_prefix[] = { 0x10U, 0x03U, 0x00U, 0x18U, 0x00U, 0x40U };
static const uint8_t response_payload[] = { 0x10U, 0x03U, 0x04U, 0x80U, 0x05U, 0x12U, 0x34U };
uint8_t response[sizeof response_payload + 2U];
uint16_t words[2];
if (periph28335_build_read_registers(16U, 24U, 64U, request, sizeof request)
!= sizeof request || memcmp(request, read_prefix, sizeof read_prefix) != 0) return 1;
if (periph28335_build_write_register(16U, 7U, 0x1234U, request, sizeof request)
!= sizeof request || memcmp(request, "\x10\x06\x00\x07\x12\x34", 6U) != 0) return 2;
if (periph28335_build_command(16U, 15U, request, sizeof request)
!= sizeof request || memcmp(request, "\x10\x06\x00\x7F\x80\x00", 6U) != 0) return 3;
if (periph28335_append_crc(response_payload, sizeof response_payload,
response, sizeof response) != sizeof response) return 4;
if (periph28335_decode_read_response(response, sizeof response, 16U, 2U,
words, 2U) != PERIPH28335_OK || words[0] != 0x8005U || words[1] != 0x1234U) return 5;
response[0] = 17U;
if (periph28335_decode_read_response(response, sizeof response, 16U, 2U,
words, 2U) != PERIPH28335_ERROR_CRC) return 6;
if (periph28335_project_count() != 9U ||
strcmp(periph28335_project_name(2U), "23550") != 0 ||
strcmp(periph28335_command_name(2U, 7U), "Send") != 0) return 7;
puts("PM35/TMS320F28335 protocol tests passed");
return 0;
}

View File

@@ -26,6 +26,13 @@ int main(void) {
assert(output[0] == y[0]);
assert(set_plot_eval(SET_PLOT_DRAG, drag, 6, output, 4) == 1);
assert(output[0] == -4);
{
const double limits[] = {0, 500, -2, 2};
const double reversed[] = {1, 1, -2, 2};
assert(set_plot_eval(SET_PLOT_LIMITS, limits, 4, output, 4) == 4);
assert(output[0] == 0 && output[1] == 500 && output[2] == -2 && output[3] == 2);
assert(set_plot_eval(SET_PLOT_LIMITS, reversed, 4, output, 4) == 0);
}
puts("shared plot: OK");
return 0;
}

View File

@@ -17,6 +17,15 @@ int main(void)
assert(set_spectrum_analyze(times, values, 32, 32, 0, SET_FILTER_LOW_PASS, 0, 16, 1, output, 17, meta) == SET_SPECTRUM_CUTOFF);
times[12] = times[11];
assert(set_spectrum_analyze(times, values, 32, 32, 0, 0, 0, 0, 1, output, 17, meta) == SET_SPECTRUM_TIMING);
{
const double amplitudes[] = {10.0, .01, .02, .8, .03, .4, .02};
const double noise[] = {0, .10, .12, .11, .09, .10};
double scratch[6], peak[2];
assert(set_spectrum_dominant_peak(amplitudes, 7, 5, 3, 1e-6, scratch, 6, peak, 2) == 1);
assert(peak[0] == 15 && peak[1] == .8);
assert(set_spectrum_dominant_peak(noise, 6, 1, 3, 1e-6, scratch, 6, peak, 2) == 0);
assert(set_spectrum_dominant_peak(amplitudes, 7, 0, 3, 1e-6, scratch, 6, peak, 2) == -1);
}
puts("shared spectrum: OK");
return 0;
}

View File

@@ -0,0 +1,35 @@
#include <stdio.h>
#include <string.h>
#include "tms2812.h"
int main(void)
{
uint8_t request[TMS2812_UPLOAD_REQUEST_SIZE];
static const uint8_t prefix[] = {
0x05U, 0x34U, 0x78U, 0x56U, 0x34U, 0x12U,
0x00U, 0x10U, 0x00U, 0x00U
};
uint8_t reply[4U + TMS2812_UPLOAD_RESPONSE_OVERHEAD];
uint8_t decoded[4];
uint16_t crc;
if (tms2812_build_upload_request(5U, 0x12345678UL, 0x1000U,
request, sizeof request) != sizeof request ||
memcmp(request, prefix, sizeof prefix) != 0) return 1;
reply[0] = 5U;
reply[1] = TMS2812_CMD_UPLOAD;
reply[2] = 0x10U; reply[3] = 0x20U; reply[4] = 0x30U; reply[5] = 0x40U;
crc = tms2812_crc16(reply, 6U);
reply[6] = (uint8_t)crc;
reply[7] = (uint8_t)(crc >> 8);
memset(&reply[8], 0, 4U);
if (tms2812_decode_upload_response(reply, sizeof reply, 5U, 4U,
decoded, sizeof decoded) != TMS2812_OK ||
memcmp(decoded, &reply[2], sizeof decoded) != 0) return 2;
reply[6] ^= 1U;
if (tms2812_validate_upload_response(reply, sizeof reply, 5U, 4U)
!= TMS2812_ERROR_CRC) return 3;
puts("PM67/TMS320F2812 upload protocol tests passed");
return 0;
}

View File

@@ -0,0 +1,225 @@
#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;
}

View File

@@ -34,8 +34,11 @@ int main(void)
assert(!set_trend_watch_ack(expected, 4, 1000, 3));
const uint8_t packet[] = {1, 2, 3, 4, 2, 0, 52, 18, 255, 255};
uint16_t words[64];
uint32_t timestamp = 0;
assert(set_trend_watch_values(packet, sizeof(packet), words, 64) == 2);
assert(words[0] == 0x1234 && words[1] == 0xFFFF);
assert(set_trend_watch_decode(packet, sizeof(packet), &timestamp, words, 64) == 2);
assert(timestamp == 0x04030201UL);
assert(set_trend_watch_values(packet, sizeof(packet) - 1, words, 64) == -1);
assert(set_trend_watch_values(packet, sizeof(packet), words, 1) == -1);
puts("Shared trend tests passed");