mbed

Fork of mbed-dev by mbed official

Revision:
175:b96e65c34a4d
Parent:
173:7d866c31b3c5
Child:
179:79309dc6340a
--- a/targets/TARGET_STM/can_api.c	Fri Sep 15 14:59:18 2017 +0100
+++ b/targets/TARGET_STM/can_api.c	Mon Oct 02 15:33:19 2017 +0100
@@ -25,10 +25,21 @@
 #include <math.h>
 #include <string.h>
 
-static CAN_HandleTypeDef CanHandle;
 static uint32_t can_irq_ids[CAN_NUM] = {0};
 static can_irq_handler irq_handler;
 
+static void can_registers_init(can_t *obj)
+{
+    if (HAL_CAN_Init(&obj->CanHandle) != HAL_OK) {
+        error("Cannot initialize CAN");
+    }
+
+    // Set initial CAN frequency to specified frequency
+    if (can_frequency(obj, obj->hz) != 1) {
+        error("Can frequency could not be set\n");
+    }
+}
+
 void can_init(can_t *obj, PinName rd, PinName td)
 {
     can_init_freq(obj, rd, td, 100000);
@@ -38,16 +49,16 @@
 {
     CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
     CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
+    CANName can = (CANName)pinmap_merge(can_rd, can_td);
 
-    obj->can = (CANName)pinmap_merge(can_rd, can_td);
-    MBED_ASSERT((int)obj->can != NC);
+    MBED_ASSERT((int)can != NC);
 
-    if (obj->can == CAN_1) {
+    if (can == CAN_1) {
         __HAL_RCC_CAN1_CLK_ENABLE();
         obj->index = 0;
     }
 #if defined(CAN2_BASE) && (CAN_NUM == 2)
-    else if (obj->can == CAN_2) {
+    else if (can == CAN_2) {
         __HAL_RCC_CAN1_CLK_ENABLE(); // needed to set filters
         __HAL_RCC_CAN2_CLK_ENABLE();
         obj->index = 1;
@@ -67,33 +78,30 @@
         pin_mode(td, PullUp);
     }
 
-    CanHandle.Instance = (CAN_TypeDef *)(obj->can);
+    /*  Use default values for rist init */
+    obj->CanHandle.Instance = (CAN_TypeDef *)can;
+    obj->CanHandle.Init.TTCM = DISABLE;
+    obj->CanHandle.Init.ABOM = DISABLE;
+    obj->CanHandle.Init.AWUM = DISABLE;
+    obj->CanHandle.Init.NART = DISABLE;
+    obj->CanHandle.Init.RFLM = DISABLE;
+    obj->CanHandle.Init.TXFP = DISABLE;
+    obj->CanHandle.Init.Mode = CAN_MODE_NORMAL;
+    obj->CanHandle.Init.SJW = CAN_SJW_1TQ;
+    obj->CanHandle.Init.BS1 = CAN_BS1_6TQ;
+    obj->CanHandle.Init.BS2 = CAN_BS2_8TQ;
+    obj->CanHandle.Init.Prescaler = 2;
 
-    CanHandle.Init.TTCM = DISABLE;
-    CanHandle.Init.ABOM = DISABLE;
-    CanHandle.Init.AWUM = DISABLE;
-    CanHandle.Init.NART = DISABLE;
-    CanHandle.Init.RFLM = DISABLE;
-    CanHandle.Init.TXFP = DISABLE;
-    CanHandle.Init.Mode = CAN_MODE_NORMAL;
-    CanHandle.Init.SJW = CAN_SJW_1TQ;
-    CanHandle.Init.BS1 = CAN_BS1_6TQ;
-    CanHandle.Init.BS2 = CAN_BS2_8TQ;
-    CanHandle.Init.Prescaler = 2;
+    /*  Store frequency to be restored in case of reset */
+    obj->hz = hz;
 
-    if (HAL_CAN_Init(&CanHandle) != HAL_OK) {
-        error("Cannot initialize CAN");
-    }
+    can_registers_init(obj);
 
-    // Set initial CAN frequency to specified frequency
-    if (can_frequency(obj, hz) != 1) {
-        error("Can frequency could not be set\n");
-    }
-
-    uint32_t filter_number = (obj->can == CAN_1) ? 0 : 14;
+    uint32_t filter_number = (can == CAN_1) ? 0 : 14;
     can_filter(obj, 0, 0, CANStandard, filter_number);
 }
 
+
 void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
 {
     irq_handler = handler;
@@ -102,7 +110,7 @@
 
 void can_irq_free(can_t *obj)
 {
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
 
     can->IER &= ~(CAN_IT_FMP0 | CAN_IT_FMP1 | CAN_IT_TME | \
                   CAN_IT_ERR | CAN_IT_EPV | CAN_IT_BOF);
@@ -111,14 +119,15 @@
 
 void can_free(can_t *obj)
 {
+    CANName can = (CANName) obj->CanHandle.Instance;
     // Reset CAN and disable clock
-    if (obj->can == CAN_1) {
+    if (can == CAN_1) {
         __HAL_RCC_CAN1_FORCE_RESET();
         __HAL_RCC_CAN1_RELEASE_RESET();
         __HAL_RCC_CAN1_CLK_DISABLE();
     }
 #if defined(CAN2_BASE) && (CAN_NUM == 2)
-    if (obj->can == CAN_2) {
+    if (can == CAN_2) {
         __HAL_RCC_CAN2_FORCE_RESET();
         __HAL_RCC_CAN2_RELEASE_RESET();
         __HAL_RCC_CAN2_CLK_DISABLE();
@@ -196,7 +205,7 @@
 {
     int pclk = HAL_RCC_GetPCLK1Freq();
     int btr = can_speed(pclk, (unsigned int)f, 1);
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
     uint32_t tickstart = 0;
     int status = 1;
 
@@ -211,7 +220,11 @@
             }
         }
         if (status != 0) {
-            can->BTR = btr;
+            /*  Do not erase all BTR registers (e.g. silent mode), only the
+             *  ones calculated in can_speed */
+            can->BTR &= ~(CAN_BTR_TS2 | CAN_BTR_TS1 | CAN_BTR_SJW | CAN_BTR_BRP);
+            can->BTR |= btr;
+
             can->MCR &= ~(uint32_t)CAN_MCR_INRQ;
             /* Get tick */
             tickstart = HAL_GetTick();
@@ -236,7 +249,7 @@
 int can_write(can_t *obj, CAN_Message msg, int cc)
 {
     uint32_t  transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
 
     /* Select one empty transmit mailbox */
     if ((can->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
@@ -279,7 +292,7 @@
 {
     //handle is the FIFO number
 
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
 
     // check FPM0 which holds the pending message count in FIFO 0
     // if no message is pending, return 0
@@ -324,46 +337,61 @@
 
 void can_reset(can_t *obj)
 {
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
+
+    /* Reset IP and delete errors */
     can->MCR |= CAN_MCR_RESET;
     can->ESR = 0x0;
+
+    /* restore registers state as saved in obj context */
+    can_registers_init(obj);
 }
 
 unsigned char can_rderror(can_t *obj)
 {
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
     return (can->ESR >> 24) & 0xFF;
 }
 
 unsigned char can_tderror(can_t *obj)
 {
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
     return (can->ESR >> 16) & 0xFF;
 }
 
 void can_monitor(can_t *obj, int silent)
 {
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
-
-    can->MCR |= CAN_MCR_INRQ ;
-    while ((can->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
+    CanMode mode = MODE_NORMAL;
+    /*  Update current state w/ or w/o silent */
+    if(silent) {
+        switch (obj->CanHandle.Init.Mode) {
+            case CAN_MODE_LOOPBACK:
+            case CAN_MODE_SILENT_LOOPBACK:
+                mode = MODE_TEST_SILENT;
+                break;
+            default:
+                mode = MODE_SILENT;
+                break;
+        }
+    } else {
+        switch (obj->CanHandle.Init.Mode) {
+            case CAN_MODE_LOOPBACK:
+            case CAN_MODE_SILENT_LOOPBACK:
+                mode = MODE_TEST_LOCAL;
+                break;
+            default:
+                mode = MODE_NORMAL;
+                break;
+        }
     }
 
-    if (silent) {
-        can->BTR |= ((uint32_t)1 << 31);
-    } else {
-        can->BTR &= ~((uint32_t)1 << 31);
-    }
-
-    can->MCR &= ~(uint32_t)CAN_MCR_INRQ;
-    while ((can->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) {
-    }
+    can_mode(obj, mode);
 }
 
 int can_mode(can_t *obj, CanMode mode)
 {
     int success = 0;
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
 
     can->MCR |= CAN_MCR_INRQ ;
     while ((can->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
@@ -371,21 +399,25 @@
 
     switch (mode) {
         case MODE_NORMAL:
+            obj->CanHandle.Init.Mode = CAN_MODE_NORMAL;
             can->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM);
             success = 1;
             break;
         case MODE_SILENT:
+            obj->CanHandle.Init.Mode = CAN_MODE_SILENT;
             can->BTR |= CAN_BTR_SILM;
             can->BTR &= ~CAN_BTR_LBKM;
             success = 1;
             break;
         case MODE_TEST_GLOBAL:
         case MODE_TEST_LOCAL:
+            obj->CanHandle.Init.Mode = CAN_MODE_LOOPBACK;
             can->BTR |= CAN_BTR_LBKM;
             can->BTR &= ~CAN_BTR_SILM;
             success = 1;
             break;
         case MODE_TEST_SILENT:
+            obj->CanHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
             can->BTR |= (CAN_BTR_SILM | CAN_BTR_LBKM);
             success = 1;
             break;
@@ -407,7 +439,6 @@
 
     // filter for CANAny format cannot be configured for STM32
     if ((format == CANStandard) || (format == CANExtended)) {
-        CanHandle.Instance = (CAN_TypeDef *)(obj->can);
         CAN_FilterConfTypeDef  sFilterConfig;
         sFilterConfig.FilterNumber = handle;
         sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
@@ -429,7 +460,7 @@
         sFilterConfig.FilterActivation = ENABLE;
         sFilterConfig.BankNumber = 14 + handle;
 
-        HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig);
+        HAL_CAN_ConfigFilter(&obj->CanHandle, &sFilterConfig);
         retval = handle;
     }
     return retval;
@@ -438,6 +469,7 @@
 static void can_irq(CANName name, int id)
 {
     uint32_t tmp1 = 0, tmp2 = 0, tmp3 = 0;
+    CAN_HandleTypeDef CanHandle;
     CanHandle.Instance = (CAN_TypeDef *)name;
 
     if (__HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_TME)) {
@@ -535,13 +567,12 @@
 
 void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
 {
-
-    CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+    CAN_TypeDef *can = obj->CanHandle.Instance;
     IRQn_Type irq_n = (IRQn_Type)0;
     uint32_t vector = 0;
     uint32_t ier;
 
-    if (obj->can == CAN_1) {
+    if ((CANName) can == CAN_1) {
         switch (type) {
             case IRQ_RX:
                 ier = CAN_IT_FMP0;
@@ -573,7 +604,7 @@
         }
     }
 #if defined(CAN2_BASE) && (CAN_NUM == 2)
-    else if (obj->can == CAN_2) {
+    else if ((CANName) can == CAN_2) {
         switch (type) {
             case IRQ_RX:
                 ier = CAN_IT_FMP0;