diff options
| author | wdfk-prog <[email protected]> | 2025-11-05 15:55:14 +0800 |
|---|---|---|
| committer | R b b666 <[email protected]> | 2025-11-08 11:52:25 +0800 |
| commit | 44cf90a4ef25b4ae09151a9230bc14cd9f061c38 (patch) | |
| tree | 52b43a438af72e27637a8c06d1b0e331c69239f2 /components | |
| parent | 2c9257831ef1a3ccf085380c048aff12d024d285 (diff) | |
fix(can): Resolve potential race condition in message transmission
Setting the send status flag `sndchange` after calling the can->ops->sendmsg function
could lead to a race condition if a transmission timeout occurs, resulting in incorrect state handling.
This patch moves the operation of setting the `sndchange` flag to before the call to can->ops->sendmsg.
This ensures that the mailbox's status is correctly marked as "sending" before the hardware begins transmission,
making the driver's state management more robust and reliable, especially in handling exceptions like timeouts.
Additionally, new macros for CAN filter modes have been added in dev_can.h.
Diffstat (limited to 'components')
| -rw-r--r-- | components/drivers/can/dev_can.c | 5 | ||||
| -rw-r--r-- | components/drivers/include/drivers/dev_can.h | 3 |
2 files changed, 6 insertions, 2 deletions
diff --git a/components/drivers/can/dev_can.c b/components/drivers/can/dev_can.c index 73aee2f094..e0cf0db9b2 100644 --- a/components/drivers/can/dev_can.c +++ b/components/drivers/can/dev_can.c @@ -186,6 +186,7 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da no = ((rt_ubase_t)tx_tosnd - (rt_ubase_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list); tx_tosnd->result = RT_CAN_SND_RESULT_WAIT; rt_completion_init(&tx_tosnd->completion); + can->status.sndchange |= 1<<no; if (can->ops->sendmsg(can, data, no) != RT_EOK) { /* send failed. */ @@ -196,7 +197,6 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da goto err_ret; } - can->status.sndchange |= 1<<no; if (rt_completion_wait(&(tx_tosnd->completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK) { level = rt_hw_local_irq_disable(); @@ -286,11 +286,12 @@ rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_ms tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_WAIT; rt_hw_local_irq_enable(level); + can->status.sndchange |= 1<<no; if (can->ops->sendmsg(can, data, no) != RT_EOK) { continue; } - can->status.sndchange |= 1<<no; + if (rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK) { can->status.sndchange &= ~ (1<<no); diff --git a/components/drivers/include/drivers/dev_can.h b/components/drivers/include/drivers/dev_can.h index ef91302742..9bf0c162cb 100644 --- a/components/drivers/include/drivers/dev_can.h +++ b/components/drivers/include/drivers/dev_can.h @@ -68,6 +68,9 @@ enum CANBAUD #define RT_CAN_MODE_PRIV 0x01 #define RT_CAN_MODE_NOPRIV 0x00 +#define RT_CAN_MODE_MASK 0x00 +#define RT_CAN_MODE_LIST 0x01 + /** * @defgroup group_drivers_can CAN Driver * @brief CAN driver api |
