1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/*! This crate for Rust provides a minimal multitask library `Minimult` for Cortex-M microcontrollers. # Target *Single-core* systems of * Cortex-M0 / M0+ / M1 (`thumbv6m-none-eabi`) * Cortex-M3 (`thumbv7m-none-eabi`) * Cortex-M4 / M7 (`thumbv7em-none-eabi`) with FPU (`thumbv7em-none-eabihf`) * Cortex-M23 (`thumbv8m.base-none-eabi`) * Cortex-M33 / M35P (`thumbv8m.main-none-eabi`) with FPU (`thumbv8m.main-none-eabihf`) # Features * Task like that of a typical RTOS * `Minimult` can take closures and register them as tasks. * `Minimult` runs into a loop to start dispatching those tasks. * *Not supported: dynamically creating and spawning.* * Synchronization * `idle` and `kick` * A task goes into an idle state and other tasks/interrupts wake it up by kicking. * `MTMsgSender` and `MTMsgReceiver` * Task-to-task communication by message passing. * `MTSharedCh` * Shared variable among tasks. * Priority-based dispatching * A higher priority task preempts lower priority tasks. * Round-robin dispatching within the same priority tasks. * `dispatch` can be directly requested so that timer-based preemption is also possible. * Static memory allocation * `Minimult` doesn't require a global allocator but reserves a bunch of memory block in advance. # Examples ## Usage ``` // Runnable on QEMU ARM #![no_main] #![no_std] use cortex_m::Peripherals; use cortex_m_rt::entry; use cortex_m_rt::exception; use cortex_m_semihosting::debug; use cortex_m_semihosting::hprintln; use panic_semihosting as _; use minimult_cortex_m::*; #[entry] fn main() -> ! { let mut mem = Minimult::mem::<[u8; 4096]>(); let mut mt = Minimult::new(&mut mem, 3); let mut q = mt.msgq::<u32>(4); let (snd, rcv) = q.ch(); let sh = mt.share::<u32>(0); let shch1 = sh.ch(); let shch2 = sh.ch(); mt.register(0/*tid*/, 1, 256, || task0(snd)); mt.register(1/*tid*/, 1, 256, || task1(rcv, shch1)); mt.register(2/*tid*/, 1, 256, || task2(shch2)); // SysTick settings let cmperi = Peripherals::take().unwrap(); let mut syst = cmperi.SYST; syst.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core); syst.set_reload(1_000_000); syst.clear_current(); syst.enable_counter(); syst.enable_interrupt(); // must be error in terms of lifetime and ownership //drop(mem); //drop(q); //drop(snd); //drop(rcv); //drop(sh); //drop(shch1); //drop(shch2); hprintln!("Minimult run").unwrap(); mt.run() } #[exception] fn SysTick() { Minimult::kick(0/*tid*/); } fn task0(mut snd: MTMsgSender<u32>) { for vsnd in 0.. { Minimult::idle(); hprintln!("task0 send {}", vsnd).unwrap(); snd.send(vsnd); } } fn task1(mut rcv: MTMsgReceiver<u32>, shch: MTSharedCh<u32>) { for i in 0.. { let vrcv = rcv.receive(); assert_eq!(i, vrcv); hprintln!("task1 touch {}", vrcv).unwrap(); let mut vtouch = shch.touch(); *vtouch = vrcv; } } fn task2(shch: MTSharedCh<u32>) { let mut j = 0; while j < 50 { let vlook = shch.look(); assert!(j <= *vlook); //hprintln!("task2 look {}", *vlook).unwrap(); // many lines printed j = *vlook; } hprintln!("task2 exit").unwrap(); debug::exit(debug::EXIT_SUCCESS); } ``` ## Other Examples You can find a specific board's example [here](https://github.com/convexbrain/Minimult/tree/master/examples/). Currently there are very few examples, however. */ #![no_std] /* Type parameter rule: * A: method-level general variable * F: method-level general closure * V: struct-level general variable * T: task closure * I: index * K: key * M: message * B: memory block */ mod minimult; // Lifetime safe and high-level API wrapper mod kernel; // Low-level unsafe and lifetime unbounded singleton mod bheap; // binary heap and list mod memory; // static memory allocation mod msgqueue; // message queue mod shared; // read-write shared variable mod bkptpanic; // bkpt panic, assert and unwrap /// Task identifier pub type MTTaskId = u16; /// Task priority pub type MTTaskPri = u8; pub use crate::minimult::{ Minimult }; pub use crate::memory::{ MTMemBlk }; pub use crate::msgqueue::{ MTMsgSender, MTMsgReceiver, MTMsgQueue }; pub use crate::shared::{ MTSharedCh, MTShared, MTSharedLook, MTSharedTouch };