@@ -35,6 +35,12 @@ LOG_MODULE_REGISTER(can_mcp2515, CONFIG_CAN_LOG_LEVEL);
3535#error You must either set a sampling-point or timings (phase-seg* and prop-seg)
3636#endif
3737
38+ /* Timeout for changing mode */
39+ #define MCP2515_MODE_CHANGE_TIMEOUT_USEC 1000
40+ #define MCP2515_MODE_CHANGE_RETRIES 100
41+ #define MCP2515_MODE_CHANGE_DELAY \
42+ K_USEC(MCP2515_MODE_CHANGE_TIMEOUT_USEC / MCP2515_MODE_CHANGE_RETRIES)
43+
3844static int mcp2515_cmd_soft_reset (const struct device * dev )
3945{
4046 const struct mcp2515_config * dev_cfg = dev -> config ;
@@ -271,22 +277,44 @@ static void mcp2515_convert_mcp2515frame_to_canframe(const uint8_t *source,
271277
272278const int mcp2515_set_mode_int (const struct device * dev , uint8_t mcp2515_mode )
273279{
280+ int retries = MCP2515_MODE_CHANGE_RETRIES ;
274281 uint8_t canstat ;
275282
276283 mcp2515_cmd_bit_modify (dev , MCP2515_ADDR_CANCTRL ,
277284 MCP2515_CANCTRL_MODE_MASK ,
278285 mcp2515_mode << MCP2515_CANCTRL_MODE_POS );
279286 mcp2515_cmd_read_reg (dev , MCP2515_ADDR_CANSTAT , & canstat , 1 );
280287
281- if (((canstat & MCP2515_CANSTAT_MODE_MASK ) >> MCP2515_CANSTAT_MODE_POS )
282- != mcp2515_mode ) {
283- LOG_ERR ("Failed to set MCP2515 operation mode" );
284- return - EIO ;
288+ while (((canstat & MCP2515_CANSTAT_MODE_MASK ) >> MCP2515_CANSTAT_MODE_POS )
289+ != mcp2515_mode ) {
290+ if (-- retries < 0 ) {
291+ LOG_ERR ("Timeout trying to set MCP2515 operation mode" );
292+ return - EIO ;
293+ }
294+
295+ k_sleep (MCP2515_MODE_CHANGE_DELAY );
296+ mcp2515_cmd_read_reg (dev , MCP2515_ADDR_CANSTAT , & canstat , 1 );
285297 }
286298
287299 return 0 ;
288300}
289301
302+ static void mcp2515_tx_done (const struct device * dev , uint8_t tx_idx , int status )
303+ {
304+ struct mcp2515_data * dev_data = dev -> data ;
305+ can_tx_callback_t callback = dev_data -> tx_cb [tx_idx ].cb ;
306+
307+ if (callback != NULL ) {
308+ callback (dev , status , dev_data -> tx_cb [tx_idx ].cb_arg );
309+ dev_data -> tx_cb [tx_idx ].cb = NULL ;
310+
311+ k_mutex_lock (& dev_data -> mutex , K_FOREVER );
312+ dev_data -> tx_busy_map &= ~BIT (tx_idx );
313+ k_mutex_unlock (& dev_data -> mutex );
314+ k_sem_give (& dev_data -> tx_sem );
315+ }
316+ }
317+
290318static int mcp2515_get_core_clock (const struct device * dev , uint32_t * rate )
291319{
292320 const struct mcp2515_config * dev_cfg = dev -> config ;
@@ -457,13 +485,26 @@ static int mcp2515_stop(const struct device *dev)
457485 const struct mcp2515_config * dev_cfg = dev -> config ;
458486 struct mcp2515_data * dev_data = dev -> data ;
459487 int ret ;
488+ int i ;
460489
461490 if (!dev_data -> started ) {
462491 return - EALREADY ;
463492 }
464493
465494 k_mutex_lock (& dev_data -> mutex , K_FOREVER );
466495
496+ /* Abort any pending transmissions before entering configuration mode */
497+ mcp2515_cmd_bit_modify (dev , MCP2515_ADDR_TXB0CTRL ,
498+ MCP2515_TXBNCTRL_TXREQ_MASK , 0 );
499+ #if MCP2515_TX_CNT == 2
500+ mcp2515_cmd_bit_modify (dev , MCP2515_ADDR_TXB1CTRL ,
501+ MCP2515_TXBNCTRL_TXREQ_MASK , 0 );
502+ #endif /* MCP2515_TX_CNT == 2 */
503+ #if MCP2515_TX_CNT == 3
504+ mcp2515_cmd_bit_modify (dev , MCP2515_ADDR_TXB2CTRL ,
505+ MCP2515_TXBNCTRL_TXREQ_MASK , 0 );
506+ #endif /* MCP2515_TX_CNT == 3 */
507+
467508 ret = mcp2515_set_mode_int (dev , MCP2515_MODE_CONFIGURATION );
468509 if (ret < 0 ) {
469510 LOG_ERR ("Failed to enter configuration mode [%d]" , ret );
@@ -475,6 +516,10 @@ static int mcp2515_stop(const struct device *dev)
475516
476517 k_mutex_unlock (& dev_data -> mutex );
477518
519+ for (i = 0 ; i < MCP2515_TX_CNT ; i ++ ) {
520+ mcp2515_tx_done (dev , i , - ENETDOWN );
521+ }
522+
478523 if (dev_cfg -> phy != NULL ) {
479524 ret = can_transceiver_disable (dev_cfg -> phy );
480525 if (ret != 0 ) {
@@ -678,19 +723,6 @@ static void mcp2515_rx(const struct device *dev, uint8_t rx_idx)
678723 mcp2515_rx_filter (dev , & frame );
679724}
680725
681- static void mcp2515_tx_done (const struct device * dev , uint8_t tx_idx )
682- {
683- struct mcp2515_data * dev_data = dev -> data ;
684-
685- dev_data -> tx_cb [tx_idx ].cb (dev , 0 , dev_data -> tx_cb [tx_idx ].cb_arg );
686- dev_data -> tx_cb [tx_idx ].cb = NULL ;
687-
688- k_mutex_lock (& dev_data -> mutex , K_FOREVER );
689- dev_data -> tx_busy_map &= ~BIT (tx_idx );
690- k_mutex_unlock (& dev_data -> mutex );
691- k_sem_give (& dev_data -> tx_sem );
692- }
693-
694726static int mcp2515_get_state (const struct device * dev , enum can_state * state ,
695727 struct can_bus_err_cnt * err_cnt )
696728{
@@ -805,15 +837,15 @@ static void mcp2515_handle_interrupts(const struct device *dev)
805837 }
806838
807839 if (canintf & MCP2515_CANINTF_TX0IF ) {
808- mcp2515_tx_done (dev , 0 );
840+ mcp2515_tx_done (dev , 0 , 0 );
809841 }
810842
811843 if (canintf & MCP2515_CANINTF_TX1IF ) {
812- mcp2515_tx_done (dev , 1 );
844+ mcp2515_tx_done (dev , 1 , 0 );
813845 }
814846
815847 if (canintf & MCP2515_CANINTF_TX2IF ) {
816- mcp2515_tx_done (dev , 2 );
848+ mcp2515_tx_done (dev , 2 , 0 );
817849 }
818850
819851 if (canintf & MCP2515_CANINTF_ERRIF ) {
0 commit comments