11
11
#![ no_main]
12
12
#![ no_std]
13
13
14
+ use panic_halt as _;
15
+
16
+ use bxcan:: Frame ;
14
17
use core:: cmp:: Ordering ;
15
18
16
- use bxcan:: { filter:: Mask32 , ExtendedId , Frame , Interrupts , Rx , StandardId , Tx } ;
17
- use heapless:: {
18
- binary_heap:: { BinaryHeap , Max } ,
19
- consts:: * ,
20
- } ;
21
- use nb:: block;
22
- use panic_halt as _;
23
- use rtic:: app;
24
- use stm32f1xx_hal:: {
25
- can:: Can ,
26
- pac:: { Interrupt , CAN1 } ,
27
- prelude:: * ,
28
- } ;
19
+ use heapless:: binary_heap:: { BinaryHeap , Max } ;
20
+
21
+ use stm32f1xx_hal:: pac:: Interrupt ;
29
22
30
23
#[ derive( Debug ) ]
31
24
pub struct PriorityFrame ( Frame ) ;
@@ -52,22 +45,31 @@ impl PartialEq for PriorityFrame {
52
45
53
46
impl Eq for PriorityFrame { }
54
47
55
- fn enqueue_frame ( queue : & mut BinaryHeap < PriorityFrame , U16 , Max > , frame : Frame ) {
48
+ fn enqueue_frame ( queue : & mut BinaryHeap < PriorityFrame , Max , 16 > , frame : Frame ) {
56
49
queue. push ( PriorityFrame ( frame) ) . unwrap ( ) ;
57
50
rtic:: pend ( Interrupt :: USB_HP_CAN_TX ) ;
58
51
}
59
52
60
- #[ app( device = stm32f1xx_hal:: pac, peripherals = true ) ]
61
- const APP : ( ) = {
62
- struct Resources {
53
+ #[ rtic:: app( device = stm32f1xx_hal:: pac) ]
54
+ mod app {
55
+ use super :: { enqueue_frame, PriorityFrame } ;
56
+ use bxcan:: { filter:: Mask32 , ExtendedId , Frame , Interrupts , Rx , StandardId , Tx } ;
57
+ use heapless:: binary_heap:: { BinaryHeap , Max } ;
58
+ use stm32f1xx_hal:: { can:: Can , pac:: CAN1 , prelude:: * } ;
59
+
60
+ #[ local]
61
+ struct Local {
63
62
can_tx : Tx < Can < CAN1 > > ,
64
- can_tx_queue : BinaryHeap < PriorityFrame , U16 , Max > ,
65
- tx_count : usize ,
66
63
can_rx : Rx < Can < CAN1 > > ,
67
64
}
65
+ #[ shared]
66
+ struct Shared {
67
+ can_tx_queue : BinaryHeap < PriorityFrame , Max , 16 > ,
68
+ tx_count : usize ,
69
+ }
68
70
69
71
#[ init]
70
- fn init ( cx : init:: Context ) -> init:: LateResources {
72
+ fn init ( cx : init:: Context ) -> ( Shared , Local , init:: Monotonics ) {
71
73
let mut flash = cx. device . FLASH . constrain ( ) ;
72
74
let rcc = cx. device . RCC . constrain ( ) ;
73
75
@@ -105,23 +107,25 @@ const APP: () = {
105
107
can. enable_interrupts (
106
108
Interrupts :: TRANSMIT_MAILBOX_EMPTY | Interrupts :: FIFO0_MESSAGE_PENDING ,
107
109
) ;
108
- block ! ( can. enable( ) ) . unwrap ( ) ;
110
+ nb :: block!( can. enable( ) ) . unwrap ( ) ;
109
111
110
112
let ( can_tx, can_rx) = can. split ( ) ;
111
113
112
114
let can_tx_queue = BinaryHeap :: new ( ) ;
113
115
114
- init:: LateResources {
115
- can_tx,
116
- can_tx_queue,
117
- tx_count : 0 ,
118
- can_rx,
119
- }
116
+ (
117
+ Shared {
118
+ can_tx_queue,
119
+ tx_count : 0 ,
120
+ } ,
121
+ Local { can_tx, can_rx } ,
122
+ init:: Monotonics ( ) ,
123
+ )
120
124
}
121
125
122
- #[ idle( resources = [ can_tx_queue, tx_count] ) ]
126
+ #[ idle( shared = [ can_tx_queue, tx_count] ) ]
123
127
fn idle ( mut cx : idle:: Context ) -> ! {
124
- let mut tx_queue = cx. resources . can_tx_queue ;
128
+ let mut tx_queue = cx. shared . can_tx_queue ;
125
129
126
130
// Enqueue some messages. Higher ID means lower priority.
127
131
tx_queue. lock ( |mut tx_queue| {
@@ -155,7 +159,7 @@ const APP: () = {
155
159
156
160
// Add some higher priority messages when 3 messages have been sent.
157
161
loop {
158
- let tx_count = cx. resources . tx_count . lock ( |tx_count| * tx_count) ;
162
+ let tx_count = cx. shared . tx_count . lock ( |tx_count| * tx_count) ;
159
163
160
164
if tx_count >= 3 {
161
165
tx_queue. lock ( |mut tx_queue| {
@@ -196,45 +200,50 @@ const APP: () = {
196
200
}
197
201
198
202
// This ISR is triggered by each finished frame transmission.
199
- #[ task( binds = USB_HP_CAN_TX , resources = [ can_tx, can_tx_queue, tx_count] ) ]
203
+ #[ task( binds = USB_HP_CAN_TX , local = [ can_tx] , shared = [ can_tx_queue, tx_count] ) ]
200
204
fn can_tx ( cx : can_tx:: Context ) {
201
- let tx = cx. resources . can_tx ;
202
- let tx_queue = cx. resources . can_tx_queue ;
205
+ let tx = cx. local . can_tx ;
206
+ let mut tx_queue = cx. shared . can_tx_queue ;
207
+ let mut tx_count = cx. shared . tx_count ;
203
208
204
209
tx. clear_interrupt_flags ( ) ;
205
210
206
211
// There is now a free mailbox. Try to transmit pending frames until either
207
212
// the queue is empty or transmission would block the execution of this ISR.
208
- while let Some ( frame) = tx_queue. peek ( ) {
209
- match tx. transmit ( & frame. 0 ) {
210
- Ok ( None ) => {
211
- // Frame was successfully placed into a transmit buffer.
212
- tx_queue. pop ( ) ;
213
- * cx. resources . tx_count += 1 ;
213
+ ( & mut tx_queue, & mut tx_count) . lock ( |tx_queue, tx_count| {
214
+ while let Some ( frame) = tx_queue. peek ( ) {
215
+ match tx. transmit ( & frame. 0 ) {
216
+ Ok ( None ) => {
217
+ // Frame was successfully placed into a transmit buffer.
218
+ tx_queue. pop ( ) ;
219
+ * tx_count += 1 ;
220
+ }
221
+ Ok ( Some ( pending_frame) ) => {
222
+ // A lower priority frame was replaced with our high priority frame.
223
+ // Put the low priority frame back in the transmit queue.
224
+ tx_queue. pop ( ) ;
225
+ enqueue_frame ( tx_queue, pending_frame) ;
226
+ }
227
+ Err ( nb:: Error :: WouldBlock ) => break ,
228
+ Err ( _) => unreachable ! ( ) ,
214
229
}
215
- Ok ( Some ( pending_frame) ) => {
216
- // A lower priority frame was replaced with our high priority frame.
217
- // Put the low priority frame back in the transmit queue.
218
- tx_queue. pop ( ) ;
219
- enqueue_frame ( tx_queue, pending_frame) ;
220
- }
221
- Err ( nb:: Error :: WouldBlock ) => break ,
222
- Err ( _) => unreachable ! ( ) ,
223
230
}
224
- }
231
+ } ) ;
225
232
}
226
233
227
- #[ task( binds = USB_LP_CAN_RX0 , resources = [ can_rx, can_tx_queue] ) ]
228
- fn can_rx0 ( cx : can_rx0:: Context ) {
234
+ #[ task( binds = USB_LP_CAN_RX0 , local = [ can_rx] , shared = [ can_tx_queue] ) ]
235
+ fn can_rx0 ( mut cx : can_rx0:: Context ) {
229
236
// Echo back received packages with correct priority ordering.
230
237
loop {
231
- match cx. resources . can_rx . receive ( ) {
238
+ match cx. local . can_rx . receive ( ) {
232
239
Ok ( frame) => {
233
- enqueue_frame ( cx. resources . can_tx_queue , frame) ;
240
+ cx. shared . can_tx_queue . lock ( |can_tx_queue| {
241
+ enqueue_frame ( can_tx_queue, frame) ;
242
+ } ) ;
234
243
}
235
244
Err ( nb:: Error :: WouldBlock ) => break ,
236
245
Err ( nb:: Error :: Other ( _) ) => { } // Ignore overrun errors.
237
246
}
238
247
}
239
248
}
240
- } ;
249
+ }
0 commit comments