#![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, } 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, 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 = 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 = 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, } 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) { let _ = queue.send(Message::DATA(self.count)); self.count += 1; } } static SENDER: StaticReadOnceLock = StaticReadOnceLock::new(Sender { count: 0 }); static RECEIVER: StaticReadOnceLock = 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(); }