28
28
#include "py/mperrno.h"
29
29
#include "py/mphal.h"
30
30
#include "can.h"
31
+ #include "pyb_can.h"
31
32
#include "irq.h"
32
33
33
34
#if MICROPY_HW_ENABLE_CAN
34
35
35
- void can_init0 (void ) {
36
- for (uint i = 0 ; i < MP_ARRAY_SIZE (MP_STATE_PORT (pyb_can_obj_all )); i ++ ) {
37
- MP_STATE_PORT (pyb_can_obj_all )[i ] = NULL ;
38
- }
39
- }
40
-
41
- void can_deinit_all (void ) {
42
- for (int i = 0 ; i < MP_ARRAY_SIZE (MP_STATE_PORT (pyb_can_obj_all )); i ++ ) {
43
- pyb_can_obj_t * can_obj = MP_STATE_PORT (pyb_can_obj_all )[i ];
44
- if (can_obj != NULL ) {
45
- can_deinit (can_obj );
46
- }
47
- }
48
- }
49
-
50
36
#if !MICROPY_HW_ENABLE_FDCAN
51
37
52
- bool can_init (pyb_can_obj_t * can_obj , uint32_t mode , uint32_t prescaler , uint32_t sjw , uint32_t bs1 , uint32_t bs2 , bool auto_restart ) {
53
- CAN_InitTypeDef * init = & can_obj -> can . Init ;
38
+ bool can_init (CAN_HandleTypeDef * can , int can_id , uint32_t mode , uint32_t prescaler , uint32_t sjw , uint32_t bs1 , uint32_t bs2 , bool auto_restart ) {
39
+ CAN_InitTypeDef * init = & can -> Init ;
54
40
init -> Mode = mode << 4 ; // shift-left so modes fit in a small-int
55
41
init -> Prescaler = prescaler ;
56
42
init -> SJW = ((sjw - 1 ) & 3 ) << 24 ;
@@ -67,7 +53,7 @@ bool can_init(pyb_can_obj_t *can_obj, uint32_t mode, uint32_t prescaler, uint32_
67
53
uint32_t sce_irq = 0 ;
68
54
const machine_pin_obj_t * pins [2 ];
69
55
70
- switch (can_obj -> can_id ) {
56
+ switch (can_id ) {
71
57
#if defined(MICROPY_HW_CAN1_TX )
72
58
case PYB_CAN_1 :
73
59
CANx = CAN1 ;
@@ -107,40 +93,34 @@ bool can_init(pyb_can_obj_t *can_obj, uint32_t mode, uint32_t prescaler, uint32_
107
93
uint32_t pin_mode = MP_HAL_PIN_MODE_ALT ;
108
94
uint32_t pin_pull = MP_HAL_PIN_PULL_UP ;
109
95
for (int i = 0 ; i < 2 ; i ++ ) {
110
- if (!mp_hal_pin_config_alt (pins [i ], pin_mode , pin_pull , AF_FN_CAN , can_obj -> can_id )) {
96
+ if (!mp_hal_pin_config_alt (pins [i ], pin_mode , pin_pull , AF_FN_CAN , can_id )) {
111
97
return false;
112
98
}
113
99
}
114
100
115
101
// init CANx
116
- can_obj -> can . Instance = CANx ;
117
- HAL_CAN_Init (& can_obj -> can );
102
+ can -> Instance = CANx ;
103
+ HAL_CAN_Init (can );
118
104
119
- can_obj -> is_enabled = true;
120
- can_obj -> num_error_warning = 0 ;
121
- can_obj -> num_error_passive = 0 ;
122
- can_obj -> num_bus_off = 0 ;
123
-
124
- __HAL_CAN_ENABLE_IT (& can_obj -> can , CAN_IT_ERR | CAN_IT_BOF | CAN_IT_EPV | CAN_IT_EWG );
105
+ __HAL_CAN_ENABLE_IT (can , CAN_IT_ERR | CAN_IT_BOF | CAN_IT_EPV | CAN_IT_EWG );
125
106
126
107
NVIC_SetPriority (sce_irq , IRQ_PRI_CAN );
127
108
HAL_NVIC_EnableIRQ (sce_irq );
128
109
129
110
return true;
130
111
}
131
112
132
- void can_deinit (pyb_can_obj_t * self ) {
133
- self -> is_enabled = false;
134
- HAL_CAN_DeInit (& self -> can );
135
- if (self -> can .Instance == CAN1 ) {
113
+ void can_deinit (CAN_HandleTypeDef * can ) {
114
+ HAL_CAN_DeInit (can );
115
+ if (can -> Instance == CAN1 ) {
136
116
HAL_NVIC_DisableIRQ (CAN1_RX0_IRQn );
137
117
HAL_NVIC_DisableIRQ (CAN1_RX1_IRQn );
138
118
HAL_NVIC_DisableIRQ (CAN1_SCE_IRQn );
139
119
__HAL_RCC_CAN1_FORCE_RESET ();
140
120
__HAL_RCC_CAN1_RELEASE_RESET ();
141
121
__HAL_RCC_CAN1_CLK_DISABLE ();
142
122
#if defined(CAN2 )
143
- } else if (self -> can . Instance == CAN2 ) {
123
+ } else if (can -> Instance == CAN2 ) {
144
124
HAL_NVIC_DisableIRQ (CAN2_RX0_IRQn );
145
125
HAL_NVIC_DisableIRQ (CAN2_RX1_IRQn );
146
126
HAL_NVIC_DisableIRQ (CAN2_SCE_IRQn );
@@ -149,7 +129,7 @@ void can_deinit(pyb_can_obj_t *self) {
149
129
__HAL_RCC_CAN2_CLK_DISABLE ();
150
130
#endif
151
131
#if defined(CAN3 )
152
- } else if (self -> can . Instance == CAN3 ) {
132
+ } else if (can -> Instance == CAN3 ) {
153
133
HAL_NVIC_DisableIRQ (CAN3_RX0_IRQn );
154
134
HAL_NVIC_DisableIRQ (CAN3_RX1_IRQn );
155
135
HAL_NVIC_DisableIRQ (CAN3_SCE_IRQn );
@@ -160,26 +140,38 @@ void can_deinit(pyb_can_obj_t *self) {
160
140
}
161
141
}
162
142
163
- void can_clearfilter (pyb_can_obj_t * self , uint32_t f , uint8_t bank ) {
143
+ void can_disable_rx_interrupts (CAN_HandleTypeDef * can , can_rx_fifo_t fifo ) {
144
+ __HAL_CAN_DISABLE_IT (can , ((fifo == CAN_RX_FIFO0 ) ?
145
+ (CAN_IT_FMP0 | CAN_IT_FF0 | CAN_IT_FOV0 ) :
146
+ (CAN_IT_FMP1 | CAN_IT_FF1 | CAN_IT_FOV1 )));
147
+ }
148
+
149
+ void can_enable_rx_interrupts (CAN_HandleTypeDef * can , can_rx_fifo_t fifo , bool enable_msg_received ) {
150
+ __HAL_CAN_ENABLE_IT (can , ((fifo == CAN_RX_FIFO0 ) ?
151
+ ((enable_msg_received ? CAN_IT_FMP0 : 0 ) | CAN_IT_FF0 | CAN_IT_FOV0 ) :
152
+ ((enable_msg_received ? CAN_IT_FMP1 : 0 ) | CAN_IT_FF1 | CAN_IT_FOV1 )));
153
+ }
154
+
155
+ void can_clearfilter (CAN_HandleTypeDef * can , uint32_t filter_num , uint8_t bank ) {
164
156
CAN_FilterConfTypeDef filter ;
165
157
166
158
filter .FilterIdHigh = 0 ;
167
159
filter .FilterIdLow = 0 ;
168
160
filter .FilterMaskIdHigh = 0 ;
169
161
filter .FilterMaskIdLow = 0 ;
170
162
filter .FilterFIFOAssignment = CAN_FILTER_FIFO0 ;
171
- filter .FilterNumber = f ;
163
+ filter .FilterNumber = filter_num ;
172
164
filter .FilterMode = CAN_FILTERMODE_IDMASK ;
173
165
filter .FilterScale = CAN_FILTERSCALE_16BIT ;
174
166
filter .FilterActivation = DISABLE ;
175
167
filter .BankNumber = bank ;
176
168
177
- HAL_CAN_ConfigFilter (& self -> can , & filter );
169
+ HAL_CAN_ConfigFilter (can , & filter );
178
170
}
179
171
180
- int can_receive (CAN_HandleTypeDef * can , int fifo , CanRxMsgTypeDef * msg , uint8_t * data , uint32_t timeout_ms ) {
172
+ int can_receive (CAN_HandleTypeDef * can , can_rx_fifo_t fifo , CanRxMsgTypeDef * msg , uint8_t * data , uint32_t timeout_ms ) {
181
173
volatile uint32_t * rfr ;
182
- if (fifo == CAN_FIFO0 ) {
174
+ if (fifo == CAN_RX_FIFO0 ) {
183
175
rfr = & can -> Instance -> RF0R ;
184
176
} else {
185
177
rfr = & can -> Instance -> RF1R ;
@@ -222,13 +214,16 @@ int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t
222
214
return 0 ; // success
223
215
}
224
216
225
- // We have our own version of CAN transmit so we can handle Timeout=0 correctly.
226
- HAL_StatusTypeDef CAN_Transmit (CAN_HandleTypeDef * hcan , uint32_t Timeout ) {
217
+ // Lightly modified version of HAL CAN_Transmit to handle Timeout=0 correctly
218
+ HAL_StatusTypeDef can_transmit (CAN_HandleTypeDef * hcan , CanTxMsgTypeDef * txmsg , uint8_t * data , uint32_t Timeout ) {
227
219
uint32_t transmitmailbox ;
228
220
uint32_t tickstart ;
229
221
uint32_t rqcpflag = 0 ;
230
222
uint32_t txokflag = 0 ;
231
223
224
+ hcan -> pTxMsg = txmsg ;
225
+ (void )data ; // Not needed here, caller has set it up as &tx_msg->Data
226
+
232
227
// Check the parameters
233
228
assert_param (IS_CAN_IDTYPE (hcan -> pTxMsg -> IDE ));
234
229
assert_param (IS_CAN_RTR (hcan -> pTxMsg -> RTR ));
@@ -312,119 +307,130 @@ HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout) {
312
307
}
313
308
}
314
309
315
- static void can_rx_irq_handler (uint can_id , uint fifo_id ) {
316
- mp_obj_t callback ;
317
- pyb_can_obj_t * self ;
318
- mp_obj_t irq_reason = MP_OBJ_NEW_SMALL_INT (0 );
319
- byte * state ;
320
-
321
- self = MP_STATE_PORT (pyb_can_obj_all )[can_id - 1 ];
322
-
323
- if (fifo_id == CAN_FIFO0 ) {
324
- callback = self -> rxcallback0 ;
325
- state = & self -> rx_state0 ;
310
+ // Workaround for the __HAL_CAN macros expecting a CAN_HandleTypeDef which we
311
+ // don't have in the ISR. Using this "fake" struct instead of CAN_HandleTypeDef
312
+ // so it's not possible to accidentally call an API that uses one of the other
313
+ // fields in the structure.
314
+ typedef struct {
315
+ CAN_TypeDef * Instance ;
316
+ } fake_handle_t ;
317
+
318
+ static void can_rx_irq_handler (uint can_id , CAN_TypeDef * instance , can_rx_fifo_t fifo ) {
319
+ uint32_t full_flag , full_int , overrun_flag , overrun_int , pending_int ;
320
+
321
+ const fake_handle_t handle = {
322
+ .Instance = instance ,
323
+ };
324
+
325
+ if (fifo == CAN_RX_FIFO0 ) {
326
+ full_flag = CAN_FLAG_FF0 ;
327
+ full_int = CAN_IT_FF0 ;
328
+ overrun_flag = CAN_FLAG_FOV0 ;
329
+ overrun_int = CAN_IT_FOV0 ;
330
+ pending_int = CAN_IT_FMP0 ;
326
331
} else {
327
- callback = self -> rxcallback1 ;
328
- state = & self -> rx_state1 ;
332
+ full_flag = CAN_FLAG_FF1 ;
333
+ full_int = CAN_IT_FF1 ;
334
+ overrun_flag = CAN_FLAG_FOV1 ;
335
+ overrun_int = CAN_IT_FOV1 ;
336
+ pending_int = CAN_IT_FMP1 ;
329
337
}
330
338
331
- switch (* state ) {
332
- case RX_STATE_FIFO_EMPTY :
333
- __HAL_CAN_DISABLE_IT (& self -> can , (fifo_id == CAN_FIFO0 ) ? CAN_IT_FMP0 : CAN_IT_FMP1 );
334
- irq_reason = MP_OBJ_NEW_SMALL_INT (0 );
335
- * state = RX_STATE_MESSAGE_PENDING ;
336
- break ;
337
- case RX_STATE_MESSAGE_PENDING :
338
- __HAL_CAN_DISABLE_IT (& self -> can , (fifo_id == CAN_FIFO0 ) ? CAN_IT_FF0 : CAN_IT_FF1 );
339
- __HAL_CAN_CLEAR_FLAG (& self -> can , (fifo_id == CAN_FIFO0 ) ? CAN_FLAG_FF0 : CAN_FLAG_FF1 );
340
- irq_reason = MP_OBJ_NEW_SMALL_INT (1 );
341
- * state = RX_STATE_FIFO_FULL ;
342
- break ;
343
- case RX_STATE_FIFO_FULL :
344
- __HAL_CAN_DISABLE_IT (& self -> can , (fifo_id == CAN_FIFO0 ) ? CAN_IT_FOV0 : CAN_IT_FOV1 );
345
- __HAL_CAN_CLEAR_FLAG (& self -> can , (fifo_id == CAN_FIFO0 ) ? CAN_FLAG_FOV0 : CAN_FLAG_FOV1 );
346
- irq_reason = MP_OBJ_NEW_SMALL_INT (2 );
347
- * state = RX_STATE_FIFO_OVERFLOW ;
348
- break ;
349
- case RX_STATE_FIFO_OVERFLOW :
350
- // This should never happen
351
- break ;
339
+ bool full = __HAL_CAN_GET_FLAG (& handle , full_flag );
340
+ bool overrun = __HAL_CAN_GET_FLAG (& handle , overrun_flag );
341
+
342
+ // Note: receive interrupt bits are disabled below, and re-enabled by the
343
+ // higher layer after calling can_receive()
344
+
345
+ if (full ) {
346
+ __HAL_CAN_DISABLE_IT (& handle , full_int );
347
+ __HAL_CAN_CLEAR_FLAG (& handle , full_flag );
348
+ if (!overrun ) {
349
+ can_irq_handler (can_id , CAN_INT_FIFO_FULL , fifo );
350
+ }
351
+ }
352
+ if (overrun ) {
353
+ __HAL_CAN_DISABLE_IT (& handle , overrun_int );
354
+ __HAL_CAN_CLEAR_FLAG (& handle , overrun_flag );
355
+ can_irq_handler (can_id , CAN_INT_FIFO_OVERFLOW , fifo );
352
356
}
353
357
354
- pyb_can_handle_callback (self , fifo_id , callback , irq_reason );
358
+ if (!(full || overrun )) {
359
+ // Process of elimination, if neither of the above
360
+ // FIFO status flags are set then message pending interrupt is what fired.
361
+ __HAL_CAN_DISABLE_IT (& handle , pending_int );
362
+ can_irq_handler (can_id , CAN_INT_MESSAGE_RECEIVED , fifo );
363
+ }
355
364
}
356
365
357
- static void can_sce_irq_handler (uint can_id ) {
358
- pyb_can_obj_t * self = MP_STATE_PORT (pyb_can_obj_all )[can_id - 1 ];
359
- if (self ) {
360
- self -> can .Instance -> MSR = CAN_MSR_ERRI ;
361
- uint32_t esr = self -> can .Instance -> ESR ;
362
- if (esr & CAN_ESR_BOFF ) {
363
- ++ self -> num_bus_off ;
364
- } else if (esr & CAN_ESR_EPVF ) {
365
- ++ self -> num_error_passive ;
366
- } else if (esr & CAN_ESR_EWGF ) {
367
- ++ self -> num_error_warning ;
368
- }
366
+ static void can_sce_irq_handler (uint can_id , CAN_TypeDef * instance ) {
367
+ instance -> MSR = CAN_MSR_ERRI ; // Write to clear ERRIE interrupt
368
+ uint32_t esr = instance -> ESR ;
369
+ if (esr & CAN_ESR_BOFF ) {
370
+ can_irq_handler (can_id , CAN_INT_ERR_BUS_OFF , 0 );
371
+ } else if (esr & CAN_ESR_EPVF ) {
372
+ can_irq_handler (can_id , CAN_INT_ERR_PASSIVE , 0 );
373
+ } else if (esr & CAN_ESR_EWGF ) {
374
+ can_irq_handler (can_id , CAN_INT_ERR_WARNING , 0 );
369
375
}
370
376
}
371
377
372
378
#if defined(MICROPY_HW_CAN1_TX )
373
379
void CAN1_RX0_IRQHandler (void ) {
374
380
IRQ_ENTER (CAN1_RX0_IRQn );
375
- can_rx_irq_handler (PYB_CAN_1 , CAN_FIFO0 );
381
+ can_rx_irq_handler (PYB_CAN_1 , CAN1 , CAN_RX_FIFO0 );
376
382
IRQ_EXIT (CAN1_RX0_IRQn );
377
383
}
378
384
379
385
void CAN1_RX1_IRQHandler (void ) {
380
386
IRQ_ENTER (CAN1_RX1_IRQn );
381
- can_rx_irq_handler (PYB_CAN_1 , CAN_FIFO1 );
387
+ can_rx_irq_handler (PYB_CAN_1 , CAN1 , CAN_RX_FIFO1 );
382
388
IRQ_EXIT (CAN1_RX1_IRQn );
383
389
}
384
390
385
391
void CAN1_SCE_IRQHandler (void ) {
386
392
IRQ_ENTER (CAN1_SCE_IRQn );
387
- can_sce_irq_handler (PYB_CAN_1 );
393
+ can_sce_irq_handler (PYB_CAN_1 , CAN1 );
388
394
IRQ_EXIT (CAN1_SCE_IRQn );
389
395
}
390
396
#endif
391
397
392
398
#if defined(MICROPY_HW_CAN2_TX )
393
399
void CAN2_RX0_IRQHandler (void ) {
394
400
IRQ_ENTER (CAN2_RX0_IRQn );
395
- can_rx_irq_handler (PYB_CAN_2 , CAN_FIFO0 );
401
+ can_rx_irq_handler (PYB_CAN_2 , CAN2 , CAN_RX_FIFO0 );
396
402
IRQ_EXIT (CAN2_RX0_IRQn );
397
403
}
398
404
399
405
void CAN2_RX1_IRQHandler (void ) {
400
406
IRQ_ENTER (CAN2_RX1_IRQn );
401
- can_rx_irq_handler (PYB_CAN_2 , CAN_FIFO1 );
407
+ can_rx_irq_handler (PYB_CAN_2 , CAN2 , CAN_RX_FIFO1 );
402
408
IRQ_EXIT (CAN2_RX1_IRQn );
403
409
}
404
410
405
411
void CAN2_SCE_IRQHandler (void ) {
406
412
IRQ_ENTER (CAN2_SCE_IRQn );
407
- can_sce_irq_handler (PYB_CAN_2 );
413
+ can_sce_irq_handler (PYB_CAN_2 , CAN2 );
408
414
IRQ_EXIT (CAN2_SCE_IRQn );
409
415
}
410
416
#endif
411
417
412
418
#if defined(MICROPY_HW_CAN3_TX )
413
419
void CAN3_RX0_IRQHandler (void ) {
414
420
IRQ_ENTER (CAN3_RX0_IRQn );
415
- can_rx_irq_handler (PYB_CAN_3 , CAN_FIFO0 );
421
+ can_rx_irq_handler (PYB_CAN_3 , CAN3 , CAN_RX_FIFO0 );
416
422
IRQ_EXIT (CAN3_RX0_IRQn );
417
423
}
418
424
419
425
void CAN3_RX1_IRQHandler (void ) {
420
426
IRQ_ENTER (CAN3_RX1_IRQn );
421
- can_rx_irq_handler (PYB_CAN_3 , CAN_FIFO1 );
427
+ can_rx_irq_handler (PYB_CAN_3 , CAN3 , CAN_RX_FIFO1 );
422
428
IRQ_EXIT (CAN3_RX1_IRQn );
423
429
}
424
430
425
431
void CAN3_SCE_IRQHandler (void ) {
426
432
IRQ_ENTER (CAN3_SCE_IRQn );
427
- can_sce_irq_handler (PYB_CAN_3 );
433
+ can_sce_irq_handler (PYB_CAN_3 , CAN3 );
428
434
IRQ_EXIT (CAN3_SCE_IRQn );
429
435
}
430
436
#endif
0 commit comments