Tasks running using TaskIF; with debug code

This commit is contained in:
Ulrich Mohr 2023-11-22 10:15:46 +01:00
parent f02e847ef1
commit e69e97eb4c

View File

@ -84,21 +84,28 @@ extern "C" fn rust_main() {
extern "C" fn task_entry(task_object: *mut cty::c_void) { extern "C" fn task_entry(task_object: *mut cty::c_void) {
sifln!("Task Entry"); sifln!("Task Entry");
sifln!("running pointer {:p}", task_object); sifln!("running pointer {:p}", task_object);
let task: &mut PeriodicTask; let task: &mut dyn TaskIF;
unsafe { unsafe {
let pointer = task_object as *mut PeriodicTask; let pointer = task_object as *mut PeriodicTask;
task = &mut *pointer; task = &mut *pointer;
} }
sifln!("running cast {:p}", task); sifln!("running cast {:p}", task);
task.execute(); task.run();
} }
trait ExecutableObjectIF { trait ExecutableObjectIF {
fn perform(&mut self); fn perform(&mut self);
} }
trait TaskIF {
fn run(&mut self);
fn get_stack_size(&self) -> cty::size_t;
fn set_handle(&mut self, task_handle: *const cty::c_void);
fn get_handle(&self) -> *const cty::c_void;
}
struct PeriodicTask<'a> { struct PeriodicTask<'a> {
stack_size: cty::size_t, stack_size: cty::size_t, //TODO generic type and safety
task_handle: *const cty::c_void, task_handle: *const cty::c_void,
period: usize, period: usize,
task_object: &'a mut dyn ExecutableObjectIF, task_object: &'a mut dyn ExecutableObjectIF,
@ -114,37 +121,51 @@ impl<'a> PeriodicTask<'a> {
}; };
instance instance
} }
}
fn execute(&mut self) { impl<'a> TaskIF for PeriodicTask<'a> {
fn run(&mut self) {
sifln!("Task running {}", self.period); sifln!("Task running {}", self.period);
loop { loop {
self.task_object.perform(); self.task_object.perform();
unsafe { unsafe {
task_delay(self.period as cty::uint32_t); task_delay(self.period as cty::uint32_t); //TODO type of delay should be generic but safe (cap to max in C)
} }
} }
} }
fn get_stack_size(&self) -> cty::size_t {
self.stack_size
}
fn set_handle(&mut self, task_handle: *const cty::c_void) {
self.task_handle = task_handle;
}
fn get_handle(&self) -> *const cty::c_void {
self.task_handle
}
} }
struct TaskExecutor<'a> { struct TaskExecutor<'a> {
tasks: &'a mut [PeriodicTask<'a>], tasks: &'a mut [&'a mut dyn TaskIF],
} }
impl<'a> TaskExecutor<'a> { impl<'a> TaskExecutor<'a> {
fn run_tasks(&mut self) { fn run_tasks(&mut self) {
for task in self.tasks.iter_mut() { for task in self.tasks.iter_mut() {
// we give away a raw pointer, top be called by an OS task // we give away a raw pointer, to be called by an OS task
// while this is generally very broke, we use a reference tied // while this is generally very broken, we use a reference tied
// to our own lifetime and destroy the task when we get dropped // to our own lifetime and destroy the task when we get dropped
// this way, the reference is guaranteed to be valid over our // this way, the reference is guaranteed to be valid over our
// lifetime while the task is deleted at the end of our lifetime // 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; let task_pointer: *const cty::c_void = *task as *mut _ as *const cty::c_void; //TODO this does work without the "*" in front of the task -> Why??
sifln!("create task {:p}", task_pointer); sifln!("create task {:p}", task_pointer);
let handle;
unsafe { unsafe {
task.task_handle = create_task(task_entry, task_pointer, task.stack_size); handle = create_task(task_entry, task_pointer, task.get_stack_size());
} }
if task.task_handle == 0 as *mut cty::c_void { if handle == 0 as *mut cty::c_void {
panic!("could not create Task"); panic!("could not create Task");
} else {
task.set_handle(handle);
} }
} }
} }
@ -154,7 +175,7 @@ impl<'a> Drop for TaskExecutor<'a> {
fn drop(&mut self) { fn drop(&mut self) {
for task in self.tasks.iter_mut() { for task in self.tasks.iter_mut() {
unsafe { unsafe {
delete_task(task.task_handle); delete_task(task.get_handle());
} }
} }
} }
@ -320,18 +341,27 @@ fn mission() {
}; };
let mut h2 = Handler { let mut h2 = Handler {
id: 2, id: 2,
// cycle: 0, // cycle: 0,
// other_handler: MessageQueueSender::<Message>::new(), // other_handler: MessageQueueSender::<Message>::new(),
}; };
// h2.other_handler = h1.command_queue.get_sender(); // h2.other_handler = h1.command_queue.get_sender();
let t1: PeriodicTask = PeriodicTask::new(&mut h1, 512, 200); let mut t1: PeriodicTask = PeriodicTask::new(&mut h1, 512, 200);
let t2: PeriodicTask = PeriodicTask::new(&mut h2, 512, 300); let mut t2: PeriodicTask = PeriodicTask::new(&mut h2, 512, 300);
sifln!("t1 {:p}", &t1);
let mut task_executor = TaskExecutor{tasks: &mut [t1,t2]}; let r1: &mut dyn TaskIF = &mut t1;
sifln!("as dyn {:p}", r1);
let mut task_executor = TaskExecutor {
tasks: &mut [&mut t1, &mut t2],
};
sifln!("{:p}", task_executor.tasks[0]);
task_executor.run_tasks(); task_executor.run_tasks();
@ -339,7 +369,7 @@ fn mission() {
unsafe { unsafe {
task_delay(2000); task_delay(2000);
} }
sifln!("Mission delay2"); sifln!("executor dropped");
drop(task_executor); drop(task_executor);
//t2.period = 100; //Invalid //t2.period = 100; //Invalid
h1.id = 2; h1.id = 2;