2828#include "py/mperrno.h"
2929#include "py/mphal.h"
3030#include "can.h"
31+ #include "pyb_can.h"
3132#include "irq.h"
3233
3334#if MICROPY_HW_ENABLE_CAN
3435
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-
5036#if !MICROPY_HW_ENABLE_FDCAN
5137
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 ;
5440 init -> Mode = mode << 4 ; // shift-left so modes fit in a small-int
5541 init -> Prescaler = prescaler ;
5642 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_
6753 uint32_t sce_irq = 0 ;
6854 const machine_pin_obj_t * pins [2 ];
6955
70- switch (can_obj -> can_id ) {
56+ switch (can_id ) {
7157 #if defined(MICROPY_HW_CAN1_TX )
7258 case PYB_CAN_1 :
7359 CANx = CAN1 ;
@@ -107,40 +93,34 @@ bool can_init(pyb_can_obj_t *can_obj, uint32_t mode, uint32_t prescaler, uint32_
10793 uint32_t pin_mode = MP_HAL_PIN_MODE_ALT ;
10894 uint32_t pin_pull = MP_HAL_PIN_PULL_UP ;
10995 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 )) {
11197 return false;
11298 }
11399 }
114100
115101 // init CANx
116- can_obj -> can . Instance = CANx ;
117- HAL_CAN_Init (& can_obj -> can );
102+ can -> Instance = CANx ;
103+ HAL_CAN_Init (can );
118104
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 );
125106
126107 NVIC_SetPriority (sce_irq , IRQ_PRI_CAN );
127108 HAL_NVIC_EnableIRQ (sce_irq );
128109
129110 return true;
130111}
131112
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 ) {
136116 HAL_NVIC_DisableIRQ (CAN1_RX0_IRQn );
137117 HAL_NVIC_DisableIRQ (CAN1_RX1_IRQn );
138118 HAL_NVIC_DisableIRQ (CAN1_SCE_IRQn );
139119 __HAL_RCC_CAN1_FORCE_RESET ();
140120 __HAL_RCC_CAN1_RELEASE_RESET ();
141121 __HAL_RCC_CAN1_CLK_DISABLE ();
142122 #if defined(CAN2 )
143- } else if (self -> can . Instance == CAN2 ) {
123+ } else if (can -> Instance == CAN2 ) {
144124 HAL_NVIC_DisableIRQ (CAN2_RX0_IRQn );
145125 HAL_NVIC_DisableIRQ (CAN2_RX1_IRQn );
146126 HAL_NVIC_DisableIRQ (CAN2_SCE_IRQn );
@@ -149,7 +129,7 @@ void can_deinit(pyb_can_obj_t *self) {
149129 __HAL_RCC_CAN2_CLK_DISABLE ();
150130 #endif
151131 #if defined(CAN3 )
152- } else if (self -> can . Instance == CAN3 ) {
132+ } else if (can -> Instance == CAN3 ) {
153133 HAL_NVIC_DisableIRQ (CAN3_RX0_IRQn );
154134 HAL_NVIC_DisableIRQ (CAN3_RX1_IRQn );
155135 HAL_NVIC_DisableIRQ (CAN3_SCE_IRQn );
@@ -160,26 +140,38 @@ void can_deinit(pyb_can_obj_t *self) {
160140 }
161141}
162142
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 ) {
164156 CAN_FilterConfTypeDef filter ;
165157
166158 filter .FilterIdHigh = 0 ;
167159 filter .FilterIdLow = 0 ;
168160 filter .FilterMaskIdHigh = 0 ;
169161 filter .FilterMaskIdLow = 0 ;
170162 filter .FilterFIFOAssignment = CAN_FILTER_FIFO0 ;
171- filter .FilterNumber = f ;
163+ filter .FilterNumber = filter_num ;
172164 filter .FilterMode = CAN_FILTERMODE_IDMASK ;
173165 filter .FilterScale = CAN_FILTERSCALE_16BIT ;
174166 filter .FilterActivation = DISABLE ;
175167 filter .BankNumber = bank ;
176168
177- HAL_CAN_ConfigFilter (& self -> can , & filter );
169+ HAL_CAN_ConfigFilter (can , & filter );
178170}
179171
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 ) {
181173 volatile uint32_t * rfr ;
182- if (fifo == CAN_FIFO0 ) {
174+ if (fifo == CAN_RX_FIFO0 ) {
183175 rfr = & can -> Instance -> RF0R ;
184176 } else {
185177 rfr = & can -> Instance -> RF1R ;
@@ -222,13 +214,16 @@ int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t
222214 return 0 ; // success
223215}
224216
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 ) {
227219 uint32_t transmitmailbox ;
228220 uint32_t tickstart ;
229221 uint32_t rqcpflag = 0 ;
230222 uint32_t txokflag = 0 ;
231223
224+ hcan -> pTxMsg = txmsg ;
225+ (void )data ; // Not needed here, caller has set it up as &tx_msg->Data
226+
232227 // Check the parameters
233228 assert_param (IS_CAN_IDTYPE (hcan -> pTxMsg -> IDE ));
234229 assert_param (IS_CAN_RTR (hcan -> pTxMsg -> RTR ));
@@ -312,119 +307,130 @@ HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout) {
312307 }
313308}
314309
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 ;
326331 } 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 ;
329337 }
330338
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 );
352356 }
353357
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+ }
355364}
356365
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 );
369375 }
370376}
371377
372378#if defined(MICROPY_HW_CAN1_TX )
373379void CAN1_RX0_IRQHandler (void ) {
374380 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 );
376382 IRQ_EXIT (CAN1_RX0_IRQn );
377383}
378384
379385void CAN1_RX1_IRQHandler (void ) {
380386 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 );
382388 IRQ_EXIT (CAN1_RX1_IRQn );
383389}
384390
385391void CAN1_SCE_IRQHandler (void ) {
386392 IRQ_ENTER (CAN1_SCE_IRQn );
387- can_sce_irq_handler (PYB_CAN_1 );
393+ can_sce_irq_handler (PYB_CAN_1 , CAN1 );
388394 IRQ_EXIT (CAN1_SCE_IRQn );
389395}
390396#endif
391397
392398#if defined(MICROPY_HW_CAN2_TX )
393399void CAN2_RX0_IRQHandler (void ) {
394400 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 );
396402 IRQ_EXIT (CAN2_RX0_IRQn );
397403}
398404
399405void CAN2_RX1_IRQHandler (void ) {
400406 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 );
402408 IRQ_EXIT (CAN2_RX1_IRQn );
403409}
404410
405411void CAN2_SCE_IRQHandler (void ) {
406412 IRQ_ENTER (CAN2_SCE_IRQn );
407- can_sce_irq_handler (PYB_CAN_2 );
413+ can_sce_irq_handler (PYB_CAN_2 , CAN2 );
408414 IRQ_EXIT (CAN2_SCE_IRQn );
409415}
410416#endif
411417
412418#if defined(MICROPY_HW_CAN3_TX )
413419void CAN3_RX0_IRQHandler (void ) {
414420 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 );
416422 IRQ_EXIT (CAN3_RX0_IRQn );
417423}
418424
419425void CAN3_RX1_IRQHandler (void ) {
420426 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 );
422428 IRQ_EXIT (CAN3_RX1_IRQn );
423429}
424430
425431void CAN3_SCE_IRQHandler (void ) {
426432 IRQ_ENTER (CAN3_SCE_IRQn );
427- can_sce_irq_handler (PYB_CAN_3 );
433+ can_sce_irq_handler (PYB_CAN_3 , CAN3 );
428434 IRQ_EXIT (CAN3_SCE_IRQn );
429435}
430436#endif
0 commit comments