forked from ROMEO/obsw
first version of object initialization (I hate (aka do not understand) lifetimes)
This commit is contained in:
parent
a86791b722
commit
29f1383697
@ -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;
|
12
mission_rust/src/fsrc/objectmanager.rs
Normal file
12
mission_rust/src/fsrc/objectmanager.rs
Normal 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;
|
||||||
|
}
|
@ -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 {
|
||||||
|
@ -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> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user