back to non-static FreeRTOS with heap1; Rust tasks running again and probably stable as well

This commit is contained in:
2023-11-20 22:46:40 +01:00
parent c08d15215b
commit 5bb01f1731
3 changed files with 94 additions and 132 deletions

View File

@ -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<Message>,
//other_handler: MessageQueueSender<Message>,
}
// impl Handler {
@ -207,7 +206,7 @@ impl ExecutableObjectIF for HandlerSender {
}
}
struct MessageQueue<T, const LENGTH: usize> {
/*struct MessageQueue<T, const LENGTH: usize> {
queue_id: *const cty::c_void,
buffer: [T; LENGTH],
}
@ -283,6 +282,8 @@ impl<T> MessageQueueSender<T> {
}
}
*/
#[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::<PeriodicTaskRunner>(),
&_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);