Explorar o código

* 2021-02-02 YuZhe XU fix bug in filter config
* 2021-8-25 SVCHAO The baud rate is configured according to the different APB1 frequencies.
f4-series only.

maikebing %!s(int64=3) %!d(string=hai) anos
pai
achega
0a037419dc
Modificáronse 1 ficheiros con 108 adicións e 14 borrados
  1. 108 14
      bsp/stm32/libraries/HAL_Drivers/drv_can.c

+ 108 - 14
bsp/stm32/libraries/HAL_Drivers/drv_can.c

@@ -11,6 +11,9 @@
  *                             fix bug.port to BSP [stm32]
  * 2019-03-27     YLZ          support double can channels, support stm32F4xx (only Legacy mode).
  * 2019-06-17     YLZ          port to new STM32F1xx HAL V1.1.3.
+ * 2021-02-02     YuZhe XU     fix bug in filter config
+ * 2021-8-25      SVCHAO       The baud rate is configured according to the different APB1 frequencies.
+                               f4-series only.
  */
 
 #include "drv_can.h"
@@ -33,10 +36,29 @@ static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
     {CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 150)},
     {CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_3TQ | 300)}
 };
-#elif defined (SOC_SERIES_STM32F4)/* APB1 45MHz(max) */
+#elif defined (SOC_SERIES_STM32F4)  /* 42MHz or 45MHz */
+#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx) ||\
+    defined(STM32F401xC) || defined(STM32F401xE) /* 42MHz(max) */
 static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
 {
+    {CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_4TQ | 3)},
+    {CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_5TQ | 4)},
+    {CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 6)},
+    {CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 12)},
+    {CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 24)},
+    {CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 30)},
+    {CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 60)},
+    {CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 150)},
+    {CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 300)}
+};
+#else  /* APB1 45MHz(max) */
+static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
+{
+#ifdef BSP_USING_CAN168M
+    {CAN1MBaud, (CAN_SJW_1TQ | CAN_BS1_3TQ  | CAN_BS2_3TQ | 6)},
+#else
     {CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 3)},
+#endif
     {CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_5TQ | 4)},
     {CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 6)},
     {CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 12)},
@@ -46,6 +68,7 @@ static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
     {CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 150)},
     {CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 300)}
 };
+#endif
 #elif defined (SOC_SERIES_STM32F7)/* APB1 54MHz(max) */
 static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
 {
@@ -292,6 +315,13 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
         }
         break;
     case RT_CAN_CMD_SET_FILTER:
