first version of object initialization (I hate (aka do not understand) lifetimes)

This commit is contained in:
Ulrich Mohr 2023-12-06 23:12:00 +01:00
parent a86791b722
commit 29f1383697
5 changed files with 123 additions and 49 deletions

View File

@ -1,4 +1,5 @@
pub mod sif; pub mod sif;
pub mod queues; pub mod queues;
pub mod osal; pub mod osal;
pub mod tasks; pub mod tasks;
pub mod objectmanager;

View File

@ -0,0 +1,12 @@
use super::tasks::ExecutableObjectIF;
pub type ObjectId = usize;
pub trait ObjectManager<'a> {
fn get_object(&self, id: ObjectId) -> Option<&'a dyn SystemObject>;
}
pub trait SystemObject: ExecutableObjectIF {
fn get_id(&self) -> ObjectId;
fn initialize(&mut self, object_manager: &dyn ObjectManager) -> Result<(),()>;
fn get_command_queue(&self) -> crate::fsrc::queues::MessageQueueSender;
}

View File

@ -1,23 +1,20 @@
pub struct MessageQueue<T> { pub struct MessageQueue {
queue_id: *const cty::c_void, queue_id: *const cty::c_void,
_unused: Option<T>, //need to constrain the queue to one message type for safety, but compiler needs that to be used
} }
pub struct MessageQueueSender<T> { pub struct MessageQueueSender {
queue_id: Option<*const cty::c_void>, queue_id: Option<*const cty::c_void>,
_unused: Option<T>, //need to constrain the sender to one message type for safety, but compiler needs that to be used
} }
impl<T: Default> MessageQueue<T> { impl MessageQueue {
pub fn new(depth: usize) -> Self { pub fn new(depth: usize) -> Self {
let mut instance: Self; let mut instance: Self;
unsafe { unsafe {
instance = Self { instance = Self {
queue_id: 0 as *const cty::c_void, queue_id: 0 as *const cty::c_void,
_unused: None, };
};
//TODO check cast of depth //TODO check cast of depth
instance.queue_id = crate::fsrc::osal::create_queue(depth, core::mem::size_of::<T>()); instance.queue_id = crate::fsrc::osal::create_queue(depth, core::mem::size_of::<Message>());
if instance.queue_id == 0 as *mut cty::c_void { if instance.queue_id == 0 as *mut cty::c_void {
panic!("could not create Queue"); panic!("could not create Queue");
@ -26,16 +23,15 @@ impl<T: Default> MessageQueue<T> {
} }
} }
pub fn get_sender(&self) -> MessageQueueSender<T> { pub fn get_sender(&self) -> MessageQueueSender {
let instance: MessageQueueSender<T> = MessageQueueSender::<T> { let instance: MessageQueueSender = MessageQueueSender {
queue_id: Some(self.queue_id), queue_id: Some(self.queue_id),
_unused: None,
}; };
instance instance
} }
pub fn receive(&self) -> Result<T, ()> { pub fn receive(&self) -> Result<Message, ()> {
let mut message: T = T::default(); let mut message: Message = Message::default();
let res: cty::uint8_t; let res: cty::uint8_t;
unsafe { unsafe {
//message = core::mem::MaybeUninit::zeroed().assume_init(); // We only return it if the queue received something //message = core::mem::MaybeUninit::zeroed().assume_init(); // We only return it if the queue received something
@ -50,15 +46,14 @@ impl<T: Default> MessageQueue<T> {
} }
} }
impl<T> MessageQueueSender<T> { impl MessageQueueSender {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
queue_id: None, queue_id: None,
_unused: None, }
}
} }
pub fn send(&self, message: T) -> Result<(), ()> { pub fn send(&self, message: Message) -> Result<(), ()> {
let queue_id = self.queue_id.expect("unitialized Message Queue"); let queue_id = self.queue_id.expect("unitialized Message Queue");
let res: cty::uint8_t; let res: cty::uint8_t;
unsafe { unsafe {

View File

@ -1,3 +1,7 @@
use core::slice;
use super::objectmanager::ObjectManager;
#[no_mangle] #[no_mangle]
extern "C" fn task_entry(task_object: *mut cty::c_void) { extern "C" fn task_entry(task_object: *mut cty::c_void) {
let task: &mut dyn TaskIF; let task: &mut dyn TaskIF;
@ -12,23 +16,25 @@ pub trait ExecutableObjectIF {
fn perform(&mut self); fn perform(&mut self);
} }
pub trait TaskIF { pub trait TaskIF<'a> {
fn run(&mut self); fn run(&mut self);
fn get_stack_size(&self) -> cty::size_t; fn get_stack_size(&self) -> cty::size_t;
fn set_handle(&mut self, task_handle: *const cty::c_void); fn set_handle(&mut self, task_handle: *const cty::c_void);
fn get_handle(&self) -> *const cty::c_void; fn get_handle(&self) -> *const cty::c_void;
fn get_objects(&'a self) -> &'a [&'a mut dyn crate::objectmanager::SystemObject];
fn initialize(&mut self, object_manager: &dyn ObjectManager) -> Result<(), ()>;
} }
pub struct PeriodicTask<'a> { pub struct PeriodicTask<'a> {
pub stack_size: cty::size_t, //TODO generic type and safety pub stack_size: cty::size_t, //TODO generic type and safety
pub task_handle: *const cty::c_void, pub task_handle: *const cty::c_void,
pub period: usize, pub period: usize,
pub task_objects: &'a mut [&'a mut dyn ExecutableObjectIF], pub task_objects: &'a mut [&'a mut dyn crate::objectmanager::SystemObject],
} }
impl<'a> PeriodicTask<'a> { impl<'a> PeriodicTask<'a> {
pub fn new( pub fn new(
objects: &'a mut [&'a mut dyn ExecutableObjectIF], objects: &'a mut [&'a mut dyn crate::objectmanager::SystemObject],
stack_size: usize, stack_size: usize,
period: usize, period: usize,
) -> PeriodicTask<'a> { ) -> PeriodicTask<'a> {
@ -42,7 +48,7 @@ impl<'a> PeriodicTask<'a> {
} }
} }
impl<'a> TaskIF for PeriodicTask<'a> { impl<'a> TaskIF<'a> for PeriodicTask<'a> {
fn run(&mut self) { fn run(&mut self) {
loop { loop {
for object in self.task_objects.iter_mut() { for object in self.task_objects.iter_mut() {
@ -63,14 +69,34 @@ impl<'a> TaskIF for PeriodicTask<'a> {
fn get_handle(&self) -> *const cty::c_void { fn get_handle(&self) -> *const cty::c_void {
self.task_handle self.task_handle
} }
fn get_objects(&'a self) -> &'a [&'a mut dyn crate::objectmanager::SystemObject] {
self.task_objects
}
fn initialize(&mut self, object_manager: &dyn ObjectManager) -> Result<(), ()> {
for object in self.task_objects.iter_mut() {
let result = object.initialize(object_manager);
match result {
Ok(()) => continue,
Err(()) => return Err(()),
}
}
Ok(())
}
} }
pub struct TaskExecutor<'a> { pub struct TaskExecutor<'a> {
pub tasks: &'a mut [&'a mut dyn TaskIF], pub tasks: &'a mut [&'a mut dyn TaskIF<'a>],
} }
impl<'a> TaskExecutor<'a> { impl<'a> TaskExecutor<'a> {
pub fn run_tasks(&mut self) { pub fn run_tasks(&mut self) {
let object_manager = TaskObjectManager {
tasks: unsafe { slice::from_raw_parts(self.tasks.as_ptr(), self.tasks.len()) },
};
for task in self.tasks.iter_mut() {
let _ = task.initialize(&object_manager);
}
drop(object_manager);
for task in self.tasks.iter_mut() { for task in self.tasks.iter_mut() {
// we give away a raw pointer, to be called by an OS task // we give away a raw pointer, to be called by an OS task
// while this is generally very broken, we use a reference tied // while this is generally very broken, we use a reference tied
@ -80,7 +106,8 @@ impl<'a> TaskExecutor<'a> {
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?? 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??
let handle; let handle;
unsafe { unsafe {
handle = crate::fsrc::osal::create_task(task_entry, task_pointer, task.get_stack_size()); handle =
crate::fsrc::osal::create_task(task_entry, task_pointer, task.get_stack_size());
} }
if 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");
@ -91,6 +118,26 @@ impl<'a> TaskExecutor<'a> {
} }
} }
struct TaskObjectManager<'a> {
tasks: &'a [&'a mut dyn TaskIF<'a>],
}
impl<'a> crate::objectmanager::ObjectManager<'a> for TaskObjectManager<'a> {
fn get_object(
&self,
id: crate::objectmanager::ObjectId,
) -> Option<&'a dyn crate::objectmanager::SystemObject> {
for task in self.tasks.iter() {
for object in task.get_objects().iter() {
if object.get_id() == id {
return Some(*object);
}
}
}
None
}
}
impl<'a> Drop for TaskExecutor<'a> { 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() {
@ -99,4 +146,4 @@ impl<'a> Drop for TaskExecutor<'a> {
} }
} }
} }
} }

View File

@ -6,10 +6,10 @@
mod fsrc; mod fsrc;
use core::mem::size_of;
use core::panic::PanicInfo;
use core::fmt::Write; use core::fmt::Write;
use core::panic::PanicInfo;
use fsrc::objectmanager::SystemObject;
use fsrc::*; use fsrc::*;
#[panic_handler] #[panic_handler]
@ -33,8 +33,6 @@ fn panic(panic: &PanicInfo<'_>) -> ! {
loop {} loop {}
} }
#[no_mangle] #[no_mangle]
extern "C" fn rust_main() { extern "C" fn rust_main() {
sifln!("Rust startup 🚀"); sifln!("Rust startup 🚀");
@ -42,16 +40,16 @@ extern "C" fn rust_main() {
sifln!("Mission done"); sifln!("Mission done");
} }
struct Handler { struct Handler {
id: u32, id: objectmanager::ObjectId,
command_queue: queues::MessageQueue<queues::Message>, command_queue: queues::MessageQueue,
} }
struct HandlerSender { struct HandlerSender {
id: u32, id: objectmanager::ObjectId,
other_handler: objectmanager::ObjectId,
cycle: u8, cycle: u8,
other_handler: queues::MessageQueueSender<queues::Message>, other_handler_queue: queues::MessageQueueSender,
} }
impl Handler { impl Handler {
@ -88,15 +86,15 @@ impl tasks::ExecutableObjectIF for HandlerSender {
sifln!("HandlerSender {} performs step {}", self.id, self.cycle); sifln!("HandlerSender {} performs step {}", self.id, self.cycle);
match self.cycle { match self.cycle {
0 => { 0 => {
let _ = self.other_handler.send(queues::Message::OK); let _ = self.other_handler_queue.send(queues::Message::OK);
} }
1 => { 1 => {
let _ = self.other_handler.send(queues::Message::FAILED); let _ = self.other_handler_queue.send(queues::Message::FAILED);
} }
2 => { 2 => {
let _ = self let _ = self.other_handler_queue.send(queues::Message::DATA(
.other_handler queues::GenericMessageData { p1: 13, p2: 2 },
.send(queues::Message::DATA(queues::GenericMessageData { p1: 13, p2: 2 })); ));
} }
_ => (), _ => (),
} }
@ -104,6 +102,34 @@ impl tasks::ExecutableObjectIF for HandlerSender {
} }
} }
impl SystemObject for Handler {
fn get_command_queue(&self) -> crate::fsrc::queues::MessageQueueSender {
self.command_queue.get_sender()
}
fn get_id(&self) -> objectmanager::ObjectId {
self.id
}
fn initialize(&mut self, _object_manager: &dyn objectmanager::ObjectManager) -> Result<(), ()> {
Ok(())
}
}
impl SystemObject for HandlerSender {
fn get_command_queue(&self) -> crate::fsrc::queues::MessageQueueSender {
queues::MessageQueueSender::new()
}
fn get_id(&self) -> objectmanager::ObjectId {
self.id
}
fn initialize(&mut self, object_manager: &dyn objectmanager::ObjectManager) -> Result<(), ()> {
let other_handler = object_manager.get_object(self.other_handler);
match other_handler {
Some(other) => self.other_handler_queue = other.get_command_queue(),
None => return Err(()),
}
Ok(())
}
}
fn mission() { fn mission() {
sifln!("Mission enter"); sifln!("Mission enter");
@ -114,13 +140,12 @@ fn mission() {
}; };
let mut h2 = HandlerSender { let mut h2 = HandlerSender {
id: 2, id: 2,
other_handler: 1,
cycle: 0, cycle: 0,
other_handler: queues::MessageQueueSender::<queues::Message>::new(), other_handler_queue: queues::MessageQueueSender::new(),
}; };
h2.other_handler = h1.command_queue.get_sender(); let array: &mut [&mut dyn objectmanager::SystemObject] = &mut [&mut h1];
let array: &mut [&mut dyn tasks::ExecutableObjectIF] = &mut [&mut h1];
let mut t1 = tasks::PeriodicTask::new(array, 512, 200); let mut t1 = tasks::PeriodicTask::new(array, 512, 200);
@ -131,16 +156,10 @@ fn mission() {
task_handle: 0 as *const cty::c_void, task_handle: 0 as *const cty::c_void,
}; };
let _i = 1;
sifln!("sizeof {}, pointer struct {:p}, pointer element {:p}, next element{:p}", size_of::<tasks::PeriodicTask>(), &t2, t2.task_objects, &_i);
let mut task_executor = tasks::TaskExecutor { let mut task_executor = tasks::TaskExecutor {
tasks: &mut [&mut t1, &mut t2], tasks: &mut [&mut t1, &mut t2],
}; };
sifln!("{:p}", task_executor.tasks[0]);
task_executor.run_tasks(); task_executor.run_tasks();
sifln!("Mission delay"); sifln!("Mission delay");