Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:09

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_hal_timebase_rtc_wakeup_template.c
0004   * @author  MCD Application Team
0005   * @brief   HAL time base based on the hardware RTC_WAKEUP Template.
0006   *
0007   *          This file overrides the native HAL time base functions (defined as weak)
0008   *          to use the RTC WAKEUP for the time base generation:
0009   *           + Initializes the RTC peripheral and configures the wakeup timer to be
0010   *             incremented each 1ms
0011   *           + The wakeup feature is configured to assert an interrupt each 1ms
0012   *           + HAL_IncTick is called inside the HAL_RTCEx_WakeUpTimerEventCallback
0013   *           + HSE (default), LSE or LSI can be selected as RTC clock source
0014   *
0015   ******************************************************************************
0016   * @attention
0017   *
0018   * Copyright (c) 2017 STMicroelectronics.
0019   * All rights reserved.
0020   *
0021   * This software is licensed under terms that can be found in the LICENSE file
0022   * in the root directory of this software component.
0023   * If no LICENSE file comes with this software, it is provided AS-IS.
0024   *
0025   ******************************************************************************
0026  @verbatim
0027   ==============================================================================
0028                         ##### How to use this driver #####
0029   ==============================================================================
0030     [..]
0031     This file must be copied to the application folder and modified as follows:
0032     (#) Rename it to 'stm32h7xx_hal_timebase_rtc_wakeup.c'
0033     (#) Add this file and the RTC HAL drivers to your project and uncomment
0034        HAL_RTC_MODULE_ENABLED define in stm32h7xx_hal_conf.h
0035 
0036     [..]
0037     (@) HAL RTC alarm and HAL RTC wakeup drivers can not be used with low power modes:
0038         The wake up capability of the RTC may be intrusive in case of prior low power mode
0039         configuration requiring different wake up sources.
0040         Application/Example behavior is no more guaranteed
0041     (@) The stm32h7xx_hal_timebase_tim use is recommended for the Applications/Examples
0042           requiring low power modes
0043 
0044   @endverbatim
0045   ******************************************************************************
0046   */
0047 
0048 /* Includes ------------------------------------------------------------------*/
0049 #include "stm32h7xx_hal.h"
0050 /** @addtogroup STM32H7xx_HAL_Driver
0051   * @{
0052   */
0053 
0054 /** @defgroup HAL_TimeBase_RTC_WakeUp_Template  HAL TimeBase RTC WakeUp Template
0055   * @ingroup RTEMSBSPsARMSTM32H7
0056   * @{
0057   */
0058 
0059 /* Private typedef -----------------------------------------------------------*/
0060 /* Private define ------------------------------------------------------------*/
0061 
0062 /* Uncomment the line below to select the appropriate RTC Clock source for your application:
0063   + RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision.
0064   + RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing
0065                           precision.
0066   + RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing
0067                           precision.
0068   */
0069 #define RTC_CLOCK_SOURCE_HSE
0070 /* #define RTC_CLOCK_SOURCE_LSE */
0071 /* #define RTC_CLOCK_SOURCE_LSI */
0072 
0073 #ifdef RTC_CLOCK_SOURCE_HSE
0074   #define RTC_ASYNCH_PREDIV       99U
0075   #define RTC_SYNCH_PREDIV        9U
0076   #define RCC_RTCCLKSOURCE_1MHZ   ((uint32_t)((uint32_t)RCC_BDCR_RTCSEL | (uint32_t)((HSE_VALUE/1000000U) << 12U)))
0077 #else /* RTC_CLOCK_SOURCE_LSE || RTC_CLOCK_SOURCE_LSI */
0078   #define RTC_ASYNCH_PREDIV       0U
0079   #define RTC_SYNCH_PREDIV        31U
0080 #endif /* RTC_CLOCK_SOURCE_HSE */
0081 
0082 /* Private macro -------------------------------------------------------------*/
0083 /* Private variables ---------------------------------------------------------*/
0084 static RTC_HandleTypeDef        hRTC_Handle;
0085 
0086 /* Private function prototypes -----------------------------------------------*/
0087 void RTC_WKUP_IRQHandler(void);
0088 
0089 /* Private functions ---------------------------------------------------------*/
0090 
0091 /**
0092   * @brief  This function configures the RTC_WKUP as a time base source.
0093   *         The time source is configured  to have 1ms time base with a dedicated
0094   *         Tick interrupt priority.
0095   *         Wakeup Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK
0096                              = 1ms
0097   *         Wakeup Time = WakeupTimebase * WakeUpCounter (0 + 1)
0098                         = 1 ms
0099   * @note   This function is called  automatically at the beginning of program after
0100   *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
0101   * @param  TickPriority Tick interrupt priority.
0102   * @retval HAL status
0103   */
0104 HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
0105 {
0106   __IO uint32_t counter = 0U;
0107 
0108   RCC_OscInitTypeDef        RCC_OscInitStruct;
0109   RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
0110   HAL_StatusTypeDef     status;
0111 
0112 #ifdef RTC_CLOCK_SOURCE_LSE
0113   /* Configure LSE as RTC clock source */
0114   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
0115   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
0116   RCC_OscInitStruct.LSEState = RCC_LSE_ON;
0117   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
0118 #elif defined (RTC_CLOCK_SOURCE_LSI)
0119   /* Configure LSI as RTC clock source */
0120   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
0121   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
0122   RCC_OscInitStruct.LSIState = RCC_LSI_ON;
0123   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
0124 #elif defined (RTC_CLOCK_SOURCE_HSE)
0125   /* Configure HSE as RTC clock source */
0126   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
0127   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
0128   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
0129   /* Ensure that RTC is clocked by 1MHz */
0130   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_1MHZ;
0131 #else
0132 #error Please select the RTC Clock source
0133 #endif /* RTC_CLOCK_SOURCE_LSE */
0134 
0135   status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
0136   if (status == HAL_OK)
0137   {
0138     PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
0139     status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
0140   }
0141   if (status == HAL_OK)
0142   {
0143       /* Enable RTC Clock */
0144       __HAL_RCC_RTC_ENABLE();
0145       /* The time base should be 1ms
0146          Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK
0147          HSE as RTC clock
0148            Time base = ((99 + 1) * (9 + 1)) / 1Mhz
0149                      = 1ms
0150          LSE as RTC clock
0151            Time base = ((31 + 1) * (0 + 1)) / 32.768Khz
0152                      = ~1ms
0153          LSI as RTC clock
0154            Time base = ((31 + 1) * (0 + 1)) / 32Khz
0155                      = 1ms
0156       */
0157       hRTC_Handle.Instance = RTC;
0158       hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24;
0159       hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
0160       hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
0161       hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE;
0162       hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
0163       hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
0164       status = HAL_RTC_Init(&hRTC_Handle);
0165   }
0166   if (status == HAL_OK)
0167   {
0168       /* Disable the write protection for RTC registers */
0169       __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
0170 
0171       /* Disable the Wake-up Timer */
0172       __HAL_RTC_WAKEUPTIMER_DISABLE(&hRTC_Handle);
0173 
0174       /* In case of interrupt mode is used, the interrupt source must disabled */
0175       __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hRTC_Handle, RTC_IT_WUT);
0176 
0177       /* Wait till RTC WUTWF flag is set  */
0178 #if defined(RTC_ICSR_WUTWF)
0179       while (READ_BIT(hRTC_Handle.Instance->ICSR, RTC_FLAG_WUTWF) == (uint32_t)RESET)
0180 #else
0181       while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hRTC_Handle, RTC_FLAG_WUTWF) == (uint32_t)RESET)
0182 #endif  /* RTC_ICSR_WUTWF */
0183       {
0184         if (counter++ == (SystemCoreClock / 48U))
0185       {
0186         status = HAL_ERROR;
0187       }
0188     }
0189   }
0190   if (status == HAL_OK)
0191   {
0192     /* Clear PWR wake up Flag */
0193     __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
0194 
0195     /* Clear RTC Wake Up timer Flag */
0196     __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_WUTF);
0197 
0198     /* Configure the Wake-up Timer counter */
0199     hRTC_Handle.Instance->WUTR = (uint32_t)0U;
0200 
0201     /* Clear the Wake-up Timer clock source bits in CR register */
0202     hRTC_Handle.Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL;
0203 
0204     /* Configure the clock source */
0205     hRTC_Handle.Instance->CR |= (uint32_t)RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
0206 
0207     /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */
0208     __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
0209 
0210     __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
0211 
0212     /* Configure the Interrupt in the RTC_CR register */
0213     __HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hRTC_Handle,RTC_IT_WUT);
0214 
0215     /* Enable the Wake-up Timer */
0216     __HAL_RTC_WAKEUPTIMER_ENABLE(&hRTC_Handle);
0217 
0218     /* Enable the write protection for RTC registers */
0219     __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
0220 
0221     /* Enable the RTC global Interrupt */
0222     HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
0223 
0224     /* Configure the SysTick IRQ priority */
0225     if (TickPriority < (1UL << __NVIC_PRIO_BITS))
0226     {
0227       HAL_NVIC_SetPriority(RTC_WKUP_IRQn, TickPriority, 0U);
0228       uwTickPrio = TickPriority;
0229     }
0230     else
0231     {
0232       status = HAL_ERROR;
0233     }
0234   }
0235   return status;
0236 }
0237 
0238 /**
0239   * @brief  Suspend Tick increment.
0240   * @note   Disable the tick increment by disabling RTC_WKUP interrupt.
0241   * @retval None
0242   */
0243 void HAL_SuspendTick(void)
0244 {
0245   /* Disable the write protection for RTC registers */
0246   __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
0247   /* Disable WAKE UP TIMER Interrupt */
0248   __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hRTC_Handle, RTC_IT_WUT);
0249   /* Enable the write protection for RTC registers */
0250   __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
0251 }
0252 
0253 /**
0254   * @brief  Resume Tick increment.
0255   * @note   Enable the tick increment by Enabling RTC_WKUP interrupt.
0256   * @retval None
0257   */
0258 void HAL_ResumeTick(void)
0259 {
0260   /* Disable the write protection for RTC registers */
0261   __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
0262   /* Enable  WAKE UP TIMER  interrupt */
0263   __HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hRTC_Handle, RTC_IT_WUT);
0264   /* Enable the write protection for RTC registers */
0265   __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
0266 }
0267 
0268 /**
0269   * @brief  Wake Up Timer Event Callback in non blocking mode
0270   * @note   This function is called  when RTC_WKUP interrupt took place, inside
0271   * RTC_WKUP_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
0272   * a global variable "uwTick" used as application time base.
0273   * @param  hrtc RTC handle
0274   * @retval None
0275   */
0276 void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
0277 {
0278   /* Prevent unused argument(s) compilation warning */
0279   UNUSED(hrtc);
0280 
0281   HAL_IncTick();
0282 }
0283 
0284 /**
0285   * @brief  This function handles  WAKE UP TIMER  interrupt request.
0286   * @retval None
0287   */
0288 void RTC_WKUP_IRQHandler(void)
0289 {
0290   HAL_RTCEx_WakeUpTimerIRQHandler(&hRTC_Handle);
0291 }
0292 
0293 /**
0294   * @}
0295   */
0296 
0297 /**
0298   * @}
0299   */
0300 
0301