Skip to content

STM32: Fix RTC test issue on targets using a 16-bit timer for us_ticker #7352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions targets/TARGET_STM/hal_tick_16b.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#if TIM_MST_16BIT

extern TIM_HandleTypeDef TimMasterHandle;
extern uint32_t prev_time;
extern uint32_t elapsed_time;

volatile uint32_t PreviousVal = 0;

Expand Down Expand Up @@ -108,6 +110,10 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
TIM_MST_DBGMCU_FREEZE;
#endif

// Used by HAL_GetTick()
prev_time = 0;
elapsed_time = 0;

return HAL_OK;
}

Expand Down
35 changes: 34 additions & 1 deletion targets/TARGET_STM/hal_tick_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,45 @@
* limitations under the License.
*/
#include "hal/us_ticker_api.h"
#include "hal_tick.h"

// Overwrite default HAL functions defined as "weak"

// This variable is set to 1 at the of mbed_sdk_init function.
// The ticker_read_us function must not be called until the mbed_sdk_init is terminated.
extern int mbed_sdk_inited;

#if TIM_MST_16BIT
// Variables also reset in HAL_InitTick()
uint32_t prev_time = 0;
uint32_t elapsed_time = 0;
#endif

// 1 ms tick is required for ST HAL driver
uint32_t HAL_GetTick()
{
return ticker_read_us(get_us_ticker_data()) / 1000; // 1 ms tick is required for ST HAL
#if TIM_MST_16BIT
uint32_t new_time;
if (mbed_sdk_inited) {
// Apply the latest time recorded just before the sdk is inited
new_time = ticker_read_us(get_us_ticker_data()) + prev_time;
prev_time = 0; // Use this time only once
return (new_time / 1000);
}
else {
new_time = us_ticker_read();
elapsed_time += (new_time - prev_time) & 0xFFFF; // Only use the lower 16 bits
prev_time = new_time;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really needed ?
What about 32b targets ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit 9523bcf do this only for 16bits timer

return (elapsed_time / 1000);
}
#else // 32-bit timer
if (mbed_sdk_inited) {
return (ticker_read_us(get_us_ticker_data()) / 1000);
}
else {
return (us_ticker_read() / 1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the 16 bit timer this will overflow in ~66ms. If anything in the SDK init takes longer than this it may get stuck as HAL_GetTick will never count higher than this during init. As a potential solution you could accumulate elapsed time rather than reading it directly. Something like:

uint32_t new_time = us_ticker_read();
elapsed_time += (new_time - prev_time) & 0xFFFF; // Only use the lower 16 bits
prev_time = new_time;
return elapsed_time / 1000;

Note - You'll need to make sure prev_time is reset in HAL_InitTick since this resets the timer count.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit f785c23

}
#endif
}

void HAL_SuspendTick(void)
Expand Down
4 changes: 4 additions & 0 deletions targets/TARGET_STM/mbed_overrides.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
*/
#include "cmsis.h"

int mbed_sdk_inited = 0;

// This function is called after RAM initialization and before main.
void mbed_sdk_init()
{
Expand All @@ -51,4 +53,6 @@ void mbed_sdk_init()
AHB/APBx prescalers and Flash settings */
SetSysClock();
SystemCoreClockUpdate();

mbed_sdk_inited = 1;
}
10 changes: 6 additions & 4 deletions targets/TARGET_STM/sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include "mbed_error.h"

extern void rtc_synchronize(void);
extern void save_timer_ctx(void);
extern void restore_timer_ctx(void);

/* Wait loop - assuming tick is 1 us */
static void wait_loop(uint32_t timeout)
Expand Down Expand Up @@ -161,7 +163,7 @@ void hal_deepsleep(void)
// Disable IRQs
core_util_critical_section_enter();

uint32_t EnterTimeUS = us_ticker_read();
save_timer_ctx();

// Request to enter STOP mode with regulator in low power mode
#if TARGET_STM32L4
Expand All @@ -186,6 +188,7 @@ void hal_deepsleep(void)
#else /* TARGET_STM32L4 */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
#endif /* TARGET_STM32L4 */

// Verify Clock Out of Deep Sleep
ForceClockOutofDeepSleep();

Expand All @@ -198,9 +201,7 @@ void hal_deepsleep(void)
* deep sleep */
wait_loop(500);

TIM_HandleTypeDef TimMasterHandle;
TimMasterHandle.Instance = TIM_MST;
__HAL_TIM_SET_COUNTER(&TimMasterHandle, EnterTimeUS);
restore_timer_ctx();

#if DEVICE_RTC
/* Wait for RTC RSF bit synchro if RTC is configured */
Expand All @@ -212,6 +213,7 @@ void hal_deepsleep(void)
rtc_synchronize();
}
#endif

// Enable IRQs
core_util_critical_section_exit();
}
Expand Down
17 changes: 17 additions & 0 deletions targets/TARGET_STM/us_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,20 @@ void us_ticker_clear_interrupt(void)
__HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
}

uint32_t timer_cnt_reg;
uint32_t timer_ccr1_reg;
uint32_t timer_dier_reg;

void save_timer_ctx(void)
{
timer_cnt_reg = __HAL_TIM_GET_COUNTER(&TimMasterHandle);
timer_ccr1_reg = __HAL_TIM_GET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1);
timer_dier_reg = TIM_MST->DIER;
}

void restore_timer_ctx(void)
{
__HAL_TIM_SET_COUNTER(&TimMasterHandle, timer_cnt_reg);
__HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, timer_ccr1_reg);
TIM_MST->DIER = timer_dier_reg;
}