forked from ROMEO/fsw-ws
cleaned up low level tests. Run on linux as well now
This commit is contained in:
+2
-3
@@ -17,10 +17,11 @@ set(ROMEO_WARNING_FLAGS
|
||||
-Wpedantic
|
||||
-Werror) # TODO so far, this only affects mission code, not bsp
|
||||
|
||||
option(ROMEO_LOW_LEVEL_TESTS "enable semihosting for emulation" OFF)
|
||||
option(ROMEO_LOW_LEVEL_TESTS "build low level tests INSTEAD of normal binary" OFF)
|
||||
|
||||
if(${ROMEO_LOW_LEVEL_TESTS})
|
||||
add_compile_definitions(LOW_LEVEL_TESTS)
|
||||
set(OBSW_NAME romeo-low_level_tests)
|
||||
endif()
|
||||
|
||||
# CMake options which are only available when crosscompiling
|
||||
@@ -37,8 +38,6 @@ if (${CMAKE_CROSSCOMPILING})
|
||||
if(${ARM_SEMIHOSTING})
|
||||
add_compile_definitions(ARM_SEMIHOSTING)
|
||||
endif()
|
||||
|
||||
|
||||
else()
|
||||
unset(ZYNQ_UART)
|
||||
unset(ZYNQ_UART CACHE)
|
||||
|
||||
@@ -78,6 +78,14 @@
|
||||
|
||||
#define configRECORD_STACK_HIGH_ADDRESS 1
|
||||
|
||||
|
||||
// see low_level_tests/mod.rs, some weird effect in FreeRTOS
|
||||
#ifndef LOW_LEVEL_TESTS
|
||||
#define configMAX_PRIORITIES ( 10 )
|
||||
#else
|
||||
#define configMAX_PRIORITIES ( 1024 )
|
||||
#endif
|
||||
|
||||
/* Software timer related configuration options. The maximum possible task
|
||||
* priority is configMAX_PRIORITIES - 1. The priority of the timer task is
|
||||
* deliberately set higher to ensure it is correctly capped back to
|
||||
@@ -87,7 +95,8 @@
|
||||
#define configTIMER_QUEUE_LENGTH 20
|
||||
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
|
||||
|
||||
#define configMAX_PRIORITIES ( 10 )
|
||||
|
||||
|
||||
|
||||
/* Run time stats gathering configuration options. */
|
||||
unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */
|
||||
|
||||
+5
-3
@@ -8,6 +8,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <hardware/interfaces.h>
|
||||
|
||||
const char *sim_ip = "localhost";
|
||||
int ai_family = AF_UNSPEC;
|
||||
@@ -21,14 +22,15 @@ void done_error() { exit(1); }
|
||||
int test_socket();
|
||||
|
||||
// TODO link to GCC's personality or make the linux build not use it?
|
||||
// -> linux build is std at the moment
|
||||
// void rust_eh_personality() { puts("eh_personality"); }
|
||||
// -> linux build is std at the moment, only used for tests
|
||||
#ifdef LOW_LEVEL_TESTS
|
||||
void rust_eh_personality() { puts("eh_personality"); }
|
||||
#endif
|
||||
|
||||
void print_usage(const char *name) {
|
||||
fprintf(stderr, "Usage: %s [-s sim_ip] [-4|6]\n", name);
|
||||
}
|
||||
|
||||
#include <hardware/interfaces.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
hw_device_open(
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
#TODO look into corrosion cmake plugin
|
||||
|
||||
if (${CMAKE_CROSSCOMPILING})
|
||||
if(${ROMEO_LOW_LEVEL_TESTS})
|
||||
set(FEATURES "--features=\"low_level_tests\"")
|
||||
endif()
|
||||
|
||||
if(${ROMEO_LOW_LEVEL_TESTS})
|
||||
set(FEATURES "--features=\"low_level_tests\"")
|
||||
endif()
|
||||
if (${CMAKE_CROSSCOMPILING})
|
||||
|
||||
add_custom_target(
|
||||
mission_rust_internal
|
||||
@@ -31,7 +31,7 @@ else()
|
||||
|
||||
add_custom_target(
|
||||
mission_rust_internal
|
||||
COMMAND cargo build $<$<CONFIG:Release>:--release>
|
||||
COMMAND cargo build $<$<CONFIG:Release>:--release> ${FEATURES}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ extern "C" {
|
||||
//void *create_task_static(TaskFunction_t taskFunction, void *parameter,
|
||||
// char *task_data, uint32_t task_data_len, char *stack, uint32_t stack_size)
|
||||
pub fn freertos_create_task_static(
|
||||
taskFunction: TaskFunction,
|
||||
task_function: TaskFunction,
|
||||
parameter: *const core::ffi::c_void,
|
||||
priority: u32,
|
||||
task_data: *mut core::ffi::c_char,
|
||||
@@ -110,8 +110,6 @@ pub use test_api::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_api{
|
||||
use core::ptr;
|
||||
|
||||
use super::*;
|
||||
|
||||
////////////////////////
|
||||
@@ -119,127 +117,112 @@ mod test_api{
|
||||
/// shimmed in mission/freeRTOS_rust_helper.c
|
||||
//void *create_task_static(TaskFunction_t taskFunction, void *parameter,
|
||||
// char *task_data, uint32_t task_data_len, char *stack, uint32_t stack_size)
|
||||
pub fn freertos_create_task_static(
|
||||
taskFunction: TaskFunction,
|
||||
parameter: *const core::ffi::c_void,
|
||||
priority: u32,
|
||||
task_data: *mut core::ffi::c_char,
|
||||
task_data_len: u32,
|
||||
stack: *mut core::ffi::c_char,
|
||||
stack_size: u32,
|
||||
pub unsafe fn freertos_create_task_static(
|
||||
_task_function: TaskFunction,
|
||||
_parameter: *const core::ffi::c_void,
|
||||
_priority: u32,
|
||||
_task_data: *mut core::ffi::c_char,
|
||||
_task_data_len: u32,
|
||||
_stack: *mut core::ffi::c_char,
|
||||
_stack_size: u32,
|
||||
) -> *const core::ffi::c_void{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
// pub fn stop_it();
|
||||
|
||||
pub fn freertos_task_suspend(handle: *const core::ffi::c_void){
|
||||
pub unsafe fn freertos_task_suspend(_handle: *const core::ffi::c_void){
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
}
|
||||
|
||||
pub fn freertos_task_delete(handle: *const core::ffi::c_void) -> !{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
loop{}
|
||||
pub unsafe fn freertos_task_delete(_handle: *const core::ffi::c_void) -> !{
|
||||
panic!("freeRTOS APIs are not implemented for tests")
|
||||
}
|
||||
|
||||
pub fn freertos_task_storage_set(
|
||||
handle: *const core::ffi::c_void,
|
||||
data: *const core::ffi::c_void,
|
||||
pub unsafe fn freertos_task_storage_set(
|
||||
_handle: *const core::ffi::c_void,
|
||||
_data: *const core::ffi::c_void,
|
||||
){
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
}
|
||||
|
||||
pub fn freertos_task_storage_get(handle: *const core::ffi::c_void) -> *const core::ffi::c_void{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
pub fn freertos_task_delay(milliseconds: u32){
|
||||
pub unsafe fn freertos_task_storage_get(_handle: *const core::ffi::c_void) -> *const core::ffi::c_void{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
}
|
||||
|
||||
pub fn freertos_task_stack_watermark() -> u32{
|
||||
pub unsafe fn freertos_task_delay(_milliseconds: u32){
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
|
||||
pub fn freertos_task_current() -> *const core::ffi::c_void{
|
||||
pub unsafe fn freertos_task_stack_watermark() -> u32{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
}
|
||||
|
||||
pub unsafe fn freertos_task_current() -> *const core::ffi::c_void{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
// TODO this should be passed by compile time value
|
||||
pub fn freertos_task_priority_max() -> u32{
|
||||
pub unsafe fn freertos_task_priority_max() -> u32{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
u32::MAX
|
||||
}
|
||||
|
||||
//void *freertos_queue_create_static(uint32_t depth, uint32_t element_size,
|
||||
// char *queue_data, uint32_t queue_data_len,
|
||||
// uint8_t *queue, uint32_t queue_len) {
|
||||
pub fn freertos_queue_create_static(
|
||||
depth: u32,
|
||||
element_size: u32,
|
||||
queue_data: *mut core::ffi::c_char,
|
||||
queue_data_len: u32,
|
||||
queue: *mut u8,
|
||||
pub unsafe fn freertos_queue_create_static(
|
||||
_depth: u32,
|
||||
_element_size: u32,
|
||||
_queue_data: *mut core::ffi::c_char,
|
||||
_queue_data_len: u32,
|
||||
_queue: *mut u8,
|
||||
) -> *const core::ffi::c_void{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
pub fn freertos_queue_receive(
|
||||
queue: *const core::ffi::c_void,
|
||||
message: *const core::ffi::c_void,
|
||||
pub unsafe fn freertos_queue_receive(
|
||||
_queue: *const core::ffi::c_void,
|
||||
_message: *const core::ffi::c_void,
|
||||
) -> u8{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
pub fn freertos_queue_send(
|
||||
queue: *const core::ffi::c_void,
|
||||
message: *const core::ffi::c_void,
|
||||
pub unsafe fn freertos_queue_send(
|
||||
_queue: *const core::ffi::c_void,
|
||||
_message: *const core::ffi::c_void,
|
||||
) -> u8{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
|
||||
pub fn freertos_mutex_create_static(
|
||||
mutex_data: *const core::ffi::c_char,
|
||||
mutex_data_len: u32,
|
||||
pub unsafe fn freertos_mutex_create_static(
|
||||
_mutex_data: *const core::ffi::c_char,
|
||||
_mutex_data_len: u32,
|
||||
) -> *const core::ffi::c_void{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
pub fn freertos_mutex_take(mutex: *const core::ffi::c_void) -> u8{
|
||||
pub unsafe fn freertos_mutex_take(_mutex: *const core::ffi::c_void) -> u8{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
pub fn freertos_mutex_give(mutex: *const core::ffi::c_void) -> u8{
|
||||
pub unsafe fn freertos_mutex_give(_mutex: *const core::ffi::c_void) -> u8{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
|
||||
//uint8_t freertos_simple_once(uint8_t *once_data)
|
||||
pub fn freertos_simple_once(once_data: *const u8) -> u8{
|
||||
pub unsafe fn freertos_simple_once(_once_data: *const u8) -> u8{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
|
||||
//int freertos_get_sys_error()
|
||||
pub fn freertos_get_sys_error() -> core::ffi::c_int{
|
||||
pub unsafe fn freertos_get_sys_error() -> core::ffi::c_int{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
/// Harware Abstraction API in common/include/interfaces.h
|
||||
/// Used for access to peripherals to make switching between linux and embedded easier
|
||||
//int hw_device_open(const char * path, size_t path_len);
|
||||
pub fn hw_device_open(path: *const core::ffi::c_char, path_len: core::ffi::c_size_t) -> core::ffi::c_int{
|
||||
pub unsafe fn hw_device_open(_path: *const core::ffi::c_char, _path_len: core::ffi::c_size_t) -> core::ffi::c_int{
|
||||
panic!("freeRTOS APIs are not implemented for tests");
|
||||
1
|
||||
}
|
||||
}
|
||||
////////////////////////
|
||||
|
||||
@@ -206,8 +206,7 @@ impl<const STACKSIZE: usize> StaticThreadInner<STACKSIZE> {
|
||||
panic!("StaticThread(\"{}\")::spawn: priority {} is larger than maximum ({})", self.name, self.priority, unsafe{super::ffi::freertos_task_priority_max()});
|
||||
}
|
||||
|
||||
// let stack = self.stack.take_no_init().unwrap();
|
||||
let stack : &mut Box<[core::ffi::c_char;STACKSIZE]> = &mut Box::new([0;STACKSIZE]);
|
||||
let stack = self.stack.take_no_init().unwrap();
|
||||
|
||||
let closure_space = core::mem::size_of::<F>();
|
||||
// Will be checked later on, but this way we get a more precise output instead of a generic panic
|
||||
@@ -247,8 +246,7 @@ impl<const STACKSIZE: usize> StaticThreadInner<STACKSIZE> {
|
||||
);
|
||||
}
|
||||
|
||||
// let thread_data = self.thread_data.take_no_init().unwrap();
|
||||
let thread_data: &mut Box<[core::ffi::c_char;ffi::Sizes::TASK_DATA_SIZE]> = &mut Box::new([0;ffi::Sizes::TASK_DATA_SIZE]);
|
||||
let thread_data = self.thread_data.take_no_init().unwrap();
|
||||
|
||||
// SAFE: We only pass pointers derived from &'static references to the OS, so the pointers will
|
||||
// be valid for the complete runtime. This includes values borrowed by the closure
|
||||
@@ -267,11 +265,7 @@ impl<const STACKSIZE: usize> StaticThreadInner<STACKSIZE> {
|
||||
panic!("could not create thread");
|
||||
}
|
||||
|
||||
// let handle = self.handle.take_no_init().unwrap();
|
||||
let handle = &mut Box::new(ThreadHandle {
|
||||
name: "todo",
|
||||
freertos_handle: None,
|
||||
});
|
||||
let handle = self.handle.take_no_init().unwrap();
|
||||
handle.freertos_handle = Some(freertos_handle);
|
||||
|
||||
// Store the Handle in task local storage, so we can use the rust types later on
|
||||
@@ -284,7 +278,7 @@ impl<const STACKSIZE: usize> StaticThreadInner<STACKSIZE> {
|
||||
)
|
||||
};
|
||||
// this creates a copy of handle, as it impls Copy
|
||||
**handle
|
||||
*handle
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![cfg_attr(target_env = "newlib", no_std)]
|
||||
#![cfg_attr(any(target_env = "newlib", feature = "low_level_tests"), no_std)]
|
||||
#![feature(never_type)]
|
||||
#![feature(c_size_t)] // for ffi, tracking issue [88345]
|
||||
|
||||
@@ -6,7 +6,7 @@ mod dh;
|
||||
pub mod fsrc;
|
||||
mod panic;
|
||||
|
||||
//#[cfg(feature = "low_level_tests")]
|
||||
#[cfg(feature = "low_level_tests")]
|
||||
mod low_level_tests;
|
||||
|
||||
use core::fmt::Write;
|
||||
@@ -229,6 +229,6 @@ fn init_task() -> ! {
|
||||
|
||||
mod tests {
|
||||
#[test]
|
||||
fn works_at_all() {
|
||||
fn work_at_all() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,17 +54,25 @@ static TEST_RUNNER_THREAD_DATA: StaticReadOnceLock<
|
||||
extern "C" fn rust_low_level_tests() {
|
||||
// Safe because I do not care right now. TODO
|
||||
unsafe { CONTROLLER_TASK_HANDLE = osal::ffi::freertos_task_current() };
|
||||
run_tests(&mut [function_with_name!(mutex), function_with_name!(fail), function_with_name!(mutex)]);
|
||||
run_tests(&mut [function_with_name!(work_at_all)]);
|
||||
}
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn increment_on_linux(number: &mut u32) {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn increment_on_linux(number: &mut u32) {
|
||||
*number = *number + 1;
|
||||
}
|
||||
|
||||
/// Runner for low level tests, will attempt to look a bit like std rust tests.
|
||||
/// expects a function and its name, to print it
|
||||
/// use the function_with_name! macro to generate the tuple
|
||||
fn run_tests(tests: &mut [(fn(), &'static str)]) -> ! {
|
||||
let stack = TEST_RUNNER_STACK.take_no_init().unwrap();
|
||||
let stack = Arc::new(Mutex::new([0i8;102400]));
|
||||
let thread_data = TEST_RUNNER_THREAD_DATA.take_no_init().unwrap();
|
||||
let thread_data = Arc::new(Mutex::new([0i8;osal::ffi::Sizes::TASK_DATA_SIZE]));
|
||||
|
||||
|
||||
let number_of_tests = tests.len();
|
||||
|
||||
@@ -79,20 +87,21 @@ fn run_tests(tests: &mut [(fn(), &'static str)]) -> ! {
|
||||
|
||||
let mut passed = 0;
|
||||
let mut failed = 0;
|
||||
let mut priority = 1;
|
||||
|
||||
for test in tests {
|
||||
// Note for the pedantic: Static FreeRTOS can not delete tasks, only
|
||||
// suspend them. So it is not formally correct to resuse the task data
|
||||
// and stack. But as the suspended task will not be restarted, it does work
|
||||
// in this (testing!) context.
|
||||
let test_function = test.0 as *const core::ffi::c_void;
|
||||
let stack = &mut stack.lock().unwrap();
|
||||
let thread_data = &mut thread_data.lock().unwrap();
|
||||
for element in thread_data.iter_mut() {
|
||||
*element = 0;
|
||||
}
|
||||
for element in stack.iter_mut() {
|
||||
*element = 0;
|
||||
}
|
||||
unsafe {
|
||||
osal::ffi::freertos_create_task_static(
|
||||
run_one_test,
|
||||
test_function,
|
||||
2,
|
||||
priority,
|
||||
thread_data.as_mut_ptr(),
|
||||
thread_data.len().try_into().unwrap(),
|
||||
stack.as_mut_ptr(),
|
||||
@@ -108,6 +117,11 @@ fn run_tests(tests: &mut [(fn(), &'static str)]) -> ! {
|
||||
sifln!("❌ FAILED");
|
||||
failed+=1;
|
||||
}
|
||||
// some weird bug/effect in FreeRTOS on linux breaks here
|
||||
// if a task priority is reused.
|
||||
// So, we just increase the priority lineary. We mande sure in FreeRTOSConfig.h
|
||||
// to have enough (1024) available.
|
||||
increment_on_linux(&mut priority)
|
||||
}
|
||||
sifln!();
|
||||
|
||||
@@ -118,7 +132,6 @@ fn run_tests(tests: &mut [(fn(), &'static str)]) -> ! {
|
||||
sifln!("test result: ❌ FAILED. {passed} passed; {failed} failed");
|
||||
unsafe { done_error() }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -131,7 +144,7 @@ extern "C" fn run_one_test(parameter: *mut core::ffi::c_void) -> ! {
|
||||
osal::thread::current().delete();
|
||||
}
|
||||
|
||||
fn mutex() {}
|
||||
fn work_at_all() {}
|
||||
|
||||
fn fail() {
|
||||
assert_eq!(1, 2);
|
||||
|
||||
+45
-42
@@ -1,49 +1,52 @@
|
||||
#[cfg(target_env = "newlib")]
|
||||
use core::panic::PanicInfo;
|
||||
#[cfg(target_env = "newlib")]
|
||||
use core::fmt::Write;
|
||||
#[cfg(any(target_env = "newlib", feature = "low_level_tests"))]
|
||||
pub use no_std::*;
|
||||
|
||||
#[cfg(target_env = "newlib")]
|
||||
extern "C" {
|
||||
#[cfg(not(feature = "low_level_tests"))]
|
||||
fn done_error() -> !; // exit code != 0
|
||||
|
||||
#[cfg(feature = "low_level_tests")]
|
||||
//uint32_t freertos_task_notify(void *task, uint32_t value)
|
||||
fn freertos_task_notify(task: *const core::ffi::c_void, value: u32);
|
||||
}
|
||||
#[cfg(any(target_env = "newlib", feature = "low_level_tests"))]
|
||||
mod no_std {
|
||||
use core::fmt::Write;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[cfg(target_env = "newlib")]
|
||||
#[panic_handler]
|
||||
fn panic(panic: &PanicInfo<'_>) -> ! {
|
||||
// unsafe { this breaks in ISR
|
||||
// osal::stop_it();
|
||||
// }
|
||||
_ = writeln!(crate::fsrc::sif::Stderr {}, "");
|
||||
_ = writeln!(
|
||||
crate::fsrc::sif::Stderr {},
|
||||
"Thread '{}' {}",
|
||||
crate::fsrc::osal::thread::current().name(),
|
||||
panic
|
||||
);
|
||||
#[cfg(not(feature = "low_level_tests"))]
|
||||
{
|
||||
unsafe { done_error() };
|
||||
#[allow(unreachable_code)] // safeguard as this is only a weak contract with C
|
||||
loop {}
|
||||
|
||||
extern "C" {
|
||||
#[cfg(not(feature = "low_level_tests"))]
|
||||
fn done_error() -> !; // exit code != 0
|
||||
|
||||
#[cfg(feature = "low_level_tests")]
|
||||
//uint32_t freertos_task_notify(void *task, uint32_t value)
|
||||
fn freertos_task_notify(task: *const core::ffi::c_void, value: u32);
|
||||
}
|
||||
#[cfg(feature = "low_level_tests")]
|
||||
{
|
||||
// When running low level tests, do not exit on panic
|
||||
// but delete thread so the main thread can continue
|
||||
// with the next test
|
||||
unsafe {
|
||||
freertos_task_notify(
|
||||
super::low_level_tests::CONTROLLER_TASK_HANDLE,
|
||||
super::low_level_tests::PANIC,
|
||||
);
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(panic: &PanicInfo<'_>) -> ! {
|
||||
// unsafe { this breaks in ISR
|
||||
// osal::stop_it();
|
||||
// }
|
||||
_ = writeln!(crate::fsrc::sif::Stderr {}, "");
|
||||
_ = writeln!(
|
||||
crate::fsrc::sif::Stderr {},
|
||||
"Thread '{}' {}",
|
||||
crate::fsrc::osal::thread::current().name(),
|
||||
panic
|
||||
);
|
||||
#[cfg(not(feature = "low_level_tests"))]
|
||||
{
|
||||
unsafe { done_error() };
|
||||
#[allow(unreachable_code)] // safeguard as this is only a weak contract with C
|
||||
loop {}
|
||||
}
|
||||
#[cfg(feature = "low_level_tests")]
|
||||
{
|
||||
// When running low level tests, do not exit on panic
|
||||
// but delete thread so the main thread can continue
|
||||
// with the next test
|
||||
unsafe {
|
||||
freertos_task_notify(
|
||||
crate::low_level_tests::CONTROLLER_TASK_HANDLE,
|
||||
crate::low_level_tests::PANIC,
|
||||
);
|
||||
}
|
||||
crate::fsrc::osal::thread::current().delete();
|
||||
}
|
||||
super::osal::thread::current().delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user