Fork of mbed-dev with the NUCLEO-L152RE target modified for use with the STM32L151RB (128 kB flash, 16 kB RAM).

Fork of mbed-dev by mbed official

To use this, remove the default "mbed" library and import this one instead. Target must be NUCLEO_L152RE.

Files at this revision

API Documentation at this revision

Comitter:
Jim Paris
Date:
Thu Oct 08 10:27:29 2015 -0400
Parent:
24:43727708725f
Child:
26:d19adb5b60f6
Commit message:
Fix us_ticker, hal_tick for 16-bit counter (based on STM32L0 code)

Changed in this revision

targets/cmsis/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/hal_tick.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/PeripheralNames.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/PeripheralPins.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_STM32L1/pwmout_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_STM32L1/us_ticker.c Show annotated file Show diff for this revision Revisions of this file
--- a/targets/cmsis/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/hal_tick.c	Wed Oct 07 17:47:41 2015 -0400
+++ b/targets/cmsis/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/hal_tick.c	Thu Oct 08 10:27:29 2015 -0400
@@ -38,16 +38,43 @@
 uint32_t PreviousVal = 0;
 
 void us_ticker_irq_handler(void);
+void set_compare(uint16_t count);
+
+extern volatile uint32_t SlaveCounter;
+extern volatile uint32_t oc_int_part;
+extern volatile uint16_t oc_rem_part;
 
 void timer_irq_handler(void) {
+    uint16_t cval = TIM_MST->CNT;
+
+    TimMasterHandle.Instance = TIM_MST;
+
+    // Clear Update interrupt flag
+    if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) {
+        __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE);
+        SlaveCounter++;
+    }
+
     // Channel 1 for mbed timeout
-    if (__HAL_TIM_GET_ITSTATUS(&TimMasterHandle, TIM_IT_CC1) == SET) {
-        us_ticker_irq_handler();
+    if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
+        __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
+        if (oc_rem_part > 0) {
+            set_compare(oc_rem_part); // Finish the remaining time left
+            oc_rem_part = 0;
+        } else {
+            if (oc_int_part > 0) {
+                set_compare(0xFFFF);
+                oc_rem_part = cval; // To finish the counter loop the next time
+                oc_int_part--;
+            } else {
+                us_ticker_irq_handler();
+            }
+        }
     }
 
     // Channel 2 for HAL tick
-    if (__HAL_TIM_GET_ITSTATUS(&TimMasterHandle, TIM_IT_CC2) == SET) {
-        __HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC2);
+    if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC2) == SET) {
+        __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC2);
         uint32_t val = __HAL_TIM_GetCounter(&TimMasterHandle);
         if ((val - PreviousVal) >= HAL_TICK_DELAY) {
             // Increment HAL variable
@@ -55,9 +82,6 @@
             // Prepare next interrupt
             __HAL_TIM_SetCompare(&TimMasterHandle, TIM_CHANNEL_2, val + HAL_TICK_DELAY);
             PreviousVal = val;
-#if 0 // For DEBUG only
-            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
-#endif
         }
     }
 }
@@ -76,33 +100,33 @@
 
     // Configure time base
     TimMasterHandle.Instance = TIM_MST;
