summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorwdfk-prog <[email protected]>2025-11-05 15:55:14 +0800
committerR b b666 <[email protected]>2025-11-08 11:52:25 +0800
commit44cf90a4ef25b4ae09151a9230bc14cd9f061c38 (patch)
tree52b43a438af72e27637a8c06d1b0e331c69239f2 /components
parent2c9257831ef1a3ccf085380c048aff12d024d285 (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.c5
-rw-r--r--components/drivers/include/drivers/dev_can.h3
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