1717LOG_MODULE_REGISTER (can_mcan , CONFIG_CAN_LOG_LEVEL );
1818
1919#define CAN_INIT_TIMEOUT_MS 100
20+ #define TXBCF_TIMER_TIMEOUT K_MSEC(CONFIG_CAN_MCAN_TXBCF_POLL_INTERVAL_MS)
2021
2122int can_mcan_read_reg (const struct device * dev , uint16_t reg , uint32_t * val )
2223{
@@ -276,7 +277,7 @@ int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap)
276277{
277278 ARG_UNUSED (dev );
278279
279- * cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY ;
280+ * cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT ;
280281
281282 if (IS_ENABLED (CONFIG_CAN_MANUAL_RECOVERY_MODE )) {
282283 * cap |= CAN_MODE_MANUAL_RECOVERY ;
@@ -322,12 +323,78 @@ int can_mcan_start(const struct device *dev)
322323 return err ;
323324 }
324325
326+ uint32_t cccr ;
327+
328+ err = can_mcan_read_reg (dev , CAN_MCAN_CCCR , & cccr );
329+ if (err != 0 ) {
330+ return err ;
331+ }
332+
333+ if (cccr & CAN_MCAN_CCCR_DAR ) {
334+ /*
335+ * When DAR (Disable Automatic Retransmission), used for CAN_MODE_ONE_SHOT,
336+ * is enabled, and a transmission fails, a bug in the MCAN IP prevents the
337+ * TCF (Transmission Cancellation Finalized) interrupt from triggering,
338+ * despite the correct bit being set in the TXBCF register. It is thus
339+ * necessary to poll TXBCF register to detect when a transmission failed if
340+ * DAR is enabled.
341+ */
342+ k_timer_start (& data -> txbcf_timer , TXBCF_TIMER_TIMEOUT , TXBCF_TIMER_TIMEOUT );
343+ }
344+
325345 data -> common .started = true;
326346 pm_device_busy_set (dev );
327347
328348 return err ;
329349}
330350
351+ static int can_mcan_read_txbcf (const struct device * dev )
352+ {
353+ const struct can_mcan_config * config = dev -> config ;
354+ const struct can_mcan_callbacks * cbs = config -> callbacks ;
355+ struct can_mcan_data * data = dev -> data ;
356+ uint32_t txbcfs ;
357+ int err ;
358+ can_tx_callback_t tx_cb ;
359+ void * user_data ;
360+
361+ err = can_mcan_read_reg (dev , CAN_MCAN_TXBCF , & txbcfs );
362+ if (err != 0 ) {
363+ LOG_ERR ("failed to read tx cancellation finished (err %d)" , err );
364+ return err ;
365+ }
366+
367+ if (txbcfs == 0 ) {
368+ return 0 ;
369+ }
370+
371+ for (size_t tx_idx = 0 ; tx_idx < cbs -> num_tx ; tx_idx ++ ) {
372+ if ((txbcfs & BIT (tx_idx )) == 0 ) {
373+ continue ;
374+ }
375+
376+ if (cbs -> tx [tx_idx ].function == NULL ) {
377+ continue ;
378+ }
379+
380+ tx_cb = cbs -> tx [tx_idx ].function ;
381+ user_data = cbs -> tx [tx_idx ].user_data ;
382+ cbs -> tx [tx_idx ].function = NULL ;
383+ LOG_DBG ("tx buffer cancellation finished (idx %u)" , tx_idx );
384+ k_sem_give (& data -> tx_sem );
385+ tx_cb (dev , - EIO , user_data );
386+ }
387+
388+ return 0 ;
389+ }
390+
391+ static void can_mcan_txbcf_timer_handler (struct k_timer * timer_id )
392+ {
393+ const struct device * dev = k_timer_user_data_get (timer_id );
394+
395+ can_mcan_read_txbcf (dev );
396+ }
397+
331398static bool can_mcan_rx_filters_exist (const struct device * dev )
332399{
333400 const struct can_mcan_config * config = dev -> config ;
@@ -362,6 +429,8 @@ int can_mcan_stop(const struct device *dev)
362429 return - EALREADY ;
363430 }
364431
432+ k_timer_stop (& data -> txbcf_timer );
433+
365434 /* CAN transmissions are automatically stopped when entering init mode */
366435 err = can_mcan_enter_init_mode (dev , K_MSEC (CAN_INIT_TIMEOUT_MS ));
367436 if (err != 0 ) {
@@ -402,7 +471,7 @@ int can_mcan_stop(const struct device *dev)
402471
403472int can_mcan_set_mode (const struct device * dev , can_mode_t mode )
404473{
405- can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY ;
474+ can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT ;
406475 struct can_mcan_data * data = dev -> data ;
407476 uint32_t cccr ;
408477 uint32_t test ;
@@ -460,6 +529,13 @@ int can_mcan_set_mode(const struct device *dev, can_mode_t mode)
460529 }
461530#endif /* CONFIG_CAN_FD_MODE */
462531
532+ if ((mode & CAN_MODE_ONE_SHOT ) != 0 ) {
533+ /* Disable Automatic Retransmission */
534+ cccr |= CAN_MCAN_CCCR_DAR ;
535+ } else {
536+ cccr &= ~CAN_MCAN_CCCR_DAR ;
537+ }
538+
463539 err = can_mcan_write_reg (dev , CAN_MCAN_CCCR , cccr );
464540 if (err != 0 ) {
465541 goto unlock ;
@@ -1053,6 +1129,21 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
10531129 }
10541130 }
10551131
1132+ uint32_t cccr ;
1133+
1134+ err = can_mcan_read_reg (dev , CAN_MCAN_CCCR , & cccr );
1135+ if (err != 0 ) {
1136+ return err ;
1137+ }
1138+
1139+ if (cccr & CAN_MCAN_CCCR_DAR ) {
1140+ /*
1141+ * TXBCR is cleared after TXBAR is set. Stop timer to ensure
1142+ * TXBCR is not read before TXBAR has been set.
1143+ */
1144+ k_timer_stop (& data -> txbcf_timer );
1145+ }
1146+
10561147 __ASSERT_NO_MSG (put_idx < cbs -> num_tx );
10571148 cbs -> tx [put_idx ].function = callback ;
10581149 cbs -> tx [put_idx ].user_data = user_data ;
@@ -1063,10 +1154,18 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
10631154 goto err_unlock ;
10641155 }
10651156
1157+ if (cccr & CAN_MCAN_CCCR_DAR ) {
1158+ k_timer_start (& data -> txbcf_timer , TXBCF_TIMER_TIMEOUT , TXBCF_TIMER_TIMEOUT );
1159+ }
1160+
10661161 k_mutex_unlock (& data -> tx_mtx );
10671162 return 0 ;
10681163
10691164err_unlock :
1165+ if (cccr & CAN_MCAN_CCCR_DAR ) {
1166+ k_timer_start (& data -> txbcf_timer , TXBCF_TIMER_TIMEOUT , TXBCF_TIMER_TIMEOUT );
1167+ }
1168+
10701169 k_mutex_unlock (& data -> tx_mtx );
10711170 k_sem_give (& data -> tx_sem );
10721171
@@ -1424,6 +1523,8 @@ int can_mcan_init(const struct device *dev)
14241523 k_mutex_init (& data -> lock );
14251524 k_mutex_init (& data -> tx_mtx );
14261525 k_sem_init (& data -> tx_sem , cbs -> num_tx , cbs -> num_tx );
1526+ k_timer_init (& data -> txbcf_timer , can_mcan_txbcf_timer_handler , NULL );
1527+ k_timer_user_data_set (& data -> txbcf_timer , (void * )dev );
14271528
14281529 if (config -> common .phy != NULL && !device_is_ready (config -> common .phy )) {
14291530 LOG_ERR ("CAN transceiver not ready" );
@@ -1565,5 +1666,14 @@ int can_mcan_init(const struct device *dev)
15651666 return err ;
15661667 }
15671668
1669+ /*
1670+ * Interrupt on every TX buffer cancellation finished event.
1671+ */
1672+ reg = CAN_MCAN_TXBCIE_CFIE ;
1673+ err = can_mcan_write_reg (dev , CAN_MCAN_TXBCIE , reg );
1674+ if (err != 0 ) {
1675+ return err ;
1676+ }
1677+
15681678 return can_mcan_clear_mram (dev , 0 , config -> mram_size );
15691679}
0 commit comments