Files
obsw/mission_rust/src/lib.rs
T
2025-11-05 18:28:35 +01:00

230 lines
5.8 KiB
Rust

#![no_std]
#![feature(never_type)]
#![feature(c_size_t)] // for ffi, tracking issue [88345]
//TODO os errors in API calls
mod dh;
pub mod fsrc;
mod panic;
use core::fmt::Write;
use core::time::Duration;
use fsrc::*;
use osal::{
queue::{MessageQueue, MessageQueueSender},
sync::{Mutex, MutexClone, StaticInit, StaticReadOnceLock},
thread,
};
use crate::{
dh::EchoHandler,
fsrc::{
dh::debug::DeviceHandlerDebugger,
osal::io::HardwareInterface,
},
};
static THREAD_INIT: StaticReadOnceLock<
thread::StaticThread<{ thread::Sizes::MINIMAL_STACK_SIZE + 2024 }>,
> = StaticReadOnceLock::new(thread::StaticThread::new("Init", u32::MAX));
#[no_mangle]
extern "C" fn rust_main() {
// we are already in a task (init task started by C), so we can use all APIs safely,
// but start a new init task anyway to be able to control that task's stack here
sifln!("Rust startup 🚀");
THREAD_INIT.take_no_init().unwrap().spawn(init_task);
// delete self, init task will take over
thread::current().delete();
}
struct Test {
a: u8,
block: Duration,
mutex: Mutex<u8>,
}
struct Test2 {
a: u8,
period: Duration,
}
impl Test {
fn run(&mut self) {
sifln!("Test: {} taking mutex", self.a);
let mut guard = self.mutex.lock();
let data: u8 = *guard;
sifln!("Test: {} took mutex, was {}", self.a, data);
osal::thread::current().delay(self.block);
*guard = self.a;
sifln!("Test: {} giving mutex, is now {}", self.a, *guard);
drop(guard);
sifln!("Test: {} gave mutex", self.a);
}
}
impl Test2 {
pub fn run(&mut self, mutex: MutexClone<u8>, block: Duration) -> ! {
sifln!(
"Stack watermark {}",
osal::thread::current().stack_watermark()
);
loop {
sifln!("Test2: {} taking mutex", self.a);
let mut guard = mutex.lock();
let data: u8 = *guard;
sifln!("{} took mutex, was {}", self.a, data);
sifln!(
"Test2: Stack watermark {}",
osal::thread::current().stack_watermark()
);
osal::thread::current().delay(block);
*guard = self.a;
sifln!("Test2: {} giving mutex, is now {}", self.a, *guard);
drop(guard);
sifln!("Test2: {} gave mutex", self.a);
osal::thread::current().delay(self.period);
}
}
}
impl StaticInit for Test {
fn static_init(&'static mut self) {
self.mutex.static_init();
}
}
impl StaticInit for Test2 {
fn static_init(&'static mut self) {}
}
static TEST1: StaticReadOnceLock<Test> = StaticReadOnceLock::new(Test {
a: 1,
block: Duration::from_millis(1000),
mutex: Mutex::new(13),
});
static THREAD_1: StaticReadOnceLock<
thread::StaticThreadPeriodic<{ thread::Sizes::MINIMAL_STACK_SIZE + 512 }>,
> = StaticReadOnceLock::new(thread::StaticThreadPeriodic::new(
"Thread 1",
2,
Duration::from_millis(1000),
));
static TEST2: StaticReadOnceLock<Test2> = StaticReadOnceLock::new(Test2 {
a: 2,
period: Duration::from_millis(5000),
});
static THREAD_2: StaticReadOnceLock<
thread::StaticThread<{ thread::Sizes::MINIMAL_STACK_SIZE + 512 }>,
> = StaticReadOnceLock::new(thread::StaticThread::new("Thread 2", 2));
#[derive(Copy, Clone, Default)]
pub enum Message {
OK,
#[default]
NONE,
DATA(u8),
}
struct Receiver {
queue: MessageQueue<Message, 100>,
}
impl Receiver {
fn run(&self) {
let message = self.queue.receive();
let message = if let Ok(message) = message {
message
} else {
sifln!("receiver: got nothing");
return;
};
match message {
Message::OK => {
sifln!("receiver: ok");
}
Message::NONE => {
sifln!("receiver: NONE");
}
Message::DATA(data) => {
sifln!("receiver: {}", data);
}
}
}
}
impl StaticInit for Receiver {
fn static_init(&'static mut self) {
self.queue.static_init();
}
}
struct Sender {
count: u8,
}
impl Sender {
fn run(&mut self, queue: MessageQueueSender<Message>) {
let _ = queue.send(Message::DATA(self.count));
self.count += 1;
}
}
static SENDER: StaticReadOnceLock<Sender> = StaticReadOnceLock::new(Sender { count: 0 });
static RECEIVER: StaticReadOnceLock<Receiver> = StaticReadOnceLock::new(Receiver {
queue: MessageQueue::new(),
});
static THREAD_3: StaticReadOnceLock<
thread::StaticThreadPeriodic<{ thread::Sizes::MINIMAL_STACK_SIZE + 512 }>,
> = StaticReadOnceLock::new(thread::StaticThreadPeriodic::new(
"Thread 3",
2,
Duration::from_millis(200),
));
fn init_task() -> ! {
sifln!("Mission enter");
let commands = [dh::Command(0), dh::Command(1), dh::Command(2)];
let mut debugger = DeviceHandlerDebugger::new(
EchoHandler { buffer: [0; 10] },
HardwareInterface::new("debug/uart🚀").unwrap(),
&commands,
&[],
Duration::from_millis(500),
0.5,
);
debugger.run().unwrap();
let test1 = TEST1.take().unwrap();
let test2 = TEST2.take().unwrap();
let receiver = RECEIVER.take().unwrap();
let sender_handle = receiver.queue.sender();
let clone = sender_handle.clone();
let sender = SENDER.take_no_init().unwrap();
let mutex_copy = test1.mutex.clone();
let a = Duration::from_millis(10);
THREAD_2.take_no_init().unwrap().spawn(move || {
test2.run(mutex_copy, a);
});
THREAD_1.take_no_init().unwrap().spawn(move || {
test1.run();
sender.run(clone);
});
THREAD_3.take_no_init().unwrap().spawn(move || {
receiver.run();
});
sifln!("=====================Mission delete");
osal::thread::current().delete();
}