Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers, middleware (CAN stack, diagnostics, safety), applications, board support, build/test tooling, and documentation.
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @file test_can_communication.c
|
||||
* @brief Integration tests for CAN communication
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "kernel.h"
|
||||
#include "can_driver.h"
|
||||
#include "can_tp.h"
|
||||
#include "can_nm.h"
|
||||
#include <string.h>
|
||||
|
||||
/* CAN test variables */
|
||||
static CanMessage_t test_message;
|
||||
static volatile bool message_received = false;
|
||||
static volatile bool message_sent = false;
|
||||
static volatile uint32_t rx_count = 0;
|
||||
|
||||
/* Callback functions */
|
||||
static void test_rx_callback(const CanMessage_t* message) {
|
||||
message_received = true;
|
||||
rx_count++;
|
||||
memcpy(&test_message, message, sizeof(CanMessage_t));
|
||||
}
|
||||
|
||||
static void test_tx_callback(uint32_t mailbox, bool success) {
|
||||
message_sent = success;
|
||||
}
|
||||
|
||||
/* Setup */
|
||||
void setUp(void) {
|
||||
kernel_init();
|
||||
message_received = false;
|
||||
message_sent = false;
|
||||
rx_count = 0;
|
||||
|
||||
/* Initialize CAN */
|
||||
CanConfig_t config = {
|
||||
.nominal_baudrate = CAN_BAUD_500K,
|
||||
.data_baudrate = CAN_BAUD_500K,
|
||||
.frame_type = CAN_FRAME_CLASSIC,
|
||||
.enable_fd = false,
|
||||
.enable_automatic_retransmission = true,
|
||||
.rx_callback = test_rx_callback,
|
||||
.tx_callback = test_tx_callback,
|
||||
.filter_count = 0
|
||||
};
|
||||
|
||||
can_init(&config);
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
void tearDown(void) {
|
||||
can_deinit();
|
||||
kernel_stop();
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Cases
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief Test CAN initialization
|
||||
*/
|
||||
void test_can_init(void) {
|
||||
CanStatistics_t stats;
|
||||
TEST_ASSERT_EQUAL(KERNEL_OK, can_get_statistics(&stats));
|
||||
TEST_ASSERT_EQUAL(0, stats.tx_messages);
|
||||
TEST_ASSERT_EQUAL(0, stats.rx_messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test CAN message send
|
||||
*/
|
||||
void test_can_send(void) {
|
||||
CanMessage_t msg = {
|
||||
.id = {.id = 0x100, .is_extended = false},
|
||||
.length = 8,
|
||||
.data = {1, 2, 3, 4, 5, 6, 7, 8}
|
||||
};
|
||||
|
||||
TEST_ASSERT_EQUAL(KERNEL_OK, can_send_message(&msg, 1000));
|
||||
|
||||
/* Wait for transmission */
|
||||
kernel_delay(10);
|
||||
|
||||
TEST_ASSERT_TRUE(message_sent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test CAN message receive
|
||||
*/
|
||||
void test_can_receive(void) {
|
||||
CanMessage_t msg = {
|
||||
.id = {.id = 0x200, .is_extended = false},
|
||||
.length = 4,
|
||||
.data = {0xAA, 0xBB, 0xCC, 0xDD}
|
||||
};
|
||||
|
||||
/* Simulate received message */
|
||||
can_process_interrupt();
|
||||
|
||||
TEST_ASSERT_TRUE(message_received);
|
||||
TEST_ASSERT_EQUAL(0x200, test_message.id.id);
|
||||
TEST_ASSERT_EQUAL(4, test_message.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test CAN TP multi-frame message
|
||||
*/
|
||||
void test_can_tp_multiframe(void) {
|
||||
CanTpConfig_t tp_config = {
|
||||
.addressing_format = CAN_TP_ADDRESSING_NORMAL,
|
||||
.source_address = 0x100,
|
||||
.target_address = 0x200,
|
||||
.timeout_ms = 1000,
|
||||
.stmin = 10,
|
||||
.block_size = 8,
|
||||
.padding_enabled = true,
|
||||
.padding_byte = 0xAA
|
||||
};
|
||||
|
||||
can_tp_init(&tp_config);
|
||||
|
||||
/* Create test message */
|
||||
uint8_t data[100];
|
||||
for (int i = 0; i < 100; i++) {
|
||||
data[i] = i;
|
||||
}
|
||||
|
||||
CanTpMessage_t tp_msg = {
|
||||
.message_id = 0x300,
|
||||
.data = data,
|
||||
.length = 100,
|
||||
.addressing_format = CAN_TP_ADDRESSING_NORMAL
|
||||
};
|
||||
|
||||
TEST_ASSERT_EQUAL(KERNEL_OK, can_tp_send_message(&tp_msg, 5000));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test CAN network management
|
||||
*/
|
||||
void test_can_nm(void) {
|
||||
CanNmConfig_t nm_config = {
|
||||
.node_id = 1,
|
||||
.network_id = 0,
|
||||
.message_id = 0x400,
|
||||
.timeout_ms = 2000,
|
||||
.repeat_message_time_ms = 500,
|
||||
.is_coordinator = false,
|
||||
.sleep_ack_timeout_ms = 100
|
||||
};
|
||||
|
||||
TEST_ASSERT_EQUAL(KERNEL_OK, can_nm_init(&nm_config));
|
||||
TEST_ASSERT_EQUAL(KERNEL_OK, can_nm_start());
|
||||
|
||||
kernel_delay(100);
|
||||
|
||||
TEST_ASSERT_EQUAL(CAN_NM_NORMAL_OPERATION, can_nm_get_state());
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Runner
|
||||
* ============================================================================ */
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
|
||||
RUN_TEST(test_can_init);
|
||||
RUN_TEST(test_can_send);
|
||||
RUN_TEST(test_can_receive);
|
||||
RUN_TEST(test_can_tp_multiframe);
|
||||
RUN_TEST(test_can_nm);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file test_fault_handling.c
|
||||
* @brief Integration tests for fault handling
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "kernel.h"
|
||||
#include "task.h"
|
||||
#include "fault_handler.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Fault test variables */
|
||||
static volatile uint32_t fault_count = 0;
|
||||
static volatile uint32_t last_fault_type = 0;
|
||||
|
||||
/* Fault callback */
|
||||
static void test_fault_callback(const FaultInfo_t* fault_info) {
|
||||
fault_count++;
|
||||
last_fault_type = fault_info->type;
|
||||
}
|
||||
|
||||
/* Stack overflow test task */
|
||||
static void stack_overflow_task(void* params) {
|
||||
(void)params;
|
||||
|
||||
/* Allocate large array on stack to cause overflow */
|
||||
uint8_t large_array[10000];
|
||||
memset(large_array, 0, sizeof(large_array));
|
||||
|
||||
while (1) {
|
||||
kernel_delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup */
|
||||
void setUp(void) {
|
||||
kernel_init();
|
||||
fault_count = 0;
|
||||
last_fault_type = 0;
|
||||
|
||||
fault_handler_register_callback(test_fault_callback);
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
void tearDown(void) {
|
||||
kernel_stop();
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Cases
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief Test fault handler initialization
|
||||
*/
|
||||
void test_fault_handler_init(void) {
|
||||
fault_handler_init();
|
||||
TEST_ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test stack overflow detection
|
||||
*/
|
||||
void test_stack_overflow_detection(void) {
|
||||
TaskConfig_t config = {
|
||||
.name = "overflow",
|
||||
.function = stack_overflow_task,
|
||||
.parameters = NULL,
|
||||
.stack_size = 512, /* Small stack to force overflow */
|
||||
.priority = 1,
|
||||
.period_ticks = 0
|
||||
};
|
||||
|
||||
TaskHandle_t task = task_create(&config);
|
||||
|
||||
kernel_start();
|
||||
kernel_delay(100);
|
||||
|
||||
/* Stack overflow should be detected */
|
||||
TEST_ASSERT_GREATER_THAN(0, fault_count);
|
||||
TEST_ASSERT_EQUAL(FAULT_STACK_OVERFLOW, last_fault_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test fault processing
|
||||
*/
|
||||
void test_fault_process(void) {
|
||||
fault_handler_process(FAULT_HARD_FAULT, 0x20000000, 0x01);
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fault_count);
|
||||
TEST_ASSERT_EQUAL(FAULT_HARD_FAULT, last_fault_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test multiple faults
|
||||
*/
|
||||
void test_multiple_faults(void) {
|
||||
fault_handler_process(FAULT_BUS_FAULT, 0x40000000, 0x02);
|
||||
fault_handler_process(FAULT_USAGE_FAULT, 0x00000000, 0x03);
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fault_count);
|
||||
TEST_ASSERT_EQUAL(FAULT_USAGE_FAULT, last_fault_type);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Runner
|
||||
* ============================================================================ */
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
|
||||
RUN_TEST(test_fault_handler_init);
|
||||
RUN_TEST(test_stack_overflow_detection);
|
||||
RUN_TEST(test_fault_process);
|
||||
RUN_TEST(test_multiple_faults);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* @file test_timing.c
|
||||
* @brief Integration tests for timing accuracy
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "kernel.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Timing test variables */
|
||||
static volatile uint32_t periodic_count = 0;
|
||||
static volatile uint32_t first_period_time = 0;
|
||||
static volatile uint32_t last_period_time = 0;
|
||||
static volatile uint32_t max_period_jitter = 0;
|
||||
|
||||
/* Periodic test task */
|
||||
static void periodic_task(void* params) {
|
||||
(void)params;
|
||||
|
||||
uint32_t current_time = kernel_get_tick_count();
|
||||
|
||||
if (periodic_count == 0) {
|
||||
first_period_time = current_time;
|
||||
} else {
|
||||
uint32_t period = current_time - last_period_time;
|
||||
if (period > max_period_jitter) {
|
||||
max_period_jitter = period;
|
||||
}
|
||||
}
|
||||
|
||||
last_period_time = current_time;
|
||||
periodic_count++;
|
||||
|
||||
while (1) {
|
||||
kernel_delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup */
|
||||
void setUp(void) {
|
||||
kernel_init();
|
||||
periodic_count = 0;
|
||||
max_period_jitter = 0;
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
void tearDown(void) {
|
||||
kernel_stop();
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Cases
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief Test periodic task timing
|
||||
*/
|
||||
void test_periodic_timing(void) {
|
||||
TaskConfig_t config = {
|
||||
.name = "periodic",
|
||||
.function = periodic_task,
|
||||
.parameters = NULL,
|
||||
.stack_size = 1024,
|
||||
.priority = 1,
|
||||
.period_ticks = 10
|
||||
};
|
||||
|
||||
TaskHandle_t task = task_create(&config);
|
||||
|
||||
kernel_start();
|
||||
kernel_delay(1000); /* Run for 1 second */
|
||||
|
||||
/* Verify task executed */
|
||||
TEST_ASSERT_GREATER_THAN(90, periodic_count);
|
||||
TEST_ASSERT_LESS_THAN(110, periodic_count);
|
||||
|
||||
/* Verify timing accuracy */
|
||||
TEST_ASSERT_LESS_OR_EQUAL(2, max_period_jitter); /* Max 2ms jitter */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test delay accuracy
|
||||
*/
|
||||
void test_delay_accuracy(void) {
|
||||
kernel_start();
|
||||
|
||||
uint32_t start = kernel_get_tick_count();
|
||||
kernel_delay(100);
|
||||
uint32_t end = kernel_get_tick_count();
|
||||
|
||||
uint32_t elapsed = end - start;
|
||||
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(99, elapsed);
|
||||
TEST_ASSERT_LESS_OR_EQUAL(102, elapsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test tick count
|
||||
*/
|
||||
void test_tick_count(void) {
|
||||
kernel_start();
|
||||
|
||||
uint32_t start = kernel_get_tick_count();
|
||||
kernel_delay(50);
|
||||
uint32_t end = kernel_get_tick_count();
|
||||
|
||||
TEST_ASSERT_EQUAL(50, end - start);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test high-frequency task
|
||||
*/
|
||||
void test_high_frequency_task(void) {
|
||||
TaskConfig_t config = {
|
||||
.name = "fast_task",
|
||||
.function = periodic_task,
|
||||
.parameters = NULL,
|
||||
.stack_size = 1024,
|
||||
.priority = 0,
|
||||
.period_ticks = 1
|
||||
};
|
||||
|
||||
TaskHandle_t task = task_create(&config);
|
||||
|
||||
kernel_start();
|
||||
kernel_delay(100);
|
||||
|
||||
/* 1ms task should execute approximately 100 times */
|
||||
TEST_ASSERT_GREATER_THAN(90, periodic_count);
|
||||
TEST_ASSERT_LESS_THAN(110, periodic_count);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Runner
|
||||
* ============================================================================ */
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
|
||||
RUN_TEST(test_periodic_timing);
|
||||
RUN_TEST(test_delay_accuracy);
|
||||
RUN_TEST(test_tick_count);
|
||||
RUN_TEST(test_high_frequency_task);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
Reference in New Issue
Block a user