From 5bb01f1731dbabffcf3b9754533eb070ef7a9065 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Mon, 20 Nov 2023 22:46:40 +0100 Subject: [PATCH] back to non-static FreeRTOS with heap1; Rust tasks running again and probably stable as well --- mission/freeRTOS_rust_helper.c | 70 ++++------------ mission/main.c | 8 +- mission_rust/src/lib.rs | 148 +++++++++++++++++---------------- 3 files changed, 94 insertions(+), 132 deletions(-) diff --git a/mission/freeRTOS_rust_helper.c b/mission/freeRTOS_rust_helper.c index 265965a..7fc3fbb 100644 --- a/mission/freeRTOS_rust_helper.c +++ b/mission/freeRTOS_rust_helper.c @@ -4,78 +4,38 @@ // TODO namespace the names -/** - * Task descriptors - */ -#define NUMBER_OF_TASKS 100 -SemaphoreHandle_t taskMutex = NULL; -StaticSemaphore_t taskMutexDescriptor; -size_t nextFreeTaskDescriptor = 0; -StaticTask_t taskDescriptors[NUMBER_OF_TASKS]; - -/** - * Queue descriptors - */ -#define NUMBER_OF_QUEUES 300 -SemaphoreHandle_t queueMutex = NULL; -StaticSemaphore_t queueMutexDescriptor; -size_t nextFreeQueueDescriptor = 0; -StaticQueue_t queueDescriptors[NUMBER_OF_QUEUES]; - -// TODO check and return -void initFreeRTOSHelper() { - taskMutex = xSemaphoreCreateRecursiveMutexStatic(&taskMutexDescriptor); - queueMutex = xSemaphoreCreateRecursiveMutexStatic(&queueMutexDescriptor); -} - const char *get_task_name() { return pcTaskGetName(NULL); } void stop_it() { taskENTER_CRITICAL(); } // TODO return some error code? -void *create_task(TaskFunction_t taskFunction, void *parameter, void *buffer, - size_t buffersize) { - if (xSemaphoreTakeRecursive(taskMutex, portMAX_DELAY) != pdTRUE) { +void *create_task(TaskFunction_t taskFunction, void *parameter, + size_t stack_size) { + TaskHandle_t newTask; + BaseType_t result = + xTaskCreate(taskFunction, "rust", stack_size, parameter, 4, &newTask); + if (result == pdTRUE) { + return newTask; + } else { return NULL; } - // we hold the task mutex and are now allowed to access the taskDescriptors - if (nextFreeTaskDescriptor >= - sizeof(taskDescriptors) / sizeof(*taskDescriptors)) { - return NULL; - } - - TaskHandle_t newTask = xTaskCreateStatic( - taskFunction, "rust", buffersize / sizeof(StackType_t), parameter, 4, - buffer, taskDescriptors + nextFreeTaskDescriptor); - - nextFreeTaskDescriptor++; - - xSemaphoreGiveRecursive(taskMutex); - return newTask; } void task_delay(uint32_t milliseconds) { vTaskDelay(pdMS_TO_TICKS(milliseconds)); } -void *create_queue(size_t length, size_t element_size, uint8_t *buffer) { - if (xSemaphoreTakeRecursive(queueMutex, portMAX_DELAY) != pdTRUE) { - return NULL; - } - // we hold the queue mutex and are now allowed to access the taskDescriptors - if (nextFreeQueueDescriptor >= - sizeof(queueDescriptors) / sizeof(*queueDescriptors)) { - return NULL; - } - QueueHandle_t newQueue = xQueueCreateStatic( - length, element_size, buffer, queueDescriptors + nextFreeQueueDescriptor); - nextFreeQueueDescriptor++; - xSemaphoreGiveRecursive(queueMutex); +void delete_task(void * task){ + vTaskSuspend(task); //we can not use vDeleteTask as it would free the allocated memory which is forbidden using heap1 (which we use) +} + +void *create_queue(size_t length, size_t element_size) { + QueueHandle_t newQueue = xQueueCreate(length, element_size); return newQueue; } uint8_t queue_receive(void *queue, void *message) { - if (xQueueReceive(queue, message, portMAX_DELAY) == pdPASS) { + if (xQueueReceive(queue, message, 0) == pdPASS) { return 1; } else { return 0; diff --git a/mission/main.c b/mission/main.c index 7fdb6f7..3f39d59 100644 --- a/mission/main.c +++ b/mission/main.c @@ -131,8 +131,6 @@ int main(void) { /* Configure the hardware ready to run the demo. */ prvSetupHardware(); - initFreeRTOSHelper(); - // printf("Booting Software\n"); int taskParameters = 0; @@ -141,15 +139,15 @@ int main(void) { StaticTask_t xTaskBuffer; StackType_t xStack[stackSizeWords]; - xTaskCreateStatic( + xTaskCreate( mission, /* The function that implements the task. */ "init", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ - stackSizeWords, /* The size of the stack to allocate to the task. */ + 10240, /* The size of the stack to allocate to the task. */ &taskParameters, /* The parameter passed to the task - not used in this simple case. */ 4, /* The priority assigned to the task. */ - xStack, &xTaskBuffer); + NULL); vTaskStartScheduler(); diff --git a/mission_rust/src/lib.rs b/mission_rust/src/lib.rs index 3396bcd..2b1f204 100644 --- a/mission_rust/src/lib.rs +++ b/mission_rust/src/lib.rs @@ -50,28 +50,23 @@ type TaskFunction = unsafe extern "C" fn(*mut cty::c_void); extern "C" { fn outbyte(c: cty::c_char); - + //void *create_task(TaskFunction_t taskFunction, void *parameter, size_t stack_size) fn create_task( taskFunction: TaskFunction, - parameter: *mut cty::c_void, - buffer: *mut cty::c_void, - buffersize: cty::size_t, + parameter: *const cty::c_void, + stack_size: cty::size_t, ) -> *const cty::c_void; fn get_task_name() -> *const core::ffi::c_uchar; fn stop_it(); - //TODO wrap os agnostic - fn vTaskDelete(handle: *const cty::c_void); + fn delete_task(handle: *const cty::c_void); fn task_delay(milliseconds: cty::uint32_t); - fn create_queue( - length: cty::size_t, - element_size: cty::size_t, - buffer: *mut cty::c_void, - ) -> *const cty::c_void; + //void *create_queue(size_t length, size_t element_size) + fn create_queue(length: cty::size_t, element_size: cty::size_t) -> *const cty::c_void; fn queue_receive(queue: *const cty::c_void, message: *const cty::c_void) -> cty::uint8_t; fn queue_send(queue: *const cty::c_void, message: *const cty::c_void) -> cty::uint8_t; @@ -88,13 +83,13 @@ extern "C" fn rust_main() { #[no_mangle] extern "C" fn task_entry(task_object: *mut cty::c_void) { sifln!("Task Entry"); - sifln!("getting pointer {:p}", task_object); - let task: &mut PeriodicTaskRunner; + sifln!("running pointer {:p}", task_object); + let task: &mut PeriodicTask; unsafe { - let pointer = task_object as *mut PeriodicTaskRunner; + let pointer = task_object as *mut PeriodicTask; task = &mut *pointer; } - sifln!("casting pointer {:p}", task as *mut PeriodicTaskRunner); + sifln!("running cast {:p}", task); task.execute(); } @@ -102,61 +97,65 @@ trait ExecutableObjectIF { fn perform(&mut self); } -struct PeriodicTaskRunner<'a> { - period: u32, +struct PeriodicTask<'a> { + stack_size: cty::size_t, + task_handle: *const cty::c_void, + period: usize, task_object: &'a mut dyn ExecutableObjectIF, } -struct PeriodicTask<'a, const STACKSIZE: usize> { - stack: [u8; STACKSIZE], - task: *const cty::c_void, - runner: PeriodicTaskRunner<'a>, -} -impl<'a> PeriodicTaskRunner<'a> { - fn execute(&mut self) { - sifln!("Task Runner {}", self.period); - loop { - // self.task_object.perform(); - // unsafe { - // task_delay(self.period); - // } - unsafe { task_delay(200) }; - } - } -} - -impl<'a, const STACKSIZE: usize> PeriodicTask<'a, STACKSIZE> { - fn new(object: &'a mut dyn ExecutableObjectIF) -> Self { - let mut instance = Self { - stack: [0; STACKSIZE], - task: 0 as *const cty::c_void, - runner: PeriodicTaskRunner { - period: 500, - task_object: object, - }, +impl<'a> PeriodicTask<'a> { + fn new(object: &'a mut dyn ExecutableObjectIF, stack_size: usize, period: usize) -> Self { + let instance = Self { + stack_size: stack_size, + task_handle: 0 as *const cty::c_void, + period: period, + task_object: object, }; - let runner_pointer: *mut cty::c_void = &mut instance.runner as *mut _ as *mut cty::c_void; - let stack_pointer: *mut cty::c_void = &mut instance.stack as *mut _ as *mut cty::c_void; - sifln!( - "giving pointer {:p} {:p}, instance {:p}", - runner_pointer, - &mut instance.runner as *mut PeriodicTaskRunner, - &instance as *const Self - ); - unsafe { - instance.task = create_task(task_entry, runner_pointer, stack_pointer, STACKSIZE); - } - if instance.task == 0 as *mut cty::c_void { - panic!("could not create Task"); - } instance } + + fn execute(&mut self) { + sifln!("Task running {}", self.period); + loop { + self.task_object.perform(); + unsafe { + task_delay(self.period as cty::uint32_t); + } + } + } } -impl<'a, const STACKSIZE: usize> Drop for PeriodicTask<'a, STACKSIZE> { +struct TaskExecutor<'a> { + tasks: &'a mut [PeriodicTask<'a>], +} + +impl<'a> TaskExecutor<'a> { + fn run_tasks(&mut self) { + for task in self.tasks.iter_mut() { + // we give away a raw pointer, top be called by an OS task + // while this is generally very broke, we use a reference tied + // to our own lifetime and destroy the task when we get dropped + // this way, the reference is guaranteed to be valid over our + // lifetime while the task is deleted at the end of our lifetime + let task_pointer: *const cty::c_void = task as *mut _ as *const cty::c_void; + sifln!("create task {:p}", task_pointer); + unsafe { + task.task_handle = create_task(task_entry, task_pointer, task.stack_size); + } + if task.task_handle == 0 as *mut cty::c_void { + panic!("could not create Task"); + } + } + } +} + +impl<'a> Drop for TaskExecutor<'a> { fn drop(&mut self) { - unsafe { - vTaskDelete(self.task); + for task in self.tasks.iter_mut() { + unsafe { + delete_task(task.task_handle); + } } } } @@ -169,7 +168,7 @@ struct Handler { struct HandlerSender { id: u32, cycle: u8, - other_handler: MessageQueueSender, + //other_handler: MessageQueueSender, } // impl Handler { @@ -207,7 +206,7 @@ impl ExecutableObjectIF for HandlerSender { } } -struct MessageQueue { +/*struct MessageQueue { queue_id: *const cty::c_void, buffer: [T; LENGTH], } @@ -283,6 +282,8 @@ impl MessageQueueSender { } } +*/ + #[derive(Clone, Copy)] struct GenericMessageData { p1: u32, @@ -299,7 +300,6 @@ enum Message { struct Outbytes {} use core::fmt::{Error, Write}; - impl Write for Outbytes { fn write_str(&mut self, s: &str) -> Result<(), Error> { for c in s.as_bytes() { @@ -326,18 +326,22 @@ fn mission() { // h2.other_handler = h1.command_queue.get_sender(); - let mut _t1: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h1); + let t1: PeriodicTask = PeriodicTask::new(&mut h1, 512, 200); - sifln!( - "mission pointer {:p} {:p} {} {:p}", - &_t1 as *const PeriodicTask<512>, - &mut _t1.runner as *mut PeriodicTaskRunner, - core::mem::size_of::(), - &_t1.stack as *const _ - ); + let mut tasks = [t1]; + + let task_ref = &mut tasks[..]; + + let task1_ref = &task_ref[0]; + + sifln!("main t1 {:p}", task1_ref); //let _t2: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h2); + let mut task_executor = TaskExecutor{tasks: task_ref}; + + task_executor.run_tasks(); + sifln!("Mission delay"); unsafe { task_delay(3000);