| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893 |
- /**
- ******************************************************************************
- * File Name : hw_timerserver.c
- * Description : Hardware timerserver source file for STM32WPAN Middleware.
- *
- ******************************************************************************
- * @attention
- *
- * <h2><center>© Copyright (c) 2020 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under Ultimate Liberty license
- * SLA0044, the "License"; You may not use this file except in compliance with
- * the License. You may obtain a copy of the License at:
- * www.st.com/SLA0044
- *
- ******************************************************************************
- */
- /* Includes ------------------------------------------------------------------*/
- #include "app_common.h"
- #include "hw_conf.h"
- /* Private typedef -----------------------------------------------------------*/
- typedef enum
- {
- TimerID_Free,
- TimerID_Created,
- TimerID_Running
- }TimerIDStatus_t;
- typedef enum
- {
- SSR_Read_Requested,
- SSR_Read_Not_Requested
- }RequestReadSSR_t;
- typedef enum
- {
- WakeupTimerValue_Overpassed,
- WakeupTimerValue_LargeEnough
- }WakeupTimerLimitation_Status_t;
- typedef struct
- {
- HW_TS_pTimerCb_t pTimerCallBack;
- uint32_t CounterInit;
- uint32_t CountLeft;
- TimerIDStatus_t TimerIDStatus;
- HW_TS_Mode_t TimerMode;
- uint32_t TimerProcessID;
- uint8_t PreviousID;
- uint8_t NextID;
- }TimerContext_t;
- /* Private defines -----------------------------------------------------------*/
- #define SSR_FORBIDDEN_VALUE 0xFFFFFFFF
- #define TIMER_LIST_EMPTY 0xFFFF
- /* Private macros ------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /**
- * START of Section TIMERSERVER_CONTEXT
- */
- PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile TimerContext_t aTimerContext[CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER];
- PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint8_t CurrentRunningTimerID;
- PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint8_t PreviousRunningTimerID;
- PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint32_t SSRValueOnLastSetup;
- PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile WakeupTimerLimitation_Status_t WakeupTimerLimitation;
- /**
- * END of Section TIMERSERVER_CONTEXT
- */
- static RTC_HandleTypeDef *phrtc; /**< RTC handle */
- static uint8_t WakeupTimerDivider;
- static uint8_t AsynchPrescalerUserConfig;
- static uint16_t SynchPrescalerUserConfig;
- static volatile uint16_t MaxWakeupTimerSetup;
- /* Global variables ----------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- static void RestartWakeupCounter(uint16_t Value);
- static uint16_t ReturnTimeElapsed(void);
- static void RescheduleTimerList(void);
- static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR);
- static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID);
- static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID);
- static uint16_t linkTimer(uint8_t TimerID);
- static uint32_t ReadRtcSsrValue(void);
- __weak void HW_TS_RTC_CountUpdated_AppNot(void);
- /* Functions Definition ------------------------------------------------------*/
- /**
- * @brief Read the RTC_SSR value
- * As described in the reference manual, the RTC_SSR shall be read twice to ensure
- * reliability of the value
- * @param None
- * @retval SSR value read
- */
- static uint32_t ReadRtcSsrValue(void)
- {
- uint32_t first_read;
- uint32_t second_read;
- first_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
- second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
- while(first_read != second_read)
- {
- first_read = second_read;
- second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
- }
- return second_read;
- }
- /**
- * @brief Insert a Timer in the list after the Timer ID specified
- * @param TimerID: The ID of the Timer
- * @param RefTimerID: The ID of the Timer to be linked after
- * @retval None
- */
- static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID)
- {
- uint8_t next_id;
- next_id = aTimerContext[RefTimerID].NextID;
- if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
- {
- aTimerContext[next_id].PreviousID = TimerID;
- }
- aTimerContext[TimerID].NextID = next_id;
- aTimerContext[TimerID].PreviousID = RefTimerID ;
- aTimerContext[RefTimerID].NextID = TimerID;
- return;
- }
- /**
- * @brief Insert a Timer in the list before the ID specified
- * @param TimerID: The ID of the Timer
- * @param RefTimerID: The ID of the Timer to be linked before
- * @retval None
- */
- static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID)
- {
- uint8_t previous_id;
- if(RefTimerID != CurrentRunningTimerID)
- {
- previous_id = aTimerContext[RefTimerID].PreviousID;
- aTimerContext[previous_id].NextID = TimerID;
- aTimerContext[TimerID].NextID = RefTimerID;
- aTimerContext[TimerID].PreviousID = previous_id ;
- aTimerContext[RefTimerID].PreviousID = TimerID;
- }
- else
- {
- aTimerContext[TimerID].NextID = RefTimerID;
- aTimerContext[RefTimerID].PreviousID = TimerID;
- }
- return;
- }
- /**
- * @brief Insert a Timer in the list
- * @param TimerID: The ID of the Timer
- * @retval None
- */
- static uint16_t linkTimer(uint8_t TimerID)
- {
- uint32_t time_left;
- uint16_t time_elapsed;
- uint8_t timer_id_lookup;
- uint8_t next_id;
- if(CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
- {
- /**
- * No timer in the list
- */
- PreviousRunningTimerID = CurrentRunningTimerID;
- CurrentRunningTimerID = TimerID;
- aTimerContext[TimerID].NextID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;
- SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
- time_elapsed = 0;
- }
- else
- {
- time_elapsed = ReturnTimeElapsed();
- /**
- * update count of the timer to be linked
- */
- aTimerContext[TimerID].CountLeft += time_elapsed;
- time_left = aTimerContext[TimerID].CountLeft;
- /**
- * Search for index where the new timer shall be linked
- */
- if(aTimerContext[CurrentRunningTimerID].CountLeft <= time_left)
- {
- /**
- * Search for the ID after the first one
- */
- timer_id_lookup = CurrentRunningTimerID;
- next_id = aTimerContext[timer_id_lookup].NextID;
- while((next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[next_id].CountLeft <= time_left))
- {
- timer_id_lookup = aTimerContext[timer_id_lookup].NextID;
- next_id = aTimerContext[timer_id_lookup].NextID;
- }
- /**
- * Link after the ID
- */
- LinkTimerAfter(TimerID, timer_id_lookup);
- }
- else
- {
- /**
- * Link before the first ID
- */
- LinkTimerBefore(TimerID, CurrentRunningTimerID);
- PreviousRunningTimerID = CurrentRunningTimerID;
- CurrentRunningTimerID = TimerID;
- }
- }
- return time_elapsed;
- }
- /**
- * @brief Remove a Timer from the list
- * @param TimerID: The ID of the Timer
- * @param RequestReadSSR: Request to read the SSR register or not
- * @retval None
- */
- static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR)
- {
- uint8_t previous_id;
- uint8_t next_id;
- if(TimerID == CurrentRunningTimerID)
- {
- PreviousRunningTimerID = CurrentRunningTimerID;
- CurrentRunningTimerID = aTimerContext[TimerID].NextID;
- }
- else
- {
- previous_id = aTimerContext[TimerID].PreviousID;
- next_id = aTimerContext[TimerID].NextID;
- aTimerContext[previous_id].NextID = aTimerContext[TimerID].NextID;
- if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
- {
- aTimerContext[next_id].PreviousID = aTimerContext[TimerID].PreviousID;
- }
- }
- /**
- * Timer is out of the list
- */
- aTimerContext[TimerID].TimerIDStatus = TimerID_Created;
- if((CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (RequestReadSSR == SSR_Read_Requested))
- {
- SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
- }
- return;
- }
- /**
- * @brief Return the number of ticks counted by the wakeuptimer since it has been started
- * @note The API is reading the SSR register to get how many ticks have been counted
- * since the time the timer has been started
- * @param None
- * @retval Time expired in Ticks
- */
- static uint16_t ReturnTimeElapsed(void)
- {
- uint32_t return_value;
- uint32_t wrap_counter;
- if(SSRValueOnLastSetup != SSR_FORBIDDEN_VALUE)
- {
- return_value = ReadRtcSsrValue(); /**< Read SSR register first */
- if (SSRValueOnLastSetup >= return_value)
- {
- return_value = SSRValueOnLastSetup - return_value;
- }
- else
- {
- wrap_counter = SynchPrescalerUserConfig - return_value;
- return_value = SSRValueOnLastSetup + wrap_counter;
- }
- /**
- * At this stage, ReturnValue holds the number of ticks counted by SSR
- * Need to translate in number of ticks counted by the Wakeuptimer
- */
- return_value = return_value*AsynchPrescalerUserConfig;
- return_value = return_value >> WakeupTimerDivider;
- }
- else
- {
- return_value = 0;
- }
- return (uint16_t)return_value;
- }
- /**
- * @brief Set the wakeup counter
- * @note The API is writing the counter value so that the value is decreased by one to cope with the fact
- * the interrupt is generated with 1 extra clock cycle (See RefManuel)
- * It assumes all condition are met to be allowed to write the wakeup counter
- * @param Value: Value to be written in the counter
- * @retval None
- */
- static void RestartWakeupCounter(uint16_t Value)
- {
- /**
- * The wakeuptimer has been disabled in the calling function to reduce the time to poll the WUTWF
- * FLAG when the new value will have to be written
- * __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);
- */
- if(Value == 0)
- {
- SSRValueOnLastSetup = ReadRtcSsrValue();
- /**
- * Simulate that the Timer expired
- */
- HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
- }
- else
- {
- if((Value > 1) ||(WakeupTimerDivider != 1))
- {
- Value -= 1;
- }
- while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
- /**
- * make sure to clear the flags after checking the WUTWF.
- * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
- * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
- * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
- * due to the autoreload feature
- */
- __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
- __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
- HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
- MODIFY_REG(RTC->WUTR, RTC_WUTR_WUT, Value);
- /**
- * Update the value here after the WUTWF polling that may take some time
- */
- SSRValueOnLastSetup = ReadRtcSsrValue();
- __HAL_RTC_WAKEUPTIMER_ENABLE(phrtc); /**< Enable the Wakeup Timer */
- HW_TS_RTC_CountUpdated_AppNot();
- }
- return ;
- }
- /**
- * @brief Reschedule the list of timer
- * @note 1) Update the count left for each timer in the list
- * 2) Setup the wakeuptimer
- * @param None
- * @retval None
- */
- static void RescheduleTimerList(void)
- {
- uint8_t localTimerID;
- uint32_t timecountleft;
- uint16_t wakeup_timer_value;
- uint16_t time_elapsed;
- /**
- * The wakeuptimer is disabled now to reduce the time to poll the WUTWF
- * FLAG when the new value will have to be written
- */
- if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
- {
- /**
- * Wait for the flag to be back to 0 when the wakeup timer is enabled
- */
- while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == SET);
- }
- __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc); /**< Disable the Wakeup Timer */
- localTimerID = CurrentRunningTimerID;
- /**
- * Calculate what will be the value to write in the wakeuptimer
- */
- timecountleft = aTimerContext[localTimerID].CountLeft;
- /**
- * Read how much has been counted
- */
- time_elapsed = ReturnTimeElapsed();
- if(timecountleft < time_elapsed )
- {
- /**
- * There is no tick left to count
- */
- wakeup_timer_value = 0;
- WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
- }
- else
- {
- if(timecountleft > (time_elapsed + MaxWakeupTimerSetup))
- {
- /**
- * The number of tick left is greater than the Wakeuptimer maximum value
- */
- wakeup_timer_value = MaxWakeupTimerSetup;
- WakeupTimerLimitation = WakeupTimerValue_Overpassed;
- }
- else
- {
- wakeup_timer_value = timecountleft - time_elapsed;
- WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
- }
- }
- /**
- * update ticks left to be counted for each timer
- */
- while(localTimerID != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
- {
- if (aTimerContext[localTimerID].CountLeft < time_elapsed)
- {
- aTimerContext[localTimerID].CountLeft = 0;
- }
- else
- {
- aTimerContext[localTimerID].CountLeft -= time_elapsed;
- }
- localTimerID = aTimerContext[localTimerID].NextID;
- }
- /**
- * Write next count
- */
- RestartWakeupCounter(wakeup_timer_value);
- return ;
- }
- /* Public functions ----------------------------------------------------------*/
- /**
- * For all public interface except that may need write access to the RTC, the RTC
- * shall be unlock at the beginning and locked at the output
- * In order to ease maintainability, the unlock is done at the top and the lock at then end
- * in case some new implementation is coming in the future
- */
- void HW_TS_RTC_Wakeup_Handler(void)
- {
- HW_TS_pTimerCb_t ptimer_callback;
- uint32_t timer_process_id;
- uint8_t local_current_running_timer_id;
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- uint32_t primask_bit;
- #endif
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
- __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
- #endif
- /* Disable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
- /**
- * Disable the Wakeup Timer
- * This may speed up a bit the processing to wait the timer to be disabled
- * The timer is still counting 2 RTCCLK
- */
- __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);
- local_current_running_timer_id = CurrentRunningTimerID;
- if(aTimerContext[local_current_running_timer_id].TimerIDStatus == TimerID_Running)
- {
- ptimer_callback = aTimerContext[local_current_running_timer_id].pTimerCallBack;
- timer_process_id = aTimerContext[local_current_running_timer_id].TimerProcessID;
- /**
- * It should be good to check whether the TimeElapsed is greater or not than the tick left to be counted
- * However, due to the inaccuracy of the reading of the time elapsed, it may return there is 1 tick
- * to be left whereas the count is over
- * A more secure implementation has been done with a flag to state whereas the full count has been written
- * in the wakeuptimer or not
- */
- if(WakeupTimerLimitation != WakeupTimerValue_Overpassed)
- {
- if(aTimerContext[local_current_running_timer_id].TimerMode == hw_ts_Repeated)
- {
- UnlinkTimer(local_current_running_timer_id, SSR_Read_Not_Requested);
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- HW_TS_Start(local_current_running_timer_id, aTimerContext[local_current_running_timer_id].CounterInit);
- /* Disable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
- }
- else
- {
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- HW_TS_Stop(local_current_running_timer_id);
- /* Disable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
- }
- HW_TS_RTC_Int_AppNot(timer_process_id, local_current_running_timer_id, ptimer_callback);
- }
- else
- {
- RescheduleTimerList();
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- }
- }
- else
- {
- /**
- * We should never end up in this case
- * However, if due to any bug in the timer server this is the case, the mistake may not impact the user.
- * We could just clean the interrupt flag and get out from this unexpected interrupt
- */
- while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
- /**
- * make sure to clear the flags after checking the WUTWF.
- * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
- * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
- * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
- * due to the autoreload feature
- */
- __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
- __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- }
- /* Enable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
- return;
- }
- void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *hrtc)
- {
- uint8_t loop;
- uint32_t localmaxwakeuptimersetup;
- /**
- * Get RTC handler
- */
- phrtc = hrtc;
- /* Disable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
- SET_BIT(RTC->CR, RTC_CR_BYPSHAD);
- /**
- * Readout the user config
- */
- WakeupTimerDivider = (4 - ((uint32_t)(READ_BIT(RTC->CR, RTC_CR_WUCKSEL))));
- AsynchPrescalerUserConfig = (uint8_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_A) >> (uint32_t)POSITION_VAL(RTC_PRER_PREDIV_A)) + 1;
- SynchPrescalerUserConfig = (uint16_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_S)) + 1;
- /**
- * Margin is taken to avoid wrong calculation when the wrap around is there and some
- * application interrupts may have delayed the reading
- */
- localmaxwakeuptimersetup = ((((SynchPrescalerUserConfig - 1)*AsynchPrescalerUserConfig) - CFG_HW_TS_RTC_HANDLER_MAX_DELAY) >> WakeupTimerDivider);
- if(localmaxwakeuptimersetup >= 0xFFFF)
- {
- MaxWakeupTimerSetup = 0xFFFF;
- }
- else
- {
- MaxWakeupTimerSetup = (uint16_t)localmaxwakeuptimersetup;
- }
- /**
- * Configure EXTI module
- */
- LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
- LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
- if(TimerInitMode == hw_ts_InitMode_Full)
- {
- WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
- SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
- /**
- * Initialize the timer server
- */
- for(loop = 0; loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; loop++)
- {
- aTimerContext[loop].TimerIDStatus = TimerID_Free;
- }
- CurrentRunningTimerID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; /**< Set ID to non valid value */
- __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc); /**< Disable the Wakeup Timer */
- __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
- __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
- HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
- __HAL_RTC_WAKEUPTIMER_ENABLE_IT(phrtc, RTC_IT_WUT); /**< Enable interrupt in RTC module */
- }
- else
- {
- if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTF) != RESET)
- {
- /**
- * Simulate that the Timer expired
- */
- HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
- }
- }
- /* Enable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
- HAL_NVIC_SetPriority(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO); /**< Set NVIC priority */
- HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
- return;
- }
- HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pftimeout_handler)
- {
- HW_TS_ReturnStatus_t localreturnstatus;
- uint8_t loop = 0;
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- uint32_t primask_bit;
- #endif
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
- __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
- #endif
- while((loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[loop].TimerIDStatus != TimerID_Free))
- {
- loop++;
- }
- if(loop != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
- {
- aTimerContext[loop].TimerIDStatus = TimerID_Created;
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- aTimerContext[loop].TimerProcessID = TimerProcessID;
- aTimerContext[loop].TimerMode = TimerMode;
- aTimerContext[loop].pTimerCallBack = pftimeout_handler;
- *pTimerId = loop;
- localreturnstatus = hw_ts_Successful;
- }
- else
- {
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- localreturnstatus = hw_ts_Failed;
- }
- return(localreturnstatus);
- }
- void HW_TS_Delete(uint8_t timer_id)
- {
- HW_TS_Stop(timer_id);
- aTimerContext[timer_id].TimerIDStatus = TimerID_Free; /**< release ID */
- return;
- }
- void HW_TS_Stop(uint8_t timer_id)
- {
- uint8_t localcurrentrunningtimerid;
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- uint32_t primask_bit;
- #endif
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
- __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
- #endif
- HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Disable NVIC */
- /* Disable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
- if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
- {
- UnlinkTimer(timer_id, SSR_Read_Requested);
- localcurrentrunningtimerid = CurrentRunningTimerID;
- if(localcurrentrunningtimerid == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
- {
- /**
- * List is empty
- */
- /**
- * Disable the timer
- */
- if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
- {
- /**
- * Wait for the flag to be back to 0 when the wakeup timer is enabled
- */
- while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == SET);
- }
- __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc); /**< Disable the Wakeup Timer */
- while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
- /**
- * make sure to clear the flags after checking the WUTWF.
- * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
- * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
- * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
- * due to the autoreload feature
- */
- __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
- __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
- HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
- }
- else if(PreviousRunningTimerID != localcurrentrunningtimerid)
- {
- RescheduleTimerList();
- }
- }
- /* Enable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
- HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- return;
- }
- void HW_TS_Start(uint8_t timer_id, uint32_t timeout_ticks)
- {
- uint16_t time_elapsed;
- uint8_t localcurrentrunningtimerid;
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- uint32_t primask_bit;
- #endif
- if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
- {
- HW_TS_Stop( timer_id );
- }
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
- __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
- #endif
- HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Disable NVIC */
- /* Disable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
- aTimerContext[timer_id].TimerIDStatus = TimerID_Running;
- aTimerContext[timer_id].CountLeft = timeout_ticks;
- aTimerContext[timer_id].CounterInit = timeout_ticks;
- time_elapsed = linkTimer(timer_id);
- localcurrentrunningtimerid = CurrentRunningTimerID;
- if(PreviousRunningTimerID != localcurrentrunningtimerid)
- {
- RescheduleTimerList();
- }
- else
- {
- aTimerContext[timer_id].CountLeft -= time_elapsed;
- }
- /* Enable the write protection for RTC registers */
- __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
- HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
- #if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- #endif
- return;
- }
- uint16_t HW_TS_RTC_ReadLeftTicksToCount(void)
- {
- uint32_t primask_bit;
- uint16_t return_value, auro_reload_value, elapsed_time_value;
- primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
- __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
- if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
- {
- auro_reload_value = (uint32_t)(READ_BIT(RTC->WUTR, RTC_WUTR_WUT));
- elapsed_time_value = ReturnTimeElapsed();
- if(auro_reload_value > elapsed_time_value)
- {
- return_value = auro_reload_value - elapsed_time_value;
- }
- else
- {
- return_value = 0;
- }
- }
- else
- {
- return_value = TIMER_LIST_EMPTY;
- }
- __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
- return (return_value);
- }
- __weak void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack)
- {
- pTimerCallBack();
- return;
- }
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|