88 * 2015-05-14 [email protected] first version 99 * 2015-07-06 Bernard code cleanup and remove RT_CAN_USING_LED;
1010 * 2025-09-20 wdfk_prog Implemented non-blocking, ISR-safe send logic unified under rt_device_write.
11+ * 2025-12-17 RCSN Support global send mode control, enable TX completion callback via RT_CAN_CMD_SET_SENDMODE
1112 */
1213
1314#include <rthw.h>
@@ -652,7 +653,7 @@ static rt_ssize_t rt_can_write(struct rt_device *dev,
652653 * 1. Called from within an interrupt context.
653654 * 2. Called from a thread, but the user explicitly set the nonblocking flag on the first message.
654655 */
655- if (rt_interrupt_get_nest () > 0 || pmsg -> nonblocking )
656+ if (rt_interrupt_get_nest () > 0 || pmsg -> nonblocking || can -> send_mode_nonblocking )
656657 {
657658 return _can_nonblocking_tx (can , pmsg , size );
658659 }
@@ -1097,12 +1098,30 @@ void rt_hw_can_isr(struct rt_can_device *can, int event)
10971098 {
10981099 struct rt_can_tx_fifo * tx_fifo ;
10991100 rt_uint32_t no ;
1101+ struct rt_device * device ;
11001102 no = event >> 8 ;
11011103 tx_fifo = (struct rt_can_tx_fifo * ) can -> can_tx ;
11021104 RT_ASSERT (tx_fifo != RT_NULL );
11031105
1104- if (can -> status .sndchange & (1 <<no ))
1106+ /**
1107+ * @brief Handle blocking (synchronous) send completion notification.
1108+ *
1109+ * This section is ONLY executed for blocking (synchronous) send operations.
1110+ * Specifically:
1111+ * 1. The sndchange flag is set ONLY by blocking send functions (_can_int_tx, _can_int_tx_priv)
1112+ * to indicate that there is an ongoing blocking operation waiting for this mailbox.
1113+ * 2. For non-blocking sends, the sndchange flag is NOT set, so this condition is skipped.
1114+ * 3. When a blocking send completes (via interrupt), we:
1115+ * - Store the result (OK or ERR) in tx_fifo->buffer[no].result
1116+ * - Wake up the blocked thread using rt_completion_done()
1117+ * - The blocked thread then checks the result and resumes execution
1118+ *
1119+ * Non-blocking sends are handled separately by the tx_complete callback
1120+ * (see the send_mode_nonblocking section below).
1121+ */
1122+ if (can -> status .sndchange & (1 <<no ))
11051123 {
1124+ /* Update the transmission result based on the event type */
11061125 if ((event & 0xff ) == RT_CAN_EVENT_TX_DONE )
11071126 {
11081127 tx_fifo -> buffer [no ].result = RT_CAN_SND_RESULT_OK ;
@@ -1111,11 +1130,19 @@ void rt_hw_can_isr(struct rt_can_device *can, int event)
11111130 {
11121131 tx_fifo -> buffer [no ].result = RT_CAN_SND_RESULT_ERR ;
11131132 }
1133+
1134+ /* Wake up the blocked thread waiting on this mailbox's completion */
11141135 rt_completion_done (& (tx_fifo -> buffer [no ].completion ));
1115- }
1116-
1117- if (can -> ops -> sendmsg_nonblocking != RT_NULL )
1136+ }
1137+ else if (can -> ops -> sendmsg_nonblocking != RT_NULL )
11181138 {
1139+ if (can -> send_mode_nonblocking == 1 ) {
1140+ device = & (can -> parent );
1141+ if (device -> tx_complete != RT_NULL )
1142+ {
1143+ device -> tx_complete (device , RT_NULL );
1144+ }
1145+ }
11191146 while (RT_TRUE )
11201147 {
11211148 struct rt_can_msg msg_to_send ;
0 commit comments