minimult_cortex_m/
lib.rs

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