#![no_std] #![feature(never_type)] //TODO os errors in API calls pub mod fsrc; mod panic; use core::time::Duration; use core::fmt::Write; use fsrc::*; use osal::{ sync::{Mutex, MutexClone, StaticInit, StaticReadOnceLock}, queue::{MessageQueue, MessageQueueSender}, thread, }; use crate::fsrc::osal::io::{self, HardwareInterface, Read, Write as IoWrite}; 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 interface = HardwareInterface::new("ps/uart_mtg"); let Ok(mut interface) = interface else { let error : io::Error = interface.err().unwrap(); sifln!("open: {error}"); panic!(); }; let buffer = [1,2,3,4]; interface.write(&buffer).unwrap_or_else(|e| sifln!("write: {e}")); let mut buffer = [0u8;30]; let res = interface.read(&mut buffer).unwrap_or_else(|e| {sifln!("read: {e}"); &[]}); sifln!("{res:?}"); osal::thread::current().delay(Duration::from_millis(500)); let res = interface.read(&mut buffer).unwrap_or_else(|e| {sifln!("read: {e}"); &[]}); sifln!("{res:?}"); osal::thread::current().delay(Duration::from_millis(500)); let res = interface.read(&mut buffer).unwrap_or_else(|e| {sifln!("read: {e}"); &[]}); sifln!("{res:?}"); 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(); }