forked from ROMEO/obsw
back to non-static FreeRTOS with heap1; Rust tasks running again and probably stable as well
This commit is contained in:
parent
c08d15215b
commit
5bb01f1731
@ -4,78 +4,38 @@
|
|||||||
|
|
||||||
// TODO namespace the names
|
// TODO namespace the names
|
||||||
|
|
||||||
/**
|
|
||||||
* Task descriptors
|
|
||||||
*/
|
|
||||||
#define NUMBER_OF_TASKS 100
|
|
||||||
SemaphoreHandle_t taskMutex = NULL;
|
|
||||||
StaticSemaphore_t taskMutexDescriptor;
|
|
||||||
size_t nextFreeTaskDescriptor = 0;
|
|
||||||
StaticTask_t taskDescriptors[NUMBER_OF_TASKS];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queue descriptors
|
|
||||||
*/
|
|
||||||
#define NUMBER_OF_QUEUES 300
|
|
||||||
SemaphoreHandle_t queueMutex = NULL;
|
|
||||||
StaticSemaphore_t queueMutexDescriptor;
|
|
||||||
size_t nextFreeQueueDescriptor = 0;
|
|
||||||
StaticQueue_t queueDescriptors[NUMBER_OF_QUEUES];
|
|
||||||
|
|
||||||
// TODO check and return
|
|
||||||
void initFreeRTOSHelper() {
|
|
||||||
taskMutex = xSemaphoreCreateRecursiveMutexStatic(&taskMutexDescriptor);
|
|
||||||
queueMutex = xSemaphoreCreateRecursiveMutexStatic(&queueMutexDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *get_task_name() { return pcTaskGetName(NULL); }
|
const char *get_task_name() { return pcTaskGetName(NULL); }
|
||||||
|
|
||||||
void stop_it() { taskENTER_CRITICAL(); }
|
void stop_it() { taskENTER_CRITICAL(); }
|
||||||
|
|
||||||
// TODO return some error code?
|
// TODO return some error code?
|
||||||
void *create_task(TaskFunction_t taskFunction, void *parameter, void *buffer,
|
void *create_task(TaskFunction_t taskFunction, void *parameter,
|
||||||
size_t buffersize) {
|
size_t stack_size) {
|
||||||
if (xSemaphoreTakeRecursive(taskMutex, portMAX_DELAY) != pdTRUE) {
|
TaskHandle_t newTask;
|
||||||
return NULL;
|
BaseType_t result =
|
||||||
}
|
xTaskCreate(taskFunction, "rust", stack_size, parameter, 4, &newTask);
|
||||||
// we hold the task mutex and are now allowed to access the taskDescriptors
|
if (result == pdTRUE) {
|
||||||
if (nextFreeTaskDescriptor >=
|
|
||||||
sizeof(taskDescriptors) / sizeof(*taskDescriptors)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskHandle_t newTask = xTaskCreateStatic(
|
|
||||||
taskFunction, "rust", buffersize / sizeof(StackType_t), parameter, 4,
|
|
||||||
buffer, taskDescriptors + nextFreeTaskDescriptor);
|
|
||||||
|
|
||||||
nextFreeTaskDescriptor++;
|
|
||||||
|
|
||||||
xSemaphoreGiveRecursive(taskMutex);
|
|
||||||
return newTask;
|
return newTask;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_delay(uint32_t milliseconds) {
|
void task_delay(uint32_t milliseconds) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(milliseconds));
|
vTaskDelay(pdMS_TO_TICKS(milliseconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *create_queue(size_t length, size_t element_size, uint8_t *buffer) {
|
void delete_task(void * task){
|
||||||
if (xSemaphoreTakeRecursive(queueMutex, portMAX_DELAY) != pdTRUE) {
|
vTaskSuspend(task); //we can not use vDeleteTask as it would free the allocated memory which is forbidden using heap1 (which we use)
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
// we hold the queue mutex and are now allowed to access the taskDescriptors
|
void *create_queue(size_t length, size_t element_size) {
|
||||||
if (nextFreeQueueDescriptor >=
|
QueueHandle_t newQueue = xQueueCreate(length, element_size);
|
||||||
sizeof(queueDescriptors) / sizeof(*queueDescriptors)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
QueueHandle_t newQueue = xQueueCreateStatic(
|
|
||||||
length, element_size, buffer, queueDescriptors + nextFreeQueueDescriptor);
|
|
||||||
nextFreeQueueDescriptor++;
|
|
||||||
xSemaphoreGiveRecursive(queueMutex);
|
|
||||||
return newQueue;
|
return newQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t queue_receive(void *queue, void *message) {
|
uint8_t queue_receive(void *queue, void *message) {
|
||||||
if (xQueueReceive(queue, message, portMAX_DELAY) == pdPASS) {
|
if (xQueueReceive(queue, message, 0) == pdPASS) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -131,8 +131,6 @@ int main(void) {
|
|||||||
/* Configure the hardware ready to run the demo. */
|
/* Configure the hardware ready to run the demo. */
|
||||||
prvSetupHardware();
|
prvSetupHardware();
|
||||||
|
|
||||||
initFreeRTOSHelper();
|
|
||||||
|
|
||||||
// printf("Booting Software\n");
|
// printf("Booting Software\n");
|
||||||
|
|
||||||
int taskParameters = 0;
|
int taskParameters = 0;
|
||||||
@ -141,15 +139,15 @@ int main(void) {
|
|||||||
StaticTask_t xTaskBuffer;
|
StaticTask_t xTaskBuffer;
|
||||||
StackType_t xStack[stackSizeWords];
|
StackType_t xStack[stackSizeWords];
|
||||||
|
|
||||||
xTaskCreateStatic(
|
xTaskCreate(
|
||||||
mission, /* The function that implements the task. */
|
mission, /* The function that implements the task. */
|
||||||
"init", /* The text name assigned to the task - for debug only as it is
|
"init", /* The text name assigned to the task - for debug only as it is
|
||||||
not used by the kernel. */
|
not used by the kernel. */
|
||||||
stackSizeWords, /* The size of the stack to allocate to the task. */
|
10240, /* The size of the stack to allocate to the task. */
|
||||||
&taskParameters, /* The parameter passed to the task - not used in this
|
&taskParameters, /* The parameter passed to the task - not used in this
|
||||||
simple case. */
|
simple case. */
|
||||||
4, /* The priority assigned to the task. */
|
4, /* The priority assigned to the task. */
|
||||||
xStack, &xTaskBuffer);
|
NULL);
|
||||||
|
|
||||||
vTaskStartScheduler();
|
vTaskStartScheduler();
|
||||||
|
|
||||||
|
@ -50,28 +50,23 @@ type TaskFunction = unsafe extern "C" fn(*mut cty::c_void);
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn outbyte(c: cty::c_char);
|
fn outbyte(c: cty::c_char);
|
||||||
|
//void *create_task(TaskFunction_t taskFunction, void *parameter, size_t stack_size)
|
||||||
fn create_task(
|
fn create_task(
|
||||||
taskFunction: TaskFunction,
|
taskFunction: TaskFunction,
|
||||||
parameter: *mut cty::c_void,
|
parameter: *const cty::c_void,
|
||||||
buffer: *mut cty::c_void,
|
stack_size: cty::size_t,
|
||||||
buffersize: cty::size_t,
|
|
||||||
) -> *const cty::c_void;
|
) -> *const cty::c_void;
|
||||||
|
|
||||||
fn get_task_name() -> *const core::ffi::c_uchar;
|
fn get_task_name() -> *const core::ffi::c_uchar;
|
||||||
|
|
||||||
fn stop_it();
|
fn stop_it();
|
||||||
|
|
||||||
//TODO wrap os agnostic
|
fn delete_task(handle: *const cty::c_void);
|
||||||
fn vTaskDelete(handle: *const cty::c_void);
|
|
||||||
|
|
||||||
fn task_delay(milliseconds: cty::uint32_t);
|
fn task_delay(milliseconds: cty::uint32_t);
|
||||||
|
|
||||||
fn create_queue(
|
//void *create_queue(size_t length, size_t element_size)
|
||||||
length: cty::size_t,
|
fn create_queue(length: cty::size_t, element_size: cty::size_t) -> *const cty::c_void;
|
||||||
element_size: cty::size_t,
|
|
||||||
buffer: *mut cty::c_void,
|
|
||||||
) -> *const cty::c_void;
|
|
||||||
|
|
||||||
fn queue_receive(queue: *const cty::c_void, message: *const cty::c_void) -> cty::uint8_t;
|
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;
|
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]
|
#[no_mangle]
|
||||||
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!("getting pointer {:p}", task_object);
|
sifln!("running pointer {:p}", task_object);
|
||||||
let task: &mut PeriodicTaskRunner;
|
let task: &mut PeriodicTask;
|
||||||
unsafe {
|
unsafe {
|
||||||
let pointer = task_object as *mut PeriodicTaskRunner;
|
let pointer = task_object as *mut PeriodicTask;
|
||||||
task = &mut *pointer;
|
task = &mut *pointer;
|
||||||
}
|
}
|
||||||
sifln!("casting pointer {:p}", task as *mut PeriodicTaskRunner);
|
sifln!("running cast {:p}", task);
|
||||||
task.execute();
|
task.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,61 +97,65 @@ trait ExecutableObjectIF {
|
|||||||
fn perform(&mut self);
|
fn perform(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeriodicTaskRunner<'a> {
|
struct PeriodicTask<'a> {
|
||||||
period: u32,
|
stack_size: cty::size_t,
|
||||||
|
task_handle: *const cty::c_void,
|
||||||
|
period: usize,
|
||||||
task_object: &'a mut dyn ExecutableObjectIF,
|
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> {
|
impl<'a> PeriodicTask<'a> {
|
||||||
fn execute(&mut self) {
|
fn new(object: &'a mut dyn ExecutableObjectIF, stack_size: usize, period: usize) -> Self {
|
||||||
sifln!("Task Runner {}", self.period);
|
let instance = Self {
|
||||||
loop {
|
stack_size: stack_size,
|
||||||
// self.task_object.perform();
|
task_handle: 0 as *const cty::c_void,
|
||||||
// unsafe {
|
period: period,
|
||||||
// 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,
|
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
|
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> {
|
||||||
fn drop(&mut self) {
|
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 {
|
unsafe {
|
||||||
vTaskDelete(self.task);
|
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) {
|
||||||
|
for task in self.tasks.iter_mut() {
|
||||||
|
unsafe {
|
||||||
|
delete_task(task.task_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,7 +168,7 @@ struct Handler {
|
|||||||
struct HandlerSender {
|
struct HandlerSender {
|
||||||
id: u32,
|
id: u32,
|
||||||
cycle: u8,
|
cycle: u8,
|
||||||
other_handler: MessageQueueSender<Message>,
|
//other_handler: MessageQueueSender<Message>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl Handler {
|
// 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,
|
queue_id: *const cty::c_void,
|
||||||
buffer: [T; LENGTH],
|
buffer: [T; LENGTH],
|
||||||
}
|
}
|
||||||
@ -283,6 +282,8 @@ impl<T> MessageQueueSender<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct GenericMessageData {
|
struct GenericMessageData {
|
||||||
p1: u32,
|
p1: u32,
|
||||||
@ -299,7 +300,6 @@ enum Message {
|
|||||||
struct Outbytes {}
|
struct Outbytes {}
|
||||||
|
|
||||||
use core::fmt::{Error, Write};
|
use core::fmt::{Error, Write};
|
||||||
|
|
||||||
impl Write for Outbytes {
|
impl Write for Outbytes {
|
||||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||||
for c in s.as_bytes() {
|
for c in s.as_bytes() {
|
||||||
@ -326,18 +326,22 @@ fn mission() {
|
|||||||
|
|
||||||
// h2.other_handler = h1.command_queue.get_sender();
|
// 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!(
|
let mut tasks = [t1];
|
||||||
"mission pointer {:p} {:p} {} {:p}",
|
|
||||||
&_t1 as *const PeriodicTask<512>,
|
let task_ref = &mut tasks[..];
|
||||||
&mut _t1.runner as *mut PeriodicTaskRunner,
|
|
||||||
core::mem::size_of::<PeriodicTaskRunner>(),
|
let task1_ref = &task_ref[0];
|
||||||
&_t1.stack as *const _
|
|
||||||
);
|
sifln!("main t1 {:p}", task1_ref);
|
||||||
|
|
||||||
//let _t2: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h2);
|
//let _t2: PeriodicTask<'_, 512> = PeriodicTask::new(&mut h2);
|
||||||
|
|
||||||
|
let mut task_executor = TaskExecutor{tasks: task_ref};
|
||||||
|
|
||||||
|
task_executor.run_tasks();
|
||||||
|
|
||||||
sifln!("Mission delay");
|
sifln!("Mission delay");
|
||||||
unsafe {
|
unsafe {
|
||||||
task_delay(3000);
|
task_delay(3000);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user