Browse Source

[bsp][stm32/fdcan]修复CAN-FD发送/接收问题并新增5Mbps ISO CAN-FD数据相位速率支持

takuya60 9 hours ago
parent
commit
25295501c0
1 changed files with 41 additions and 5 deletions
  1. 41 5
      bsp/stm32/libraries/HAL_Drivers/drivers/drv_fdcan.c

+ 41 - 5
bsp/stm32/libraries/HAL_Drivers/drivers/drv_fdcan.c

@@ -8,6 +8,7 @@
  * 2020-02-24     heyuan       the first version
  * 2020-02-24     heyuan       the first version
  * 2020-08-17     malongwei    Fix something
  * 2020-08-17     malongwei    Fix something
  * 2025-10-27     pandafeng    Fix some bugs
  * 2025-10-27     pandafeng    Fix some bugs
+ * 2026-03-16     sayaZhao     Fix some bugs
  */
  */
 
 
 #include "drv_fdcan.h"
 #include "drv_fdcan.h"
@@ -54,12 +55,30 @@ static const stm32_fdcan_timing_t st_FDCAN_ArbTiming[] =
 static const stm32_fdcan_timing_t st_FDCAN_DataTiming[] =
 static const stm32_fdcan_timing_t st_FDCAN_DataTiming[] =
 {
 {
     {CAN1MBaud * 8, {1, 3, 1, 1, 0}},   /* 8Mbps */
     {CAN1MBaud * 8, {1, 3, 1, 1, 0}},   /* 8Mbps */
+    {CAN1MBaud * 5,  {1, 5, 2, 1, 0}},  /* 5Mbps */
     {CAN500kBaud *8,  {1, 7, 2, 1, 0}},   /* 4Mbps */
     {CAN500kBaud *8,  {1, 7, 2, 1, 0}},   /* 4Mbps */
     {CAN250kBaud * 8,  {4, 3, 1, 1, 0}},  /* 2Mbps */
     {CAN250kBaud * 8,  {4, 3, 1, 1, 0}},  /* 2Mbps */
     {CAN125kBaud *8,  {1, 31, 8, 1, 0}},  /* 1Mkbps */
     {CAN125kBaud *8,  {1, 31, 8, 1, 0}},  /* 1Mkbps */
     {CAN100kBaud*8,  {2, 19, 5, 1, 0}},  /* 800kbps */
     {CAN100kBaud*8,  {2, 19, 5, 1, 0}},  /* 800kbps */
     {CAN50kBaud *8,   {5, 15, 4, 1, 0}},   /* 400kbps */
     {CAN50kBaud *8,   {5, 15, 4, 1, 0}},   /* 400kbps */
 };
 };
+
+/**
+ * @brief  Convert CAN-FD DLC (Data Length Code) back to actual frame length
+ * @param  dlc  DLC code (0~15)
+ * @return      Actual length in bytes (0~64)
+ */
+static uint8_t dlc_to_length(uint32_t dlc)
+{
+    const uint8_t dlc_to_len_table[16] = {
+        0,  1,  2,  3,  4,  5,  6,  7,
+        8, 12, 16, 20, 24, 32, 48, 64
+    };
+
+    if (dlc > 15) return 8;
+    return dlc_to_len_table[dlc];
+}
+
 /**
 /**
  * @brief  Convert CAN-FD frame length to DLC (Data Length Code)
  * @brief  Convert CAN-FD frame length to DLC (Data Length Code)
  *
  *
@@ -208,8 +227,18 @@ static rt_err_t _inline_can_config(struct rt_can_device *can, struct can_configu
     {
     {
         return -RT_ERROR;
         return -RT_ERROR;
     }
     }
+/* Transceiver Delay Compensation */
+#ifdef RT_CAN_USING_CANFD
+    if (cfg->enable_canfd)
+    {
+        HAL_FDCAN_ConfigTxDelayCompensation(&pdrv_can->fdcanHandle, 0x0C, 0x00);
+        HAL_FDCAN_EnableTxDelayCompensation(&pdrv_can->fdcanHandle);
+    }
+#endif
     /* default filter config */
     /* default filter config */
     HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig);
     HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig);
+    /* FIFO RX INT */
+    HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
     /*init fdcan tx header*/
     /*init fdcan tx header*/
     pdrv_can->TxHeader.Identifier = 0x000000;
     pdrv_can->TxHeader.Identifier = 0x000000;
     pdrv_can->TxHeader.IdType = FDCAN_EXTENDED_ID;
     pdrv_can->TxHeader.IdType = FDCAN_EXTENDED_ID;
@@ -352,7 +381,7 @@ static rt_err_t _inline_can_control(struct rt_can_device *can, int cmd, void *ar
             argval = (rt_uint32_t) arg;
             argval = (rt_uint32_t) arg;
             uint32_t arb_idx = _inline_get_ArbBaudIndex(argval);
             uint32_t arb_idx = _inline_get_ArbBaudIndex(argval);
             if (arb_idx == (uint32_t) -1) {
             if (arb_idx == (uint32_t) -1) {
-                return -RT_ERROR; 
+                return -RT_ERROR;
             }
             }
             if (argval != pdrv_can->device.config.baud_rate) {
             if (argval != pdrv_can->device.config.baud_rate) {
                 pdrv_can->device.config.baud_rate = argval;
                 pdrv_can->device.config.baud_rate = argval;
@@ -452,6 +481,12 @@ static int _inline_can_sendmsg(struct rt_can_device *can, const void *buf, rt_ui
         pdrv_can->TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
         pdrv_can->TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
     }
     }
 
 
+    if (pmsg->brs == 1) {
+        pdrv_can->TxHeader.BitRateSwitch = FDCAN_BRS_ON;
+    } else {
+        pdrv_can->TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
+    }
+
     if(HAL_FDCAN_AddMessageToTxBuffer(&pdrv_can->fdcanHandle, &pdrv_can->TxHeader, pmsg->data, FDCAN_TX_BUFFER0 + box_num) != HAL_OK)
     if(HAL_FDCAN_AddMessageToTxBuffer(&pdrv_can->fdcanHandle, &pdrv_can->TxHeader, pmsg->data, FDCAN_TX_BUFFER0 + box_num) != HAL_OK)
     {
     {
         return -RT_ERROR;
         return -RT_ERROR;
@@ -499,13 +534,14 @@ static int _inline_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t
         }
         }
         pmsg->id = pdrv_can->RxHeader.Identifier;
         pmsg->id = pdrv_can->RxHeader.Identifier;
 
 
-        pmsg->len = pdrv_can->RxHeader.DataLength;
-        pmsg->hdr_index = pdrv_can->RxHeader.FilterIndex;
+        uint32_t actual_dlc = pdrv_can->RxHeader.DataLength;
+        pmsg->len = dlc_to_length(actual_dlc);
 
 
-        #ifdef RT_CAN_USING_CANFD
+        pmsg->hdr_index = pdrv_can->RxHeader.FilterIndex;
+#ifdef RT_CAN_USING_CANFD
         pmsg->fd_frame =  (pdrv_can->RxHeader.FDFormat >> 16) && 0x20;
         pmsg->fd_frame =  (pdrv_can->RxHeader.FDFormat >> 16) && 0x20;
         pmsg->brs = (pdrv_can->RxHeader.BitRateSwitch >> 16) && 0x10;
         pmsg->brs = (pdrv_can->RxHeader.BitRateSwitch >> 16) && 0x10;
-        #endif
+#endif
 
 
         return sizeof(struct rt_can_msg);
         return sizeof(struct rt_can_msg);
     }
     }