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
/*! 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`) * Cortex-M4 / M7 with FPU (`thumbv7em-none-eabihf`) * Cortex-M23 (`thumbv8m.base-none-eabi`) * Cortex-M33 / M35P (`thumbv8m.main-none-eabi`) `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. * 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 #![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(snd: MTMsgSender<u32>) { // other codes... loop { Minimult::idle(); // other codes... let some_value = 1; snd.send(some_value); } } fn task1(rcv: MTMsgReceiver<u32>) { // other codes... loop { let mut some_value = 0; rcv.receive(|v| {some_value = *v}); // 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] mod minimult; pub use crate::minimult::{Minimult, MTMsgSender, MTMsgReceiver}; pub use crate::minimult::{MTTaskId, MTTaskPri, MTMemBlk, MTMsgQueue};