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};