Просмотр исходного кода

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.
wdfk-prog 2 месяцев назад
Родитель
Сommit
44cf90a4ef
2 измененных файлов с 6 добавлено и 2 удалено
  1. 3 2
      components/drivers/can/dev_can.c
  2. 3 0
      components/drivers/include/drivers/dev_can.h

+ 3 - 2
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);

+ 3 - 0
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