minimult_cortex_m/
msgqueue.rs

1use core::marker::PhantomData;
2
3use crate::minimult::Minimult;
4use crate::memory::MTRawArray;
5use crate::kernel::{MTEvent, MTEventCond};
6use crate::bkptpanic::BKUnwrap;
7
8//
9
10fn wrap_inc(x: usize, bound: usize) -> usize
11{
12    let y = x + 1;
13    if y < bound {y} else {0}
14}
15
16//
17
18/// Message queue for task-to-task communication
19pub struct MTMsgQueue<'a, M>
20{
21    mem: MTRawArray<M>,
22    wr_idx: usize,
23    rd_idx: usize,
24    msg_cnt: MTEvent,
25    phantom: PhantomData<&'a ()>
26}
27
28impl<'a, M> MTMsgQueue<'a, M>
29{
30    pub(crate) fn new(mem: MTRawArray<M>) -> MTMsgQueue<'a, M> // NOTE: lifetime safety correctness
31    {
32        MTMsgQueue {
33            mem,
34            wr_idx: 0,
35            rd_idx: 0,
36            msg_cnt: MTEvent::new(0),
37            phantom: PhantomData
38        }
39    }
40
41    /// Gets sending and receving channels.
42    /// * Returns a tuple of the sender and receiver pair.
43    pub fn ch<'q>(&'q mut self) -> (MTMsgSender<'a, 'q, M>, MTMsgReceiver<'a, 'q, M>)
44    {
45        (
46            MTMsgSender {
47                q: self,
48                phantom: PhantomData
49            },
50            MTMsgReceiver {
51                q: self,
52                phantom: PhantomData
53            }
54        )
55    }
56}
57
58//
59
60/// Message sending channel
61pub struct MTMsgSender<'a, 'q, M>
62{
63    q: *mut MTMsgQueue<'a, M>,
64    phantom: PhantomData<&'q ()>
65}
66
67unsafe impl<M: Send> Send for MTMsgSender<'_, '_, M> {}
68
69impl<M> MTMsgSender<'_, '_, M>
70{
71    /// Gets if there is a vacant message entry.
72    /// * Returns the number of vacant message entries.
73    pub fn vacant(&self) -> usize
74    {
75        let q = unsafe { self.q.as_mut().bk_unwrap() };
76
77        q.mem.len() - q.msg_cnt.cnt()
78    }
79
80    /// Sends a message.
81    /// * `msg` - the message to be sent.
82    /// * Blocks if there is no vacant message entry.
83    pub fn send(&mut self, msg: M)
84    {
85        let q = unsafe { self.q.as_mut().bk_unwrap() };
86
87        loop {
88            if q.msg_cnt.cnt() < q.mem.len() {
89                break;
90            }
91
92            Minimult::wait(&q.msg_cnt, MTEventCond::LessThan(q.mem.len()));
93        }
94
95        let curr_wr_idx = q.wr_idx;
96        let next_wr_idx = wrap_inc(curr_wr_idx, q.mem.len());
97
98        q.mem.write_volatile(curr_wr_idx, msg);
99
100        q.wr_idx = next_wr_idx; // NOTE: volatile access might be necessary
101
102        q.msg_cnt.incr();
103        Minimult::signal(&q.msg_cnt);
104    }
105}
106
107//
108
109/// Message receiving channel
110pub struct MTMsgReceiver<'a, 'q, M>
111{
112    q: *mut MTMsgQueue<'a, M>,
113    phantom: PhantomData<&'q ()>
114}
115
116unsafe impl<M: Send> Send for MTMsgReceiver<'_, '_, M> {}
117
118impl<M> MTMsgReceiver<'_, '_, M>
119{
120    /// Gets if there is an available message entry.
121    /// * Returns the number of available message entries.
122    pub fn available(&self) -> usize
123    {
124        let q = unsafe { self.q.as_mut().bk_unwrap() };
125
126        q.msg_cnt.cnt()
127    }
128
129    /// Receives a message.
130    /// * Returns the received message.
131    /// * Blocks if there is no available message entry.
132    pub fn receive(&mut self) -> M
133    {
134        let q = unsafe { self.q.as_mut().bk_unwrap() };
135
136        loop {
137            if q.msg_cnt.cnt() > 0 {
138                break;
139            }
140
141            Minimult::wait(&q.msg_cnt, MTEventCond::GreaterThan(0));
142        }
143
144        let curr_rd_idx = q.rd_idx;
145        let next_rd_idx = wrap_inc(curr_rd_idx, q.mem.len());
146
147        let msg = q.mem.read_volatile(curr_rd_idx);
148
149        q.rd_idx = next_rd_idx; // NOTE: volatile access might be necessary
150
151        q.msg_cnt.decr();
152        Minimult::signal(&q.msg_cnt);
153
154        msg
155    }
156}