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

[bsp/stm32h7]: Add STM32H7 fdcan driver. #10767

PandaFeng 2 месяцев назад
Родитель
Сommit
6d4e2aa2fe

+ 4 - 1
bsp/stm32/libraries/HAL_Drivers/drivers/SConscript

@@ -50,7 +50,10 @@ if GetDepend(['RT_USING_DAC']):
     src += ['drv_dac.c']
 
 if GetDepend(['RT_USING_CAN']):
-    src += ['drv_can.c']
+    if GetDepend(['SOC_SERIES_STM32H7']):
+        src += ['drv_fdcan.c']
+    else:
+        src += ['drv_can.c']
 
 if GetDepend(['RT_USING_PM']):
     src += ['drv_pm.c']

+ 703 - 0
bsp/stm32/libraries/HAL_Drivers/drivers/drv_fdcan.c

@@ -0,0 +1,703 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-02-24     heyuan       the first version
+ * 2020-08-17     malongwei    Fix something
+ * 2025-10-27     pandafeng    Fix some bugs
+ */
+
+#include "drv_fdcan.h"
+
+#if defined(RT_USING_CAN) && defined(RT_CAN_USING_CANFD)
+
+#if defined(BSP_USING_FDCAN1) || defined(BSP_USING_FDCAN2)
+
+
+//#define DRV_DEBUG
+#define LOG_TAG    "drv_fdcan"
+#include <drv_log.h>
+
+#ifdef BSP_USING_FDCAN1
+static stm32_fdcan_t st_DrvCan1=
+{
+    .name = "fdcan1",
+    .fdcanHandle.Instance = FDCAN1,
+};
+#endif
+
+#ifdef BSP_USING_FDCAN2
+static stm32_fdcan_t st_DrvCan2=
+{
+    .name = "fdcan2",
+    .fdcanHandle.Instance = FDCAN2,
+};
+#endif
+
+/* 40MHz CAN clock */
+static const stm32_fdcan_timing_t st_FDCAN_ArbTiming[] =
+{
+    {CAN1MBaud, {1, 29, 10, 8, 0}},   /* 1Mbps */
+    {CAN800kBaud,  {1, 37, 12, 8, 0}},   /* 800kbps */
+    {CAN500kBaud,  {1, 59, 20, 8, 0}},   /* 500kbps */
+    {CAN250kBaud,  {2, 63, 16, 8, 0}},  /* 250kbps */
+    {CAN125kBaud,  {5, 55, 8, 8, 0}},  /* 125kbps */
+    {CAN100kBaud,  {8, 41, 8, 8, 0}},  /* 100kbps */
+    {CAN50kBaud,   {16, 41, 8, 8, 0}},   /* 50kbps */
+    {CAN20kBaud,   {40,41,8,8,0}},     /* 20kbps */
+    {CAN10kBaud,   {100,31,8,8,0}}      /* 10kbps */
+};
+/* 40MHz CAN clock */
+static const stm32_fdcan_timing_t st_FDCAN_DataTiming[] =
+{
+    {CAN1MBaud * 8, {1, 3, 1, 1, 0}},   /* 8Mbps */
+    {CAN500kBaud *8,  {1, 7, 2, 1, 0}},   /* 4Mbps */
+    {CAN250kBaud * 8,  {4, 3, 1, 1, 0}},  /* 2Mbps */
+    {CAN125kBaud *8,  {1, 31, 8, 1, 0}},  /* 1Mkbps */
+    {CAN100kBaud*8,  {2, 19, 5, 1, 0}},  /* 800kbps */
+    {CAN50kBaud *8,   {5, 15, 4, 1, 0}},   /* 400kbps */
+};
+/**
+ * @brief  Convert CAN-FD frame length to DLC (Data Length Code)
+ *
+ * CAN-FD DLC mapping (length → DLC):
+ *  Length 0~8   -> DLC 0~8
+ *  Length 9~12  -> DLC 9
+ *  Length 13~16 -> DLC 10
+ *  Length 17~20 -> DLC 11
+ *  Length 21~24 -> DLC 12
+ *  Length 25~32 -> DLC 13
+ *  Length 33~48 -> DLC 14
+ *  Length 49~64 -> DLC 15
+ *
+ * @param len  Frame length in bytes (0~64)
+ * @return     DLC code (0~15)
+ */
+uint8_t length_to_dlc(uint8_t len) {
+    return (len <= 8) ? len :
+           (len <= 12) ? 9 :
+           (len <= 16) ? 10 :
+           (len <= 20) ? 11 :
+           (len <= 24) ? 12 :
+           (len <= 32) ? 13 :
+           (len <= 48) ? 14 : 15;
+}
+
+/**
+ * @brief  获取 FDCAN 仲裁段波特率配置索引
+ */
+static uint32_t _inline_get_ArbBaudIndex(uint32_t baud_rate)
+{
+    uint32_t len = sizeof(st_FDCAN_ArbTiming) / sizeof(st_FDCAN_ArbTiming[0]);
+
+    for (uint32_t i = 0; i < len; i++)
+    {
+        if (st_FDCAN_ArbTiming[i].u32Baudrate == baud_rate)
+            return i;
+    }
+    return -1;
+}
+
+/**
+ * @brief  Get the index of the FDCAN data segment bitrate configuration.
+ *
+ * @param  baud_rate  The desired data phase baud rate (in bps).
+ * @retval uint32_t   Index of the matching data segment configuration.
+ *                     Returns -1 if no matching configuration is found.
+ */
+static uint32_t _inline_get_DataBaudIndex(uint32_t baud_rate)
+{
+    uint32_t len = sizeof(st_FDCAN_DataTiming) / sizeof(st_FDCAN_DataTiming[0]);
+
+    for (uint32_t i = 0; i < len; i++)
+    {
+        if (st_FDCAN_DataTiming[i].u32Baudrate == baud_rate)
+            return i;
+    }
+    return -1;
+}
+
+static rt_err_t _inline_can_config(struct rt_can_device *can, struct can_configure *cfg)
+{
+    stm32_fdcan_t *pdrv_can;
+    rt_uint32_t tmp_u32Index;
+
+    RT_ASSERT(can);
+    RT_ASSERT(cfg);
+
+    pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
+
+    RT_ASSERT(pdrv_can);
+
+    pdrv_can->fdcanHandle.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
+    pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
+    pdrv_can->fdcanHandle.Init.AutoRetransmission = ENABLE;
+
+    pdrv_can->fdcanHandle.Init.TransmitPause = DISABLE;
+    pdrv_can->fdcanHandle.Init.ProtocolException = ENABLE;
+
+    switch (cfg->mode)
+    {
+    case RT_CAN_MODE_NORMAL:
+        pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
+        break;
+    case RT_CAN_MODE_LISTEN:
+        pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_BUS_MONITORING;
+        break;
+    case RT_CAN_MODE_LOOPBACK:
+        pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK;
+        break;
+    default:
+        pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
+        break;
+    }
+
+    uint32_t arb_idx  = _inline_get_ArbBaudIndex(cfg->baud_rate);
+    if (arb_idx == (uint32_t)-1)
+    {
+        LOG_E("not support %d baudrate", cfg->baud_rate);
+        return -RT_ERROR;
+    }
+    /* FDCAN arbitration segment */
+    pdrv_can->fdcanHandle.Init.NominalPrescaler      = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.prescaler;
+    pdrv_can->fdcanHandle.Init.NominalSyncJumpWidth  = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.num_sjw;
+    pdrv_can->fdcanHandle.Init.NominalTimeSeg1       = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.num_seg1;
+    pdrv_can->fdcanHandle.Init.NominalTimeSeg2       = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.num_seg2;
+#ifdef RT_CAN_USING_CANFD
+    if(cfg->enable_canfd) {
+        uint32_t data_idx = _inline_get_DataBaudIndex(cfg->baud_rate_fd);
+        if (data_idx == (uint32_t)-1)
+        {
+            LOG_E("not support %d baudrate", cfg->baud_rate_fd);
+            return -RT_ERROR;
+        }
+        /* 数据段 */
+        pdrv_can->fdcanHandle.Init.DataPrescaler         = st_FDCAN_DataTiming[data_idx].cam_bit_timing.prescaler;
+        pdrv_can->fdcanHandle.Init.DataSyncJumpWidth     = st_FDCAN_DataTiming[data_idx].cam_bit_timing.num_sjw;
+        pdrv_can->fdcanHandle.Init.DataTimeSeg1          = st_FDCAN_DataTiming[data_idx].cam_bit_timing.num_seg1;
+        pdrv_can->fdcanHandle.Init.DataTimeSeg2          = st_FDCAN_DataTiming[data_idx].cam_bit_timing.num_seg2;
+    }
+#endif
+    /* Configure Message RAM */
+    if(pdrv_can->fdcanHandle.Instance == FDCAN1)
+    {
+        pdrv_can->fdcanHandle.Init.MessageRAMOffset = 0;
+    }
+    else
+    {
+        pdrv_can->fdcanHandle.Init.MessageRAMOffset = 1280;
+    }
+    pdrv_can->fdcanHandle.Init.StdFiltersNbr = 2;
+    pdrv_can->fdcanHandle.Init.ExtFiltersNbr = 2;
+    pdrv_can->fdcanHandle.Init.RxFifo0ElmtsNbr = 1;
+    pdrv_can->fdcanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
+    pdrv_can->fdcanHandle.Init.RxFifo1ElmtsNbr = 0;
+    pdrv_can->fdcanHandle.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;
+    pdrv_can->fdcanHandle.Init.RxBuffersNbr = 0;
+    pdrv_can->fdcanHandle.Init.RxBufferSize = FDCAN_DATA_BYTES_64;
+    pdrv_can->fdcanHandle.Init.TxEventsNbr = 0;
+    pdrv_can->fdcanHandle.Init.TxBuffersNbr = 3;
+    pdrv_can->fdcanHandle.Init.TxFifoQueueElmtsNbr = 0;
+    pdrv_can->fdcanHandle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
+    pdrv_can->fdcanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
+
+    if (HAL_FDCAN_Init(&pdrv_can->fdcanHandle) != HAL_OK)
+    {
+        return -RT_ERROR;
+    }
+    /* default filter config */
+    HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig);
+    /*init fdcan tx header*/
+    pdrv_can->TxHeader.Identifier = 0x000000;
+    pdrv_can->TxHeader.IdType = FDCAN_EXTENDED_ID;
+    pdrv_can->TxHeader.TxFrameType = FDCAN_DATA_FRAME;
+    pdrv_can->TxHeader.DataLength = FDCAN_DLC_BYTES_8;
+    pdrv_can->TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
+    pdrv_can->TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
+    pdrv_can->TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
+    pdrv_can->TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
+    pdrv_can->TxHeader.MessageMarker = 0;
+    /* can start */
+    HAL_FDCAN_Start(&pdrv_can->fdcanHandle);
+    return RT_EOK;
+}
+
+static rt_err_t _inline_can_filter_config(stm32_fdcan_t *pdrv_can,struct rt_can_filter_config *puser_can_filter_config)
+{
+    int tmp_i32IndexCount;
+    RT_ASSERT(pdrv_can);
+    RT_ASSERT(puser_can_filter_config);
+     /* get default filter */
+    for (tmp_i32IndexCount = 0; tmp_i32IndexCount < puser_can_filter_config->count; tmp_i32IndexCount++)
+    {
+        pdrv_can->FilterConfig.FilterIndex = puser_can_filter_config->items[tmp_i32IndexCount].hdr_bank;
+        pdrv_can->FilterConfig.FilterID1 = puser_can_filter_config->items[tmp_i32IndexCount].id;
+        pdrv_can->FilterConfig.FilterID2 = puser_can_filter_config->items[tmp_i32IndexCount].mask;
+        if(puser_can_filter_config->items[tmp_i32IndexCount].ide == RT_CAN_EXTID)
+        {
+            pdrv_can->FilterConfig.IdType = FDCAN_EXTENDED_ID;
+        }
+        else
+        {
+            pdrv_can->FilterConfig.IdType = FDCAN_STANDARD_ID;
+        }
+        pdrv_can->FilterConfig.FilterType = FDCAN_FILTER_MASK;
+        pdrv_can->FilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
+        if(HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig) != HAL_OK)
+        {
+            return -RT_ERROR;
+        }
+    }
+    return RT_EOK;
+}
+
+static rt_err_t _inline_can_control(struct rt_can_device *can, int cmd, void *arg)
+{
+
+    rt_uint32_t argval;
+    stm32_fdcan_t *pdrv_can;
+    struct rt_can_filter_config *filter_cfg;
+    RT_ASSERT(can != RT_NULL);
+    pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
+    RT_ASSERT(pdrv_can != RT_NULL);
+    switch (cmd) {
+        case RT_DEVICE_CTRL_CLR_INT:
+            argval = (rt_uint32_t) arg;
+            if (argval == RT_DEVICE_FLAG_INT_RX) {
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE);
+            } else if (argval == RT_DEVICE_FLAG_INT_TX) {
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_FIFO_EMPTY);
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE);
+            } else if (argval == RT_DEVICE_CAN_INT_ERR) {
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_WARNING);
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_PASSIVE);
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_LOGGING_OVERFLOW);
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_BUS_OFF);
+                HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ARB_PROTOCOL_ERROR);
+            }
+            break;
+        case RT_DEVICE_CTRL_SET_INT:
+            argval = (rt_uint32_t) arg;
+            if (argval == RT_DEVICE_FLAG_INT_RX) {
+                HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
+                                               FDCAN_INTERRUPT_LINE0);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
+
+                if (FDCAN1 == pdrv_can->fdcanHandle.Instance) {
+                    HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 1);
+                    HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
+                } else {
+                    HAL_NVIC_SetPriority(FDCAN2_IT0_IRQn, 0, 1);
+                    HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
+                }
+            } else if (argval == RT_DEVICE_FLAG_INT_TX) {
+                HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_INTERRUPT_LINE1);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER0);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER1);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER2);
+
+                if (FDCAN1 == pdrv_can->fdcanHandle.Instance) {
+                    HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0, 2);
+                    HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
+                } else {
+                    HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 0, 2);
+                    HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
+                }
+            } else if (argval == RT_DEVICE_CAN_INT_ERR) {
+                HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_BUS_OFF, FDCAN_INTERRUPT_LINE1);
+                HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_WARNING, FDCAN_INTERRUPT_LINE1);
+                HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_PASSIVE, FDCAN_INTERRUPT_LINE1);
+                HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_ARB_PROTOCOL_ERROR,
+                                               FDCAN_INTERRUPT_LINE1);
+
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_BUS_OFF, 0);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_WARNING, 0);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_PASSIVE, 0);
+                HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ARB_PROTOCOL_ERROR, 0);
+                if (FDCAN1 == pdrv_can->fdcanHandle.Instance) {
+                    HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0, 2);
+                    HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
+                } else {
+                    HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 0, 2);
+                    HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
+                }
+            }
+            break;
+        case RT_CAN_CMD_SET_FILTER:
+            if (RT_NULL == arg) {
+                /* default filter config */
+                HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle, &pdrv_can->FilterConfig);
+            } else {
+                filter_cfg = (struct rt_can_filter_config *) arg;
+                _inline_can_filter_config(pdrv_can, filter_cfg);
+            }
+            break;
+        case RT_CAN_CMD_SET_MODE:
+            argval = (rt_uint32_t) arg;
+            if (argval != RT_CAN_MODE_NORMAL &&
+                argval != RT_CAN_MODE_LISTEN &&
+                argval != RT_CAN_MODE_LOOPBACK &&
+                argval != RT_CAN_MODE_LOOPBACKANLISTEN) {
+                return -RT_ERROR;
+            }
+            if (argval != pdrv_can->device.config.mode) {
+                pdrv_can->device.config.mode = argval;
+                return _inline_can_config(&pdrv_can->device, &pdrv_can->device.config);
+            }
+            break;
+        case RT_CAN_CMD_SET_BAUD:
+            argval = (rt_uint32_t) arg;
+            uint32_t arb_idx = _inline_get_ArbBaudIndex(argval);
+            if (arb_idx == (uint32_t) -1) {
+                return -RT_ERROR; 
+            }
+            if (argval != pdrv_can->device.config.baud_rate) {
+                pdrv_can->device.config.baud_rate = argval;
+                return _inline_can_config(&pdrv_can->device, &pdrv_can->device.config);
+            }
+            break;
+
+        case RT_CAN_CMD_SET_PRIV:
+            argval = (rt_uint32_t) arg;
+            if (argval != RT_CAN_MODE_PRIV &&
+                argval != RT_CAN_MODE_NOPRIV) {
+                return -RT_ERROR;
+            }
+            if (argval != pdrv_can->device.config.privmode) {
+                pdrv_can->device.config.privmode = argval;
+
+                return RT_EOK;
+            }
+            break;
+        case RT_CAN_CMD_GET_STATUS: {
+            rt_uint32_t tmp_u32Errcount;
+            rt_uint32_t tmp_u32status;
+            tmp_u32Errcount = pdrv_can->fdcanHandle.Instance->ECR;
+            tmp_u32status = pdrv_can->fdcanHandle.Instance->PSR;
+
+            pdrv_can->device.status.rcverrcnt = (tmp_u32Errcount >> 8) & 0x000000ff;
+            pdrv_can->device.status.snderrcnt = (tmp_u32Errcount) & 0x000000ff;
+            pdrv_can->device.status.lasterrtype = tmp_u32status & 0x000000007;
+
+            rt_memcpy(arg, &pdrv_can->device.status, sizeof(pdrv_can->device.status));
+        }
+        break;
+        case RT_CAN_CMD_SET_BAUD_FD: {
+            argval = (rt_uint32_t) arg;
+            uint32_t data_idx = _inline_get_DataBaudIndex(argval);
+            if (data_idx == (uint32_t) -1) {
+                return -RT_ERROR;
+            }
+            if (argval != pdrv_can->device.config.baud_rate_fd) {
+                pdrv_can->device.config.baud_rate_fd = argval;
+                return _inline_can_config(&pdrv_can->device, &pdrv_can->device.config);
+            }
+        }
+    }
+
+
+    return RT_EOK;
+}
+
+static int _inline_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
+{
+
+    stm32_fdcan_t *pdrv_can;
+    struct rt_can_msg *pmsg;
+    uint32_t tmp_u32DataLen;
+    RT_ASSERT(can);
+    RT_ASSERT(buf);
+
+    pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
+
+    RT_ASSERT(pdrv_can);
+
+    pmsg = (struct rt_can_msg *) buf;
+
+    /* Check the parameters */
+    tmp_u32DataLen = length_to_dlc( pmsg->len);
+
+    if(pmsg->ide == RT_CAN_EXTID)
+    {
+        pdrv_can->TxHeader.IdType = FDCAN_EXTENDED_ID;
+    }
+    else
+    {
+        pdrv_can->TxHeader.IdType = FDCAN_STANDARD_ID;
+    }
+
+    if (RT_CAN_DTR == pmsg->rtr)
+    {
+        pdrv_can->TxHeader.TxFrameType = FDCAN_DATA_FRAME;
+    }
+    else
+    {
+        pdrv_can->TxHeader.TxFrameType = FDCAN_REMOTE_FRAME;
+    }
+
+
+    pdrv_can->TxHeader.Identifier = pmsg->id;
+
+    pdrv_can->TxHeader.DataLength = tmp_u32DataLen;
+
+
+    if (pmsg->fd_frame == 1)
+    {
+        pdrv_can->TxHeader.FDFormat = FDCAN_FD_CAN;
+    }
+    else {
+        pdrv_can->TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
+    }
+
+    if(HAL_FDCAN_AddMessageToTxBuffer(&pdrv_can->fdcanHandle, &pdrv_can->TxHeader, pmsg->data, FDCAN_TX_BUFFER0 + box_num) != HAL_OK)
+    {
+        return -RT_ERROR;
+    }
+    else
+    {
+        /* Request transmission */
+        HAL_FDCAN_EnableTxBufferRequest(&pdrv_can->fdcanHandle,FDCAN_TX_BUFFER0+box_num);
+        return RT_EOK;
+    }
+}
+
+static int _inline_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
+{
+    struct rt_can_msg *pmsg;
+    stm32_fdcan_t *pdrv_can;
+
+    RT_ASSERT(can);
+    RT_ASSERT(buf);
+
+    pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
+    pmsg = (struct rt_can_msg *) buf;
+    if(HAL_FDCAN_GetRxMessage(&pdrv_can->fdcanHandle,FDCAN_RX_FIFO0+fifo, &pdrv_can->RxHeader, pmsg->data) != HAL_OK)
+    {
+        return 0;
+    }
+    else
+    {
+        if(pdrv_can->RxHeader.IdType == FDCAN_EXTENDED_ID)
+        {
+            pmsg->ide = RT_CAN_EXTID;
+        }
+        else
+        {
+            pmsg->ide = RT_CAN_STDID;
+        }
+
+        if(pdrv_can->RxHeader.RxFrameType == FDCAN_DATA_FRAME)
+        {
+            pmsg->rtr = RT_CAN_DTR;
+        }
+        else
+        {
+            pmsg->rtr = RT_CAN_RTR;
+        }
+        pmsg->id = pdrv_can->RxHeader.Identifier;
+
+        pmsg->len = pdrv_can->RxHeader.DataLength;
+        pmsg->hdr_index = pdrv_can->RxHeader.FilterIndex;
+
+        #ifdef RT_CAN_USING_CANFD
+        pmsg->fd_frame =  (pdrv_can->RxHeader.FDFormat >> 16) && 0x20;
+        pmsg->brs = (pdrv_can->RxHeader.BitRateSwitch >> 16) && 0x10;
+        #endif
+
+        return sizeof(struct rt_can_msg);
+    }
+}
+
+static const struct rt_can_ops _can_ops =
+{
+    _inline_can_config,
+    _inline_can_control,
+    _inline_can_sendmsg,
+    _inline_can_recvmsg,
+};
+
+void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
+{
+    if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
+      {
+          if(hfdcan->Instance == FDCAN1)
+          {
+#ifdef BSP_USING_FDCAN1
+              //CAN1
+              /* Retreive Rx messages from RX FIFO0 */
+              rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_RX_IND | 0 << 8);
+#endif
+          }
+        else
+        {
+#ifdef BSP_USING_FDCAN2
+            //CAN2
+            /* Retreive Rx messages from RX FIFO0 */
+            rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_RX_IND | 0 << 8);
+#endif
+        }
+    }
+}
+
+void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
+{
+    if(hfdcan->Instance == FDCAN1)
+    {
+#ifdef BSP_USING_FDCAN1
+        //can1
+        rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_DONE | ((BufferIndexes-1) << 8));
+#endif
+    }
+    else
+    {
+#ifdef BSP_USING_FDCAN2
+        //can2
+        rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_DONE | ((BufferIndexes-1) << 8));
+#endif
+    }
+}
+
+void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+    if(hfdcan->Instance == FDCAN1)
+    {
+#ifdef BSP_USING_FDCAN1
+        rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_DONE);
+#endif
+    }
+    else
+    {
+#ifdef BSP_USING_FDCAN2
+        rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_DONE);
+#endif
+    }
+}
+
+void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+    rt_uint32_t tmp_u32Errcount;
+    rt_uint32_t tmp_u32status;
+    uint32_t ret = HAL_FDCAN_GetError(hfdcan);
+
+    if(hfdcan->Instance == FDCAN1)
+    {
+#ifdef BSP_USING_FDCAN1
+        if((ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&
+            (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk))
+        {
+            //hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;
+            hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;
+            st_DrvCan1.device.status.errcode = 0xff;
+        }
+        else
+        {
+            tmp_u32Errcount = st_DrvCan1.fdcanHandle.Instance->ECR;
+            tmp_u32status = st_DrvCan1.fdcanHandle.Instance->PSR;
+            st_DrvCan1.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;
+            st_DrvCan1.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;
+            st_DrvCan1.device.status.lasterrtype = tmp_u32status&0x000000007;
+            rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_FAIL);
+
+        }
+#endif /*BSP_USING_FDCAN1*/
+    }
+    else
+    {
+#ifdef BSP_USING_FDCAN2
+        if(    (ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&
+            (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk))
+        {
+            //hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;
+            hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;
+            st_DrvCan2.device.status.errcode = 0xff;
+        }
+        else
+        {
+            //can2
+            tmp_u32Errcount = st_DrvCan2.fdcanHandle.Instance->ECR;
+            tmp_u32status = st_DrvCan2.fdcanHandle.Instance->PSR;
+            st_DrvCan2.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;
+            st_DrvCan2.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;
+            st_DrvCan2.device.status.lasterrtype = tmp_u32status&0x000000007;
+            rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_FAIL);
+        }
+#endif /*BSP_USING_FDCAN2*/
+    }
+}
+
+#ifdef BSP_USING_FDCAN1
+void FDCAN1_IT0_IRQHandler(void)             /* FDCAN1 interrupt line 0      */
+{
+    rt_interrupt_enter();
+    HAL_FDCAN_IRQHandler(&st_DrvCan1.fdcanHandle);
+    rt_interrupt_leave();
+}
+
+void FDCAN1_IT1_IRQHandler(void)             /* FDCAN1 interrupt line 1      */
+{
+    rt_interrupt_enter();
+    HAL_FDCAN_IRQHandler(&st_DrvCan1.fdcanHandle);
+    rt_interrupt_leave();
+}
+#endif /*BSP_USING_FDCAN1*/
+#ifdef BSP_USING_FDCAN2
+void FDCAN2_IT0_IRQHandler(void)             /* FDCAN2 interrupt line 0      */
+{
+    rt_interrupt_enter();
+    HAL_FDCAN_IRQHandler(&st_DrvCan2.fdcanHandle);
+    rt_interrupt_leave();
+}
+
+void FDCAN2_IT1_IRQHandler(void)             /* FDCAN2 interrupt line 1      */
+{
+    rt_interrupt_enter();
+    HAL_FDCAN_IRQHandler(&st_DrvCan2.fdcanHandle);
+    rt_interrupt_leave();
+}
+#endif/*BSP_USING_FDCAN2*/
+
+static int rt_hw_can_init(void)
+{
+    struct can_configure config;
+    config.baud_rate = CAN1MBaud;
+    config.msgboxsz = 48;
+    config.sndboxnumber = 1;
+    config.mode = RT_CAN_MODE_NORMAL;
+    config.privmode = RT_CAN_MODE_NOPRIV;
+    config.ticks = 50;
+#ifdef RT_CAN_USING_HDR
+    config.maxhdr = 14;
+#endif
+#ifdef RT_CAN_USING_CANFD
+    config.baud_rate_fd = CAN1MBaud * 8;
+    config.enable_canfd = 1;
+#endif
+    /* config default filter */
+    FDCAN_FilterTypeDef sFilterConfig;
+    sFilterConfig.IdType = FDCAN_STANDARD_ID;
+    sFilterConfig.FilterIndex = 0;
+    sFilterConfig.FilterType = FDCAN_FILTER_MASK;
+    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
+    sFilterConfig.FilterID1 = 0;
+    sFilterConfig.FilterID2 = 0x7FF;
+#ifdef BSP_USING_FDCAN1
+    st_DrvCan1.FilterConfig = sFilterConfig;
+    st_DrvCan1.device.config = config;
+    /* register FDCAN1 device */
+    rt_hw_can_register(&st_DrvCan1.device, st_DrvCan1.name, &_can_ops, &st_DrvCan1);
+#endif /* BSP_USING_FDCAN1 */
+#ifdef BSP_USING_FDCAN2
+    st_DrvCan2.FilterConfig = sFilterConfig;
+    st_DrvCan2.device.config = config;
+    /* register FDCAN2 device */
+    rt_hw_can_register(&st_DrvCan2.device, st_DrvCan2.name, &_can_ops, &st_DrvCan2);
+#endif /* BSP_USING_FDCAN2 */
+    return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_can_init);
+
+#endif /* BSP_USING_FDCAN1 || BSP_USING_FDCAN2 */
+#endif /* RT_USING_CAN */

+ 46 - 0
bsp/stm32/libraries/HAL_Drivers/drivers/drv_fdcan.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-02-24     heyuan       the first version
+ * 2020-08-17     malongwei    Fix something
+ */
+
+#ifndef __DRV_FDCAN_H__
+#define __DRV_FDCAN_H__
+
+#include <board.h>
+#include <rtdevice.h>
+
+#if defined(RT_USING_CAN) && defined(RT_CAN_USING_CANFD)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+    const char *name;
+    FDCAN_HandleTypeDef fdcanHandle;
+    FDCAN_RxHeaderTypeDef RxHeader;
+    FDCAN_TxHeaderTypeDef TxHeader;
+    uint8_t u8RxDataBuffer[8];
+    uint8_t u8TxDataBuffer[8];
+    FDCAN_FilterTypeDef FilterConfig; /*FDCAN filter*/
+    struct rt_can_device device;      /* inherit from can device */
+} stm32_fdcan_t;
+
+typedef struct {
+    uint32_t u32Baudrate;
+    struct rt_can_bit_timing cam_bit_timing;
+}stm32_fdcan_timing_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RT_USING_CAN */
+#endif /* __DRV_FDCAN_H__ */