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
To use this, remove the default "mbed" library and import this one instead. Target must be NUCLEO_L152RE.
Revision 25:d1474e74f0a2, committed 2015-10-08
- 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
--- 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); + } }