-    TimMasterHandle.Init.Period            = 0xFFFFFFFF;
-    TimMasterHandle.Init.Prescaler         = (uint32_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
-    TimMasterHandle.Init.ClockDivision     = 0;
-    TimMasterHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
-    HAL_TIM_OC_Init(&TimMasterHandle);
+    TimMasterHandle.Init.Period        = 0xFFFFFFFF;
+    TimMasterHandle.Init.Prescaler     = (uint32_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
+    TimMasterHandle.Init.ClockDivision = 0;
+    TimMasterHandle.Init.CounterMode   = TIM_COUNTERMODE_UP;
+    HAL_TIM_Base_Init(&TimMasterHandle);
+
+    // Configure output compare channel 1 for mbed timeout (enabled later when used)
+    HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
 
+    // Configure output compare channel 2 for HAL tick
+    HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_2);
+    PreviousVal = __HAL_TIM_GetCounter(&TimMasterHandle);
+    __HAL_TIM_SetCompare(&TimMasterHandle, TIM_CHANNEL_2, PreviousVal + HAL_TICK_DELAY);
+
+    // Configure interrupts
+    // Update interrupt used for 32-bit counter
+    // Output compare channel 1 interrupt for mbed timeout
+    // Output compare channel 2 interrupt for HAL tick
     NVIC_SetVector(TIM_MST_IRQ, (uint32_t)timer_irq_handler);
     NVIC_EnableIRQ(TIM_MST_IRQ);
 
-    // Channel 1 for mbed timeout
-    HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
-
-    // Channel 2 for HAL tick
-    HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_2);
-    PreviousVal = __HAL_TIM_GetCounter(&TimMasterHandle);
-    __HAL_TIM_SetCompare(&TimMasterHandle, TIM_CHANNEL_2, PreviousVal + HAL_TICK_DELAY);
-    __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC2);
+    // Enable interrupts
+    __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_UPDATE); // For 32-bit counter
+    __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC2); // For HAL tick
 
-#if 0 // For DEBUG only
-    __GPIOB_CLK_ENABLE();
-    GPIO_InitTypeDef GPIO_InitStruct;
-    GPIO_InitStruct.Pin = GPIO_PIN_6;
-    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
-    GPIO_InitStruct.Pull = GPIO_PULLUP;
-    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
-    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-#endif
+    // Enable timer
+    HAL_TIM_Base_Start(&TimMasterHandle);
 
     return HAL_OK;
 }
--- a/targets/hal/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/PeripheralNames.h	Wed Oct 07 17:47:41 2015 -0400
+++ b/targets/hal/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/PeripheralNames.h	Thu Oct 08 10:27:29 2015 -0400
@@ -72,7 +72,7 @@
     PWM_3  = (int)TIM3_BASE,
     PWM_4  = (int)TIM4_BASE,
 //    PWM_5  = (int)TIM5_BASE,
-    PWM_9  = (int)TIM9_BASE,
+//    PWM_9  = (int)TIM9_BASE,
     PWM_10 = (int)TIM10_BASE,
     PWM_11 = (int)TIM11_BASE
 } PWMName;
--- a/targets/hal/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/PeripheralPins.c	Wed Oct 07 17:47:41 2015 -0400
+++ b/targets/hal/TARGET_STM/TARGET_STM32L1/TARGET_NUCLEO_L152RE/PeripheralPins.c	Thu Oct 08 10:27:29 2015 -0400
@@ -88,7 +88,7 @@
 
 //*** PWM ***
 
-// TIM5 cannot be used because already used by the us_ticker.
+// TIM9 cannot be used because already used by the us_ticker.
 const PinMap PinMap_PWM[] = {
 //  {PA_0,  PWM_5,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5)},  // TIM5_CH1
     {PA_1,  PWM_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2)},  // TIM2_CH2
@@ -117,8 +117,8 @@
     {PB_10, PWM_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2)},  // TIM2_CH3
     {PB_11, PWM_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2)},  // TIM2_CH4
     {PB_12, PWM_10, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM10)}, // TIM10_CH1
-    {PB_13, PWM_9,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9)},  // TIM9_CH1
-    {PB_14, PWM_9,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9)},  // TIM9_CH2
+//    {PB_13, PWM_9,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9)},  // TIM9_CH1
+//    {PB_14, PWM_9,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9)},  // TIM9_CH2
     {PB_15, PWM_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM11)}, // TIM11_CH1
     {PC_6,  PWM_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3)},  // TIM3_CH1
     {PC_7,  PWM_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3)},  // TIM3_CH2
--- a/targets/hal/TARGET_STM/TARGET_STM32L1/pwmout_api.c	Wed Oct 07 17:47:41 2015 -0400
+++ b/targets/hal/TARGET_STM/TARGET_STM32L1/pwmout_api.c	Thu Oct 08 10:27:29 2015 -0400
@@ -52,7 +52,7 @@
     if (obj->pwm == PWM_3) __TIM3_CLK_ENABLE();
     if (obj->pwm == PWM_4) __TIM4_CLK_ENABLE();
 //    if (obj->pwm == PWM_5) __TIM5_CLK_ENABLE();
-    if (obj->pwm == PWM_9) __TIM9_CLK_ENABLE();
+//    if (obj->pwm == PWM_9) __TIM9_CLK_ENABLE();
     if (obj->pwm == PWM_10) __TIM10_CLK_ENABLE();
     if (obj->pwm == PWM_11) __TIM11_CLK_ENABLE();
 
--- a/targets/hal/TARGET_STM/TARGET_STM32L1/us_ticker.c	Wed Oct 07 17:47:41 2015 -0400
+++ b/targets/hal/TARGET_STM/TARGET_STM32L1/us_ticker.c	Thu Oct 08 10:27:29 2015 -0400
@@ -1,5 +1,5 @@
 /* mbed Microcontroller Library
- * Copyright (c) 2014, STMicroelectronics
+ * Copyright (c) 2015, STMicroelectronics
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,41 +29,85 @@
 #include "us_ticker_api.h"
 #include "PeripheralNames.h"
 
+// Timer selection
 #define TIM_MST TIM9
 
 static TIM_HandleTypeDef TimMasterHandle;
 static int us_ticker_inited = 0;
 
+volatile uint32_t SlaveCounter = 0;
+volatile uint32_t oc_int_part = 0;
+volatile uint16_t oc_rem_part = 0;
+
+void set_compare(uint16_t count)
+{
+    TimMasterHandle.Instance = TIM_MST;
+    // Set new output compare value
+    __HAL_TIM_SetCompare(&TimMasterHandle, TIM_CHANNEL_1, count);
+    // Enable IT
+    __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
+}
+
 void us_ticker_init(void)
 {
     if (us_ticker_inited) return;
     us_ticker_inited = 1;
 
-    TimMasterHandle.Instance = TIM_MST;
-
     HAL_InitTick(0); // The passed value is not used
 }
 
 uint32_t us_ticker_read()
 {
+    uint32_t counter, counter2;
     if (!us_ticker_inited) us_ticker_init();
-    return TIM_MST->CNT;
+    // A situation might appear when Master overflows right after Slave is read and before the
+    // new (overflowed) value of Master is read. Which would make the code below consider the
+    // previous (incorrect) value of Slave and the new value of Master, which would return a
+    // value in the past. Avoid this by computing consecutive values of the timer until they
+    // are properly ordered.
+    counter = (uint32_t)(SlaveCounter << 16);
+    counter += TIM_MST->CNT;
+    while (1) {
+        counter2 = (uint32_t)(SlaveCounter << 16);
+        counter2 += TIM_MST->CNT;
+        if (counter2 > counter) {
+            break;
+        }
+        counter = counter2;
+    }
+    return counter2;
 }
 
 void us_ticker_set_interrupt(timestamp_t timestamp)
 {
-    // Set new output compare value
-    __HAL_TIM_SetCompare(&TimMasterHandle, TIM_CHANNEL_1, (uint32_t)timestamp);
-    // Enable IT
-    __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
+    int delta = (int)((uint32_t)timestamp - us_ticker_read());
+    uint16_t cval = TIM_MST->CNT;
+
+    if (delta <= 0) { // This event was in the past
+        us_ticker_irq_handler();
+    } else {
+        oc_int_part = (uint32_t)(delta >> 16);
+        oc_rem_part = (uint16_t)(delta & 0xFFFF);
+        if (oc_rem_part <= (0xFFFF - cval)) {
+            set_compare(cval + oc_rem_part);
+            oc_rem_part = 0;
+        } else {
+            set_compare(0xFFFF);
+            oc_rem_part = oc_rem_part - (0xFFFF - cval);
+        }
+    }
 }
 
 void us_ticker_disable_interrupt(void)
 {
+    TimMasterHandle.Instance = TIM_MST;
     __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1);
 }
 
 void us_ticker_clear_interrupt(void)
 {
-    __HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1);
+    TimMasterHandle.Instance = TIM_MST;
+    if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
+        __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
+    }
 }