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
/*! 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`) `Minimult` is still in **beta** because the author had only a few tests only on Cortex-M4 with FPU. # 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 Outline ```no_run // Build-only example #![no_main] #![no_std] use cortex_m::Peripherals; use cortex_m_rt::entry; use cortex_m_rt::exception; extern crate panic_semihosting; // other codes... use minimult_cortex_m::*; #[entry] fn main() -> ! { let mut mem = Minimult::mem::<[u8; 4096]>(); let mut mt = Minimult::new(&mut mem, 2); // other codes... let mut q = mt.msgq::<u32>(4); let (snd, rcv) = q.ch(); mt.register(0/*tid*/, 1, 256, || task0(snd)); mt.register(1/*tid*/, 1, 256, || task1(rcv)); // other codes... let cmperi = Peripherals::take().unwrap(); let mut syst = cmperi.SYST; syst.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core); syst.set_reload(0xffffff); syst.clear_current(); syst.enable_counter(); syst.enable_interrupt(); // other codes... mt.run() } #[exception] fn SysTick() { // other codes... Minimult::kick(0/*tid*/); } fn task0(mut snd: MTMsgSender<u32>) { // other codes... loop { Minimult::idle(); // other codes... let some_value = 1; snd.send(some_value); } } fn task1(mut rcv: MTMsgReceiver<u32>) { // other codes... loop { let some_value = rcv.receive(); assert_eq!(some_value, 1); // other codes... } } ``` ## 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 /// 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 };