+    {
+        rt_uint32_t id_h = 0;
+        rt_uint32_t id_l = 0;
+        rt_uint32_t mask_h = 0;
+        rt_uint32_t mask_l = 0;
+        rt_uint32_t mask_l_tail = 0;  //CAN_FxR2 bit [2:0]
+
         if (RT_NULL == arg)
         {
             /* default filter config */
@@ -303,19 +333,80 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
             /* get default filter */
             for (int i = 0; i < filter_cfg->count; i++)
             {
-                drv_can->FilterConfig.FilterBank = filter_cfg->items[i].hdr;
-                drv_can->FilterConfig.FilterIdHigh = (filter_cfg->items[i].id >> 13) & 0xFFFF;
-                drv_can->FilterConfig.FilterIdLow = ((filter_cfg->items[i].id << 3) |
-                                                    (filter_cfg->items[i].ide << 2) |
-                                                    (filter_cfg->items[i].rtr << 1)) & 0xFFFF;
-                drv_can->FilterConfig.FilterMaskIdHigh = (filter_cfg->items[i].mask >> 16) & 0xFFFF;
-                drv_can->FilterConfig.FilterMaskIdLow = filter_cfg->items[i].mask & 0xFFFF;
+                if (filter_cfg->items[i].hdr == -1)
+                {
+                    /* use default filter bank settings */
+                    if (drv_can->name == "can1")
+                    {
+                        /* can1 banks 0~13 */
+                        drv_can->FilterConfig.FilterBank = i;
+                    }
+                    else if (drv_can->name == "can2")
+                    {
+                        /* can1 banks 14~27 */
+                        drv_can->FilterConfig.FilterBank = i + 14;
+                    }
+                }
+                else
+                {
+                    /* use user-defined filter bank settings */
+                    drv_can->FilterConfig.FilterBank = filter_cfg->items[i].hdr;
+                }
+                 /**
+                 * ID     | CAN_FxR1[31:24] | CAN_FxR1[23:16] | CAN_FxR1[15:8] | CAN_FxR1[7:0]       |
+                 * MASK   | CAN_FxR2[31:24] | CAN_FxR2[23:16] | CAN_FxR2[15:8] | CAN_FxR2[7:0]       |
+                 * STD ID |     STID[10:3]  | STDID[2:0] |<-                21bit                  ->|
+                 * EXT ID |    EXTID[28:21] | EXTID[20:13]    | EXTID[12:5]    | EXTID[4:0] IDE RTR 0|
+                 * @note the 32bit STD ID must << 21 to fill CAN_FxR1[31:21] and EXT ID must << 3,
+                 *       -> but the id bit of struct rt_can_filter_item is 29,
+                 *       -> so STD id << 18 and EXT id Don't need << 3, when get the high 16bit.
+                 *       -> FilterIdHigh : (((STDid << 18) or (EXT id)) >> 13) & 0xFFFF,
+                 *       -> FilterIdLow:   ((STDid << 18) or (EXT id << 3)) & 0xFFFF.
+                 * @note the mask bit of struct rt_can_filter_item is 32,
+                 *       -> FilterMaskIdHigh: (((STD mask << 21) or (EXT mask <<3)) >> 16) & 0xFFFF
+                 *       -> FilterMaskIdLow: ((STD mask << 21) or (EXT mask <<3)) & 0xFFFF
+                 */
+                if (filter_cfg->items[i].mode == CAN_FILTERMODE_IDMASK)
+                {
+                    /* make sure the CAN_FxR1[2:0](IDE RTR) work */
+                    mask_l_tail = 0x06;
+                }
+                else if (filter_cfg->items[i].mode == CAN_FILTERMODE_IDLIST)
+                {
+                    /* same as CAN_FxR1 */
+                    mask_l_tail = (filter_cfg->items[i].ide << 2) |
+                                   (filter_cfg->items[i].rtr << 1);
+                }
+                if (filter_cfg->items[i].ide == RT_CAN_STDID)
+                {
+                    id_h = ((filter_cfg->items[i].id << 18) >> 13) & 0xFFFF;
+                    id_l = ((filter_cfg->items[i].id << 18) |
+                            (filter_cfg->items[i].ide << 2) |
+                            (filter_cfg->items[i].rtr << 1)) & 0xFFFF;
+                    mask_h = ((filter_cfg->items[i].mask << 21) >> 16) & 0xFFFF;
+                    mask_l = ((filter_cfg->items[i].mask << 21) | mask_l_tail) & 0xFFFF;
+                }
+                else if (filter_cfg->items[i].ide == RT_CAN_EXTID)
+                {
+                    id_h = (filter_cfg->items[i].id >> 13) & 0xFFFF;
+                    id_l = ((filter_cfg->items[i].id << 3)   |
+                            (filter_cfg->items[i].ide << 2)  |
+                            (filter_cfg->items[i].rtr << 1)) & 0xFFFF;
+                    mask_h = ((filter_cfg->items[i].mask << 3) >> 16) & 0xFFFF;
+                    mask_l = ((filter_cfg->items[i].mask << 3) | mask_l_tail) & 0xFFFF;
+                }
+                drv_can->FilterConfig.FilterIdHigh = id_h;
+                drv_can->FilterConfig.FilterIdLow = id_l;
+                drv_can->FilterConfig.FilterMaskIdHigh = mask_h;
+                drv_can->FilterConfig.FilterMaskIdLow = mask_l;
+
                 drv_can->FilterConfig.FilterMode = filter_cfg->items[i].mode;
                 /* Filter conf */
                 HAL_CAN_ConfigFilter(&drv_can->CanHandle, &drv_can->FilterConfig);
             }
         }
         break;
+    }
     case RT_CAN_CMD_SET_MODE:
         argval = (rt_uint32_t) arg;
         if (argval != RT_CAN_MODE_NORMAL &&
@@ -401,8 +492,6 @@ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t
         case CAN_TX_MAILBOX0:
             if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0) != SET)
             {
-                /* Change CAN state */
-                hcan->State = HAL_CAN_STATE_ERROR;
                 /* Return function status */
                 return -RT_ERROR;
             }
@@ -410,8 +499,6 @@ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t
         case CAN_TX_MAILBOX1:
             if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1) != SET)
             {
-                /* Change CAN state */
-                hcan->State = HAL_CAN_STATE_ERROR;
                 /* Return function status */
                 return -RT_ERROR;
             }
@@ -419,8 +506,6 @@ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t
         case CAN_TX_MAILBOX2:
             if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2) != SET)
             {
-                /* Change CAN state */
-                hcan->State = HAL_CAN_STATE_ERROR;
                 /* Return function status */
                 return -RT_ERROR;
             }
@@ -652,6 +737,10 @@ void CAN1_TX_IRQHandler(void)
         /* Write 0 to Clear transmission status flag RQCPx */
         SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP2);
     }
+    else
+    {
+      rt_hw_can_isr(&drv_can1.device, RT_CAN_EVENT_TX_FAIL | 0 << 8);
+    }
     rt_interrupt_leave();
 }
 
@@ -687,6 +776,7 @@ void CAN1_SCE_IRQHandler(void)
     errtype = hcan->Instance->ESR;
 
     rt_interrupt_enter();
+	
     HAL_CAN_IRQHandler(hcan);
 
     switch ((errtype & 0x70) >> 4)
@@ -772,6 +862,10 @@ void CAN2_TX_IRQHandler(void)
         /* Write 0 to Clear transmission status flag RQCPx */
         SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP2);
     }
+    else
+    {
+      rt_hw_can_isr(&drv_can2.device, RT_CAN_EVENT_TX_FAIL | 0 << 8);
+    }
     rt_interrupt_leave();
 }