From 63b0a2503070924242a87154e7128eefcb41f219 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 16 Nov 2023 13:45:39 +0100 Subject: [PATCH] implemented queues, broke threads on the way :/ --- mission/freeRTOS_rust_helper.c | 43 ++++++---- mission/main.c | 2 +- mission_rust/src/lib.rs | 146 +++++++++++++++++++++++++++------ 3 files changed, 152 insertions(+), 39 deletions(-) diff --git a/mission/freeRTOS_rust_helper.c b/mission/freeRTOS_rust_helper.c index 744c81a..3cbaccf 100644 --- a/mission/freeRTOS_rust_helper.c +++ b/mission/freeRTOS_rust_helper.c @@ -2,9 +2,11 @@ #include "semphr.h" #include "task.h" +//TODO namespace the names + /** * Task descriptors -*/ + */ #define NUMBER_OF_TASKS 100 SemaphoreHandle_t taskMutex = NULL; StaticSemaphore_t taskMutexDescriptor; @@ -13,7 +15,7 @@ StaticTask_t taskDescriptors[NUMBER_OF_TASKS]; /** * Queue descriptors -*/ + */ #define NUMBER_OF_QUEUES 300 SemaphoreHandle_t queueMutex = NULL; StaticSemaphore_t queueMutexDescriptor; @@ -26,17 +28,13 @@ void initFreeRTOSHelper() { queueMutex = xSemaphoreCreateRecursiveMutexStatic(&queueMutexDescriptor); } -const char * get_task_name() { - return pcTaskGetName( NULL ); -} +const char *get_task_name() { return pcTaskGetName(NULL); } -void stop_it() { - taskENTER_CRITICAL(); -} +void stop_it() { taskENTER_CRITICAL(); } // TODO return some error code? void *create_task(TaskFunction_t taskFunction, void *parameter, void *buffer, - size_t buffersize) { + size_t buffersize) { if (xSemaphoreTakeRecursive(taskMutex, portMAX_DELAY) != pdTRUE) { return NULL; } @@ -60,8 +58,8 @@ 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) { +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 @@ -69,8 +67,25 @@ void * create_queue(size_t length, size_t element_size, uint8_t * buffer) { sizeof(queueDescriptors) / sizeof(*queueDescriptors)) { return NULL; } -QueueHandle_t newQueue = xQueueCreateStatic(length, element_size, buffer, queueDescriptors + nextFreeQueueDescriptor); -nextFreeQueueDescriptor++; -xSemaphoreGiveRecursive(queueMutex); + QueueHandle_t newQueue = xQueueCreateStatic( + length, element_size, buffer, queueDescriptors + nextFreeQueueDescriptor); + nextFreeQueueDescriptor++; + xSemaphoreGiveRecursive(queueMutex); return newQueue; +} + +uint8_t queue_receive(void *queue, void *message) { + if (xQueueReceive(queue, message, portMAX_DELAY) == pdPASS) { + return 1; + } else { + return 0; + } +} + +uint8_t queue_send(void *queue, void *message) { + if (xQueueSend(queue, message, 0) != pdPASS) { + return 1; + } else { + return 0; + } } \ No newline at end of file diff --git a/mission/main.c b/mission/main.c index 6ab1dfa..2d7b563 100644 --- a/mission/main.c +++ b/mission/main.c @@ -175,7 +175,7 @@ void mission(void *) { // printf("Starting Mission\n"); - testIp(); + //testIp(); rust_main(); diff --git a/mission_rust/src/lib.rs b/mission_rust/src/lib.rs index d29ad01..77261b6 100644 --- a/mission_rust/src/lib.rs +++ b/mission_rust/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] //TODO look into using core::ffi (some types do not seem to work) +//TODO os errors in API calls #[macro_export] macro_rules! sifln { @@ -71,6 +72,9 @@ extern "C" { element_size: cty::size_t, buffer: *mut cty::c_void, ) -> *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; } #[no_mangle] @@ -83,6 +87,7 @@ extern "C" fn rust_main() { #[no_mangle] extern "C" fn task_entry(task_object: *mut cty::c_void) { + sifln!("Task Entry"); let task: &mut PeriodicTaskRunner; unsafe { let pointer = task_object as *mut PeriodicTaskRunner; @@ -107,6 +112,7 @@ struct PeriodicTask<'a, const STACKSIZE: usize> { impl<'a> PeriodicTaskRunner<'a> { fn execute(&mut self) { + sifln!("Task Runner {}", self.period); loop { self.task_object.perform(); unsafe { @@ -131,7 +137,6 @@ impl<'a, const STACKSIZE: usize> PeriodicTask<'a, STACKSIZE> { unsafe { instance.task = create_task(task_entry, runner_pointer, stack_pointer, STACKSIZE); } - let a: core::ffi::c_char; if instance.task == 0 as *mut cty::c_void { panic!("could not create Task"); } @@ -149,51 +154,137 @@ impl<'a, const STACKSIZE: usize> Drop for PeriodicTask<'a, STACKSIZE> { struct Handler { id: u32, + //command_queue: MessageQueue, +} + +struct HandlerSender { + id: u32, + cycle: u8, + other_handler: MessageQueueSender, +} + +impl Handler { + fn handle_message(&self, message: Message) { + match message { + Message::OK=> {sifln!("OK");}, + Message::FAILED => {sifln!("FAILED");}, + Message::DATA(data) => {sifln!("p1: {}, p2 {}", data.p1, data.p2);} + } + + } } impl ExecutableObjectIF for Handler { fn perform(&mut self) { sifln!("Handler {} performs", self.id); + // let result = self.command_queue.receive(); + // match result { + // Ok(message) => self.handle_message(message), + // Err(_) => {sifln!("Handler {} got nothing", self.id);} + // } + } +} + +impl ExecutableObjectIF for HandlerSender { + fn perform(&mut self) { + sifln!("HandlerSender {} performs step {}", self.id, self.cycle); + // match self.cycle { + // 0 => {let _ = self.other_handler.send(Message::OK);}, + // 1 => {let _ = self.other_handler.send(Message::FAILED);}, + // 2 => {let _ = self.other_handler.send(Message::DATA(GenericMessageData { p1: 1, p2: 2 }));}, + // _ => (), + // } + // self.cycle += 1; } } struct MessageQueue { - queueId: *const cty::c_void, + queue_id: *const cty::c_void, buffer: [T; LENGTH], } struct MessageQueueSender { - queueId: *const cty::c_void, + queue_id: Option<*const cty::c_void>, + _unused: Option //need to constrain the sender to one message type for safety, but compiler needs that to be used } impl MessageQueue { fn new() -> Self { + let mut instance: Self; unsafe { - let mut instance = Self { - queueId: 0 as *const cty::c_void, - buffer: [core::mem::MaybeUninit::zeroed().assume_init();LENGTH] - }; + instance = Self { + queue_id: 0 as *const cty::c_void, + buffer: [core::mem::MaybeUninit::zeroed().assume_init(); LENGTH], //Gets passed to C/FreeRTOS, so we never ever touch it ever again + }; let buffer_pointer: *mut cty::c_void = &mut instance.buffer as *mut _ as *mut cty::c_void; - instance.queueId = create_queue(LENGTH, core::mem::size_of::(), buffer_pointer); - - if instance.queueId == 0 as *mut cty::c_void { - panic!("could not create Queue"); + instance.queue_id = create_queue(LENGTH, core::mem::size_of::(), buffer_pointer); + + if instance.queue_id == 0 as *mut cty::c_void { + panic!("could not create Queue"); + } + instance } - instance - } } - fn getSender(self) -> MessageQueueSender { - let instance:MessageQueueSender = MessageQueueSender::{queueId: self.queueId}; + fn get_sender(&self) -> MessageQueueSender { + let instance: MessageQueueSender = MessageQueueSender:: { + queue_id: Some(self.queue_id), + _unused: None + }; instance } + + fn receive(&self) -> Result { + let mut message: T; + let res: cty::uint8_t; + unsafe { + message = core::mem::MaybeUninit::zeroed().assume_init(); // We only return it if the queue received something + let message_pointer: *mut cty::c_void = &mut message as *mut _ as *mut cty::c_void; + res = queue_receive(self.queue_id, message_pointer); + } + if res == 1 { + Ok(message) + } else { + Err(()) + } + } } impl MessageQueueSender { - fn send(message: T) { - + fn new() -> Self { + Self { + queue_id: None, + _unused: None + } } + + fn send(&self, message: T) -> Result<(), ()> { + let queue_id = self.queue_id.expect("unitialized Message Queue"); + let res: cty::uint8_t; + unsafe { + let message_pointer: *const cty::c_void = &message as *const _ as *const cty::c_void; + res = queue_send(queue_id, message_pointer); + } + if res == 1 { + Ok(()) + } else { + Err(()) + } + } +} + +#[derive(Clone, Copy)] +struct GenericMessageData { + p1: u32, + p2: u32, +} + +#[derive(Copy, Clone)] +enum Message { + OK, + FAILED, + DATA(GenericMessageData), } struct Outbytes {} @@ -211,22 +302,29 @@ impl Write for Outbytes { } } -fn panics(a: &mut [i32]) { - a[4] = 3; -} fn mission() { sifln!("Mission enter"); - let mut h1 = Handler { id: 1 }; - let mut h2 = Handler { id: 2 }; + let mut h1 = Handler { + id: 1, + //command_queue: MessageQueue::new(), + }; + // let mut h2 = HandlerSender { + // id: 2, + // cycle: 0, + // other_handler: MessageQueueSender::::new(), + // }; + + // h2.other_handler = h1.command_queue.get_sender(); let _t1: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h1); - let _t2: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h2); + //let _t2: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h2); - sifln!("Mission done delay"); + sifln!("Mission delay"); unsafe { task_delay(3000); } + sifln!("Mission delay done"); }