mirror of https://github.com/ARMmbed/mbed-os.git
STM32 LPTICKER update for targets supporting RTC
parent
39a9801675
commit
e3deaecc27
|
@ -173,8 +173,8 @@ static void LPTIM1_IRQHandler(void)
|
|||
/* Clear Compare match flag */
|
||||
__HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM);
|
||||
|
||||
if (irq_handler) {
|
||||
irq_handler();
|
||||
if (irq_handler) {
|
||||
irq_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,28 +240,35 @@ void lp_ticker_clear_interrupt(void)
|
|||
#else /* MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
|
||||
#include "rtc_api_hal.h"
|
||||
|
||||
const ticker_info_t* lp_ticker_get_info()
|
||||
{
|
||||
static const ticker_info_t info = {
|
||||
RTC_CLOCK/4, // RTC_WAKEUPCLOCK_RTCCLK_DIV4
|
||||
32
|
||||
};
|
||||
return &info;
|
||||
}
|
||||
|
||||
void lp_ticker_init(void)
|
||||
{
|
||||
rtc_init();
|
||||
lp_ticker_disable_interrupt();
|
||||
}
|
||||
|
||||
uint32_t lp_ticker_read(void)
|
||||
{
|
||||
uint32_t usecs = rtc_read_us();
|
||||
return usecs;
|
||||
return rtc_read_lp();
|
||||
}
|
||||
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
uint32_t delta;
|
||||
|
||||
delta = timestamp - lp_ticker_read();
|
||||
rtc_set_wake_up_timer(delta);
|
||||
rtc_set_wake_up_timer(timestamp);
|
||||
}
|
||||
|
||||
void lp_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(RTC_WKUP_IRQn);
|
||||
rtc_fire_interrupt();
|
||||
}
|
||||
|
||||
void lp_ticker_disable_interrupt(void)
|
||||
|
@ -271,7 +278,7 @@ void lp_ticker_disable_interrupt(void)
|
|||
|
||||
void lp_ticker_clear_interrupt(void)
|
||||
{
|
||||
NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);
|
||||
NVIC_DisableIRQ(RTC_WKUP_IRQn);
|
||||
}
|
||||
|
||||
#endif /* MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
|
|
|
@ -36,15 +36,6 @@
|
|||
|
||||
static RTC_HandleTypeDef RtcHandle;
|
||||
|
||||
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
|
||||
|
||||
#define GET_TICK_PERIOD(VALUE) (2048 * 1000000 / VALUE) /* 1s / SynchPrediv value * 2^11 (value to get the maximum precision value with no u32 overflow) */
|
||||
|
||||
static void (*irq_handler)(void);
|
||||
static void RTC_IRQHandler(void);
|
||||
static uint32_t lp_TickPeriod_us = GET_TICK_PERIOD(4095); /* default SynchPrediv value = 4095 */
|
||||
#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
|
||||
void rtc_init(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
|
@ -119,10 +110,6 @@ void rtc_init(void)
|
|||
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
|
||||
#endif /* TARGET_STM32F1 */
|
||||
|
||||
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
|
||||
lp_TickPeriod_us = GET_TICK_PERIOD(RtcHandle.Init.SynchPrediv);
|
||||
#endif
|
||||
|
||||
if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
|
||||
error("RTC initialization failed");
|
||||
}
|
||||
|
@ -288,18 +275,41 @@ void rtc_synchronize(void)
|
|||
|
||||
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
|
||||
|
||||
static void RTC_IRQHandler(void);
|
||||
static void (*irq_handler)(void);
|
||||
|
||||
volatile uint8_t lp_Fired = 0;
|
||||
volatile uint32_t LP_continuous_time = 0;
|
||||
volatile uint32_t LP_last_RTC_time = 0;
|
||||
|
||||
static void RTC_IRQHandler(void)
|
||||
{
|
||||
/* Update HAL state */
|
||||
RtcHandle.Instance = RTC;
|
||||
HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
|
||||
/* In case of registered handler, call it. */
|
||||
if (irq_handler) {
|
||||
irq_handler();
|
||||
if(__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) {
|
||||
/* Get the status of the Interrupt */
|
||||
if((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) {
|
||||
/* Clear the WAKEUPTIMER interrupt pending bit */
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
|
||||
|
||||
lp_Fired = 0;
|
||||
if (irq_handler) {
|
||||
irq_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lp_Fired) {
|
||||
lp_Fired = 0;
|
||||
if (irq_handler) {
|
||||
irq_handler();
|
||||
}
|
||||
}
|
||||
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
|
||||
}
|
||||
|
||||
uint32_t rtc_read_us(void)
|
||||
uint32_t rtc_read_lp(void)
|
||||
{
|
||||
RTC_TimeTypeDef timeStruct = {0};
|
||||
RTC_DateTypeDef dateStruct = {0};
|
||||
|
@ -316,52 +326,52 @@ uint32_t rtc_read_us(void)
|
|||
time/date is one second less than as indicated by RTC_TR/RTC_DR. */
|
||||
timeStruct.Seconds -= 1;
|
||||
}
|
||||
uint32_t RTCTime = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60;
|
||||
uint32_t Time_us = ((timeStruct.SecondFraction - timeStruct.SubSeconds) * lp_TickPeriod_us) >> 11;
|
||||
uint32_t RTC_time_s = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; // Max 0x0001-517F => * 8191 + 8191 = 0x2A2E-AE80
|
||||
|
||||
return (RTCTime * 1000000) + Time_us ;
|
||||
if (LP_last_RTC_time <= RTC_time_s) {
|
||||
LP_continuous_time += (RTC_time_s - LP_last_RTC_time);
|
||||
} else {
|
||||
LP_continuous_time += (24 * 60 * 60 + RTC_time_s - LP_last_RTC_time);
|
||||
}
|
||||
LP_last_RTC_time = RTC_time_s;
|
||||
|
||||
return LP_continuous_time * PREDIV_S_VALUE + timeStruct.SecondFraction - timeStruct.SubSeconds;
|
||||
}
|
||||
|
||||
void rtc_set_wake_up_timer(uint32_t delta)
|
||||
void rtc_set_wake_up_timer(timestamp_t timestamp)
|
||||
{
|
||||
#define RTC_CLOCK_US (((uint64_t)RTC_CLOCK << 32 ) / 1000000)
|
||||
|
||||
uint32_t WakeUpCounter;
|
||||
uint32_t WakeUpClock;
|
||||
uint32_t current_lp_time;
|
||||
|
||||
/* Ex for Wakeup period resolution with RTCCLK=32768 Hz :
|
||||
* RTCCLK_DIV2: ~122us < wakeup period < ~4s
|
||||
* RTCCLK_DIV4: ~244us < wakeup period < ~8s
|
||||
* RTCCLK_DIV8: ~488us < wakeup period < ~16s
|
||||
* RTCCLK_DIV16: ~976us < wakeup period < ~32s
|
||||
* CK_SPRE_16BITS: 1s < wakeup period < (0xFFFF+ 1) x 1 s = 65536 s (18 hours)
|
||||
* CK_SPRE_17BITS: 18h+1s < wakeup period < (0x1FFFF+ 1) x 1 s = 131072 s (36 hours)
|
||||
*/
|
||||
if (delta < (0x10000 * 2 / RTC_CLOCK * 1000000) ) { // (0xFFFF + 1) * RTCCLK_DIV2 / RTC_CLOCK * 1s
|
||||
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 1 ;
|
||||
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV2;
|
||||
} else if (delta < (0x10000 * 4 / RTC_CLOCK * 1000000) ) {
|
||||
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 2 ;
|
||||
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV4;
|
||||
} else if (delta < (0x10000 * 8 / RTC_CLOCK * 1000000) ) {
|
||||
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 3 ;
|
||||
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV8;
|
||||
} else if (delta < (0x10000 * 16 / RTC_CLOCK * 1000000) ) {
|
||||
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 4 ;
|
||||
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV16;
|
||||
current_lp_time = rtc_read_lp();
|
||||
|
||||
if (timestamp < current_lp_time) {
|
||||
WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp;
|
||||
} else {
|
||||
WakeUpCounter = (delta / 1000000) ;
|
||||
WakeUpClock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
|
||||
WakeUpCounter = timestamp - current_lp_time;
|
||||
}
|
||||
|
||||
irq_handler = (void (*)(void))lp_ticker_irq_handler;
|
||||
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
|
||||
NVIC_EnableIRQ(RTC_WKUP_IRQn);
|
||||
if (WakeUpCounter > 0xFFFF) {
|
||||
WakeUpCounter = 0xFFFF;
|
||||
}
|
||||
|
||||
RtcHandle.Instance = RTC;
|
||||
if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, (uint32_t)WakeUpCounter, WakeUpClock) != HAL_OK) {
|
||||
if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) {
|
||||
error("rtc_set_wake_up_timer init error\n");
|
||||
}
|
||||
|
||||
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
|
||||
irq_handler = (void (*)(void))lp_ticker_irq_handler;
|
||||
NVIC_EnableIRQ(RTC_WKUP_IRQn);
|
||||
}
|
||||
|
||||
void rtc_fire_interrupt(void)
|
||||
{
|
||||
lp_Fired = 1;
|
||||
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
|
||||
irq_handler = (void (*)(void))lp_ticker_irq_handler;
|
||||
NVIC_SetPendingIRQ(RTC_WKUP_IRQn);
|
||||
NVIC_EnableIRQ(RTC_WKUP_IRQn);
|
||||
}
|
||||
|
||||
void rtc_deactivate_wake_up_timer(void)
|
||||
|
|
|
@ -44,31 +44,26 @@ extern "C" {
|
|||
#define RTC_CLOCK LSI_VALUE
|
||||
#endif
|
||||
|
||||
/* PREDIV_A : 7-bit asynchronous prescaler */
|
||||
/* PREDIV_S : 15-bit synchronous prescaler */
|
||||
/* PREDIV_S is set in order to get a 1 Hz clock */
|
||||
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
|
||||
/* PREDIV_A is set to a small value to improve the SubSeconds resolution */
|
||||
/* with a 32768Hz clock, PREDIV_A=7 gives a precision of 244us */
|
||||
#define PREDIV_A_VALUE 7
|
||||
#else /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
/* PREDIV_A is set to the maximum value to improve the consumption */
|
||||
#define PREDIV_A_VALUE 127
|
||||
#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
/* PREDIV_A : 7-bit asynchronous prescaler */
|
||||
/* PREDIV_A is set to set LPTICKER frequency to RTC_CLOCK/4 */
|
||||
#define PREDIV_A_VALUE 3
|
||||
|
||||
#define PREDIV_S_VALUE RTC_CLOCK / (PREDIV_A_VALUE + 1) - 1
|
||||
|
||||
/** Read RTC time with subsecond precision.
|
||||
/** Read RTC counter with sub second precision
|
||||
*
|
||||
* @return Time is microsecond
|
||||
* @return LP ticker counter
|
||||
*/
|
||||
uint32_t rtc_read_us(void);
|
||||
uint32_t rtc_read_lp(void);
|
||||
|
||||
/** Program a wake up timer event in delta microseconds.
|
||||
/** Program a wake up timer event
|
||||
*
|
||||
* @param delta The time to wait
|
||||
* @param timestamp: counter to set
|
||||
*/
|
||||
void rtc_set_wake_up_timer(uint32_t delta);
|
||||
void rtc_set_wake_up_timer(timestamp_t timestamp);
|
||||
|
||||
/** Call RTC Wake Up IT
|
||||
*/
|
||||
void rtc_fire_interrupt(void);
|
||||
|
||||
/** Disable the wake up timer event.
|
||||
*
|
||||
|
@ -76,13 +71,24 @@ void rtc_set_wake_up_timer(uint32_t delta);
|
|||
*/
|
||||
void rtc_deactivate_wake_up_timer(void);
|
||||
|
||||
#else /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
|
||||
/* PREDIV_A : 7-bit asynchronous prescaler */
|
||||
/* PREDIV_A is set to the maximum value to improve the consumption */
|
||||
#define PREDIV_A_VALUE 127
|
||||
|
||||
#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
|
||||
|
||||
/* PREDIV_S : 15-bit synchronous prescaler */
|
||||
/* PREDIV_S is set in order to get a 1 Hz clock */
|
||||
#define PREDIV_S_VALUE RTC_CLOCK / (PREDIV_A_VALUE + 1) - 1
|
||||
|
||||
/** Synchronise the RTC shadow registers.
|
||||
*
|
||||
* Must be called after a deepsleep.
|
||||
*/
|
||||
void rtc_synchronize(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue