Skip to content

Commit b2d442a

Browse files
committed
[update] components: drivers: can: add RT_CAN_CMD_SET_SENDMODE for non-blocking TX control
- Add global send mode control via RT_CAN_CMD_SET_SENDMODE command. TX completion callback is only triggered when non-blocking mode is explicitly enabled through this command. Signed-off-by: Runcheng Lu <[email protected]>
1 parent df990e9 commit b2d442a

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

components/drivers/can/dev_can.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
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;

components/drivers/include/drivers/dev_can.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* 2015-07-06 Bernard remove RT_CAN_USING_LED.
1010
* 2022-05-08 hpmicro add CANFD support, fixed typos
1111
* 2025-09-20 wdfk_prog Added non-blocking send mechanism APIs and data structures.
12+
* 2025-12-17 RCSN Added send_mode_nonblocking and RT_CAN_CMD_SET_SENDMODE for TX completion callback control
1213
*/
1314

1415
#ifndef __DEV_CAN_H_
@@ -417,6 +418,7 @@ struct rt_can_ops;
417418
#define RT_CAN_CMD_SET_BAUD_FD 0x1B
418419
#define RT_CAN_CMD_SET_BITTIMING 0x1C
419420
#define RT_CAN_CMD_START 0x1D
421+
#define RT_CAN_CMD_SET_SENDMODE 0x1E
420422

421423
#define RT_DEVICE_CAN_INT_ERR 0x1000
422424

@@ -563,6 +565,7 @@ struct rt_can_device
563565
#else
564566
rt_uint8_t nb_tx_rb_pool[RT_CAN_NB_TX_FIFO_SIZE]; /**< The statically allocated pool for the non-blocking TX ring buffer. */
565567
#endif /* RT_CAN_MALLOC_NB_TX_BUFFER */
568+
rt_uint8_t send_mode_nonblocking; /**< Global send mode: 0=Blocking (default), 1=Non-blocking. */
566569
};
567570
typedef struct rt_can_device *rt_can_t;
568571

0 commit comments

Comments
 (0)