forked from ROMEO/obsw
adding mutexes, cleaning up types
This commit is contained in:
parent
bae91a61d4
commit
e585ecafcc
@ -43,7 +43,7 @@ typedef s32 (*func_ptr)(int c);
|
||||
void xil_printf( const char8 *ctrl1, ...);
|
||||
void xil_vprintf(const char8 *ctrl1, va_list argp);
|
||||
void print( const char8 *ptr);
|
||||
extern void outbyte (char c);
|
||||
extern void outbyte (uint8_t c);
|
||||
extern char inbyte(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -8,12 +8,12 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void outbyte(char c);
|
||||
void outbyte(uint8_t c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void outbyte(char c) {
|
||||
void outbyte(uint8_t c) {
|
||||
XUartPs_SendByte(STDOUT_BASEADDRESS, c);
|
||||
}
|
||||
|
@ -10,7 +10,8 @@ void stop_it() { taskENTER_CRITICAL(); }
|
||||
|
||||
// TODO return some error code?
|
||||
void *create_task(TaskFunction_t taskFunction, void *parameter,
|
||||
size_t stack_size) {
|
||||
uint32_t stack_size) {
|
||||
//TODO verify uint32_t vs configSTACK_DEPTH_TYPE
|
||||
TaskHandle_t newTask;
|
||||
BaseType_t result =
|
||||
xTaskCreate(taskFunction, "rust", stack_size, parameter, 4, &newTask);
|
||||
@ -22,6 +23,7 @@ void *create_task(TaskFunction_t taskFunction, void *parameter,
|
||||
}
|
||||
|
||||
void task_delay(uint32_t milliseconds) {
|
||||
//TODO verify uint32_t vs TickType_t
|
||||
vTaskDelay(pdMS_TO_TICKS(milliseconds));
|
||||
}
|
||||
|
||||
@ -29,7 +31,8 @@ void delete_task(void * task){
|
||||
vTaskSuspend(task); //we can not use vDeleteTask as it would free the allocated memory which is forbidden using heap1 (which we use)
|
||||
}
|
||||
|
||||
void *create_queue(size_t length, size_t element_size) {
|
||||
void *create_queue(uint32_t length, uint32_t element_size) {
|
||||
//TODO verify uint32_t vs UBaseType_t
|
||||
QueueHandle_t newQueue = xQueueCreate(length, element_size);
|
||||
return newQueue;
|
||||
}
|
||||
@ -49,3 +52,27 @@ uint8_t queue_send(void *queue, void *message) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *create_mutex() {
|
||||
return xSemaphoreCreateRecursiveMutex();
|
||||
}
|
||||
|
||||
uint8_t take_mutex(void * handle) {
|
||||
// TODO check if global semaphore is free (ie, we are doing multitasking)
|
||||
// if not, pointers are invalid, bail out
|
||||
if (xSemaphoreTakeRecursive(handle, portMAX_DELAY) == pdPASS) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t give_mutex(void * handle) {
|
||||
// TODO check if global semaphore is free (ie, we are doing multitasking)
|
||||
// if not, pointers are invalid, bail out
|
||||
if (xSemaphoreGiveRecursive(handle) == pdPASS) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
9
mission_rust/Cargo.lock
generated
9
mission_rust/Cargo.lock
generated
@ -2,15 +2,6 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "mission_rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cty",
|
||||
]
|
||||
|
@ -9,4 +9,3 @@ crate-type = ["staticlib"]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cty = "0.2.2"
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::mutex;
|
||||
use super::objectmanager::SystemObjectIF;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
@ -24,16 +25,18 @@ pub trait DatapoolOwnerIF {
|
||||
pub trait DataSetIF {
|
||||
fn get_type_id(&self) -> TypeId;
|
||||
fn get_actual_data(&self) -> &dyn Reflection;
|
||||
//fn get_mutex_handle(&self) -> TODO
|
||||
fn get_mutex(&self) -> mutex::RawMutex;
|
||||
}
|
||||
|
||||
pub struct OwnedDataset<T: Reflection + Copy> {
|
||||
actual_data: T,
|
||||
mutex: mutex::RawMutex,
|
||||
}
|
||||
|
||||
pub struct ReferencedDataset<T: Reflection + Copy> {
|
||||
//we use a pointer here to avoid lifetimes
|
||||
actual_data: Option<*const T>,
|
||||
mutex: Option<mutex::RawMutex>,
|
||||
}
|
||||
|
||||
impl<T: Reflection + Copy> DataSetIF for OwnedDataset<T> {
|
||||
@ -44,33 +47,54 @@ impl<T: Reflection + Copy> DataSetIF for OwnedDataset<T> {
|
||||
fn get_actual_data(&self) -> &dyn Reflection {
|
||||
&self.actual_data
|
||||
}
|
||||
|
||||
fn get_mutex(&self) -> mutex::RawMutex {
|
||||
return self.mutex;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflection + Copy + Default> OwnedDataset<T> {
|
||||
pub fn new() -> OwnedDataset<T> {
|
||||
OwnedDataset::<T> {
|
||||
actual_data: T::default(),
|
||||
mutex: mutex::RawMutex::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self) -> T {
|
||||
//mutex
|
||||
self.actual_data
|
||||
pub fn read(&mut self) -> Result<T, ()> {
|
||||
let _mutex_guard = match self.mutex.take() {
|
||||
Err(()) => return Err(()),
|
||||
Ok(guard) => guard,
|
||||
};
|
||||
Ok(self.actual_data)
|
||||
}
|
||||
|
||||
//TODO do we want to know if it fails?
|
||||
pub fn commit(&mut self, data: T) {
|
||||
//mutex
|
||||
let _mutex_guard = match self.mutex.take() {
|
||||
Err(()) => return,
|
||||
Ok(guard) => guard,
|
||||
};
|
||||
self.actual_data = data;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflection + Copy + Default> ReferencedDataset<T> {
|
||||
pub fn new() -> ReferencedDataset<T> {
|
||||
ReferencedDataset::<T> { actual_data: None }
|
||||
ReferencedDataset::<T> {
|
||||
actual_data: None,
|
||||
mutex: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self) -> Result<T, ()> {
|
||||
//mutex
|
||||
let _mutex_guard = match self.mutex {
|
||||
None => return Err(()),
|
||||
Some(mutex) => match mutex.take() {
|
||||
Err(()) => return Err(()),
|
||||
Ok(guard) => guard,
|
||||
},
|
||||
};
|
||||
match self.actual_data {
|
||||
None => Err(()),
|
||||
Some(data) => Ok(unsafe { *data }),
|
||||
@ -92,7 +116,7 @@ impl<T: Reflection + Copy + Default> ReferencedDataset<T> {
|
||||
//pointer cast is safe because we checked the type_id
|
||||
//getting pointer to avoid lifetime check
|
||||
self.actual_data = Some(other_set.get_actual_data() as *const dyn Reflection as *const T);
|
||||
//self.mutex = other.mutex
|
||||
self.mutex = Some(other_set.get_mutex());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
//TODO control visibility of internal structs
|
||||
|
||||
pub mod sif;
|
||||
pub mod queues;
|
||||
pub mod osal;
|
||||
pub mod tasks;
|
||||
pub mod objectmanager;
|
||||
pub mod datasets;
|
||||
mod mutex;
|
44
mission_rust/src/fsrc/mutex.rs
Normal file
44
mission_rust/src/fsrc/mutex.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use super::osal;
|
||||
|
||||
// We allow copy because we protext our pointer via a global mutex
|
||||
// when using static allocation (which is TBCoded)
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RawMutex {
|
||||
handle: *const core::ffi::c_void,
|
||||
}
|
||||
|
||||
pub struct RawMutexGuard {
|
||||
handle: *const core::ffi::c_void,
|
||||
}
|
||||
|
||||
impl Drop for RawMutexGuard {
|
||||
fn drop(&mut self) {
|
||||
//TODO do we need some check here?
|
||||
unsafe{osal::give_mutex(self.handle)};
|
||||
}
|
||||
}
|
||||
|
||||
//TODO for non allocating, keep handle as option, to be set either in an initialize() call
|
||||
// or maybe lazy later on, TBD if lazy is needed or we can guarantee init to be called
|
||||
impl RawMutex {
|
||||
pub fn new() -> Self {
|
||||
let handle = unsafe {osal::create_mutex()};
|
||||
Self {
|
||||
handle: handle
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take(&self) -> Result<RawMutexGuard,()> {
|
||||
match unsafe {osal::take_mutex(self.handle)} {
|
||||
1 => Ok(RawMutexGuard { handle: self.handle }),
|
||||
_ => Err(()) //TODO error code
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn give(&self) -> Result<(),()> {
|
||||
// match unsafe {osal::give_mutex(self.handle)} {
|
||||
// 1 => Ok(()),
|
||||
// _ => Err(()) //TODO error code
|
||||
// }
|
||||
// }
|
||||
}
|
@ -1,25 +1,33 @@
|
||||
type TaskFunction = unsafe extern "C" fn(*mut cty::c_void);
|
||||
type TaskFunction = unsafe extern "C" fn(*mut core::ffi::c_void);
|
||||
|
||||
//TODO verify uXX == uintXX_t
|
||||
|
||||
extern "C" {
|
||||
pub fn outbyte(c: cty::c_char);
|
||||
pub fn outbyte(c: u8);
|
||||
//void *create_task(TaskFunction_t taskFunction, void *parameter, size_t stack_size)
|
||||
pub fn create_task(
|
||||
taskFunction: TaskFunction,
|
||||
parameter: *const cty::c_void,
|
||||
stack_size: cty::size_t,
|
||||
) -> *const cty::c_void;
|
||||
parameter: *const core::ffi::c_void,
|
||||
stack_size: u32,
|
||||
) -> *const core::ffi::c_void;
|
||||
|
||||
pub fn get_task_name() -> *const core::ffi::c_char;
|
||||
|
||||
pub fn stop_it();
|
||||
|
||||
pub fn delete_task(handle: *const cty::c_void);
|
||||
pub fn delete_task(handle: *const core::ffi::c_void);
|
||||
|
||||
pub fn task_delay(milliseconds: cty::uint32_t);
|
||||
pub fn task_delay(milliseconds: u32);
|
||||
|
||||
//void *create_queue(size_t length, size_t element_size)
|
||||
pub fn create_queue(length: cty::size_t, element_size: cty::size_t) -> *const cty::c_void;
|
||||
pub fn create_queue(length: u32, element_size: u32) -> *const core::ffi::c_void;
|
||||
|
||||
pub fn queue_receive(queue: *const core::ffi::c_void, message: *const core::ffi::c_void) -> u8;
|
||||
pub fn queue_send(queue: *const core::ffi::c_void, message: *const core::ffi::c_void) -> u8;
|
||||
|
||||
pub fn create_mutex() -> *const core::ffi::c_void;
|
||||
|
||||
pub fn take_mutex(mutex: *const core::ffi::c_void) -> u8;
|
||||
pub fn give_mutex(mutex: *const core::ffi::c_void) -> u8;
|
||||
|
||||
pub fn queue_receive(queue: *const cty::c_void, message: *const cty::c_void) -> cty::uint8_t;
|
||||
pub fn queue_send(queue: *const cty::c_void, message: *const cty::c_void) -> cty::uint8_t;
|
||||
}
|
@ -1,25 +1,24 @@
|
||||
pub struct MessageQueue {
|
||||
queue_id: *const cty::c_void,
|
||||
queue_id: *const core::ffi::c_void,
|
||||
}
|
||||
|
||||
pub struct MessageQueueSender {
|
||||
queue_id: Option<*const cty::c_void>,
|
||||
queue_id: Option<*const core::ffi::c_void>,
|
||||
}
|
||||
|
||||
impl MessageQueue {
|
||||
pub fn new(depth: usize) -> Self {
|
||||
let mut instance: Self;
|
||||
unsafe {
|
||||
instance = Self {
|
||||
queue_id: 0 as *const cty::c_void,
|
||||
};
|
||||
//TODO check cast of depth
|
||||
instance.queue_id = crate::fsrc::osal::create_queue(depth, core::mem::size_of::<Message>());
|
||||
let cast_depth: u32 = u32::try_from(depth).unwrap(); //TODO check these
|
||||
let element_size: u32 = u32::try_from(core::mem::size_of::<Message>()).unwrap();
|
||||
let queue_id = crate::fsrc::osal::create_queue(cast_depth, element_size);
|
||||
|
||||
if instance.queue_id == 0 as *mut cty::c_void {
|
||||
if queue_id == 0 as *mut core::ffi::c_void {
|
||||
panic!("could not create Queue");
|
||||
}
|
||||
instance
|
||||
|
||||
Self { queue_id: queue_id }
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,10 +31,10 @@ impl MessageQueue {
|
||||
|
||||
pub fn receive(&self) -> Result<Message, ()> {
|
||||
let mut message: Message = Message::default();
|
||||
let res: cty::uint8_t;
|
||||
let res: u8;
|
||||
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;
|
||||
let message_pointer: *mut core::ffi::c_void = &mut message as *mut _ as *mut core::ffi::c_void;
|
||||
res = crate::fsrc::osal::queue_receive(self.queue_id, message_pointer);
|
||||
}
|
||||
if res == 1 {
|
||||
@ -48,16 +47,14 @@ impl MessageQueue {
|
||||
|
||||
impl MessageQueueSender {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
queue_id: None,
|
||||
}
|
||||
Self { queue_id: None }
|
||||
}
|
||||
|
||||
pub fn send(&self, message: Message) -> Result<(), ()> {
|
||||
let queue_id = self.queue_id.expect("unitialized Message Queue");
|
||||
let res: cty::uint8_t;
|
||||
let res: u8;
|
||||
unsafe {
|
||||
let message_pointer: *const cty::c_void = &message as *const _ as *const cty::c_void;
|
||||
let message_pointer: *const core::ffi::c_void = &message as *const _ as *const core::ffi::c_void;
|
||||
res = crate::fsrc::osal::queue_send(queue_id, message_pointer);
|
||||
}
|
||||
if res == 1 {
|
||||
|
@ -1,3 +1,5 @@
|
||||
// TODO this is platform specific
|
||||
|
||||
pub struct Outbytes {}
|
||||
|
||||
use core::fmt::{Error, Write};
|
||||
|
@ -3,7 +3,7 @@ use core::slice;
|
||||
use super::objectmanager::ObjectManager;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn task_entry(task_object: *mut cty::c_void) {
|
||||
extern "C" fn task_entry(task_object: *mut core::ffi::c_void) {
|
||||
let task: &mut dyn TaskIF;
|
||||
unsafe {
|
||||
let pointer = task_object as *mut PeriodicTask;
|
||||
@ -18,29 +18,29 @@ pub trait ExecutableObjectIF {
|
||||
|
||||
pub trait TaskIF<'a> {
|
||||
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;
|
||||
fn get_stack_size(&self) -> u32;
|
||||
fn set_handle(&mut self, task_handle: *const core::ffi::c_void);
|
||||
fn get_handle(&self) -> *const core::ffi::c_void;
|
||||
fn get_objects(&'a self) -> &'a [&'a mut dyn crate::objectmanager::SystemObjectIF];
|
||||
fn initialize(&mut self, object_manager: &dyn ObjectManager) -> Result<(), ()>;
|
||||
}
|
||||
|
||||
pub struct PeriodicTask<'a> {
|
||||
pub stack_size: cty::size_t, //TODO generic type and safety
|
||||
pub task_handle: *const cty::c_void,
|
||||
pub period: usize,
|
||||
pub stack_size: u32, //TODO generic type and safety
|
||||
pub task_handle: *const core::ffi::c_void,
|
||||
pub period: u32,
|
||||
pub task_objects: &'a mut [&'a mut dyn crate::objectmanager::SystemObjectIF],
|
||||
}
|
||||
|
||||
impl<'a> PeriodicTask<'a> {
|
||||
pub fn new(
|
||||
objects: &'a mut [&'a mut dyn crate::objectmanager::SystemObjectIF],
|
||||
stack_size: usize,
|
||||
period: usize,
|
||||
stack_size: u32,
|
||||
period: u32,
|
||||
) -> PeriodicTask<'a> {
|
||||
let instance: PeriodicTask<'a> = Self {
|
||||
stack_size: stack_size,
|
||||
task_handle: 0 as *const cty::c_void,
|
||||
task_handle: 0 as *const core::ffi::c_void,
|
||||
period: period,
|
||||
task_objects: objects,
|
||||
};
|
||||
@ -56,17 +56,17 @@ impl<'a> TaskIF<'a> for PeriodicTask<'a> {
|
||||
}
|
||||
//TODO make this exact
|
||||
unsafe {
|
||||
crate::fsrc::osal::task_delay(self.period as cty::uint32_t); //TODO type of delay should be generic but safe (cap to max in C)
|
||||
crate::fsrc::osal::task_delay(self.period); //TODO type of delay should be generic but safe (cap to max in C)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn get_stack_size(&self) -> cty::size_t {
|
||||
fn get_stack_size(&self) -> u32 {
|
||||
self.stack_size
|
||||
}
|
||||
fn set_handle(&mut self, task_handle: *const cty::c_void) {
|
||||
fn set_handle(&mut self, task_handle: *const core::ffi::c_void) {
|
||||
self.task_handle = task_handle;
|
||||
}
|
||||
fn get_handle(&self) -> *const cty::c_void {
|
||||
fn get_handle(&self) -> *const core::ffi::c_void {
|
||||
self.task_handle
|
||||
}
|
||||
fn get_objects(&'a self) -> &'a [&'a mut dyn crate::objectmanager::SystemObjectIF] {
|
||||
@ -104,13 +104,13 @@ impl<'a> TaskExecutor<'a> {
|
||||
// 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; //TODO this does work without the "*" in front of the task -> Why??
|
||||
let task_pointer: *const core::ffi::c_void = *task as *mut _ as *const core::ffi::c_void; //TODO this does work without the "*" in front of the task -> Why??
|
||||
let handle;
|
||||
unsafe {
|
||||
handle =
|
||||
crate::fsrc::osal::create_task(task_entry, task_pointer, task.get_stack_size());
|
||||
crate::fsrc::osal::create_task(task_entry, task_pointer, u32::try_from(task.get_stack_size()).unwrap());
|
||||
}
|
||||
if handle == 0 as *mut cty::c_void {
|
||||
if handle == 0 as *mut core::ffi::c_void {
|
||||
panic!("could not create Task");
|
||||
} else {
|
||||
task.set_handle(handle);
|
||||
|
@ -192,7 +192,7 @@ fn mission() {
|
||||
task_objects: &mut [&mut h2],
|
||||
stack_size: 512,
|
||||
period: 400,
|
||||
task_handle: 0 as *const cty::c_void,
|
||||
task_handle: 0 as *const core::ffi::c_void,
|
||||
};
|
||||
|
||||
let mut task_executor = tasks::TaskExecutor {
|
||||
|
Loading…
x
Reference in New Issue
Block a user