2020-03-25 06:43 PM
I am using the stm32f7xx_hal_rtc.c driver to initialize the RTC. I have configured the high speed clock source as the external crystal (HSE) and I have configured the low speed (32 KHz) clock source as the external crystal (LSE). Prior to calling the HAL_RTC_Init routine to initialize the RTC, I read the contents of the RCC_CR and RCC_BDCR registers. The bits in these registers are as follows:
RCC_CR = 0x0003 3483 which means the following bits are set:
HSEON, HSIRDY, HSITRIM=0x10, HSICAL=0x84, HSEON, HSERDY
All of the other bits are clear.
RCC_BDCR = 0x0000 8003 which means the following bits are set:
LSEON, LSIRDY, RTCEN
All of the other bits are clear.
After analyzing the bits in the RCC_BDCR register, I have several questions. Most importantly, while the RTCEN bit is set, the RTCSEL (clock source select bits) are 00 which specifies no clock source selected. The bits should be 01 which specifies the LSE as the clock source.
Also, in spite of the fact that the LSERDY is set in the RCC_CR register, I do not see any sine wave signal when probing the 32 KHz crystal!!
The HAL_EnterInitMode routine hangs when waiting for the RTC_ISR_INITF flag to be set. The routine times out and takes the error exit. I am suspecting that the reason that the RTC initalization is failing is that there is no clock source selected for the RTC.
HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc)
{
uint32_t tickstart = 0;
/* Check if the Initialization mode is set */
if((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
{
/* Set the Initialization mode */
hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK;
/* Get tick */
tickstart = HAL_GetTick();
/* Wait till RTC is in INIT state and if Time out is reached exit */
while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
{
if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
Any help with either of these issues would be appreciated.
2020-03-25 11:52 PM
> Also, in spite of the fact that the LSERDY is set in the RCC_CR register, I do not see any sine wave signal when probing the 32 KHz crystal!!
That's a low power circuit, you shouldn't be touching it with a common oscilloscope probe. Output LSE to MCO and measure there. If problems, try to increase LSEDRV.
> After analyzing the bits in the RCC_BDCR register, I have several questions. Most importantly, while the RTCEN bit is set, the RTCSEL (clock source select bits) are 00 which specifies no clock source selected. The bits should be 01 which specifies the LSE as the clock source.
Cube is open source, so you can step through it and observe what does it do with RCC registers. Or, maybe better, ditch Cube, write your own clock setup.
Also note, that LSE might take quite some time until it starts up; tens of seconds are normal - think about this when observing the LSE, and also when setting any timeout.
JW
2020-03-26 10:12 AM
Thank you for the advice. I will first try to modify the code in the stm32f7xx_hal_rcc.c driver to set the RTC clock select bits. My reasoning is that access to the registers in the backup domain are enable by the driver and so it would be trivial to add a line of code setting the RTC clock select bits. I will also try your suggestion to route the LSE clock to MCO and make my measurements there. (BTW, I am using a scope probe in the X10 mode which presents an impedence > 1M ohms and a very low capacitance so it shouldn't interfere (load) the 32 KHz oscillator circuit.)
In any event, I will advise you of the results of the recommended changes.
2020-03-26 10:43 AM
Your advice was spot on!! I modified the stm32f7xx_hal_rcc.c driver to set the RTC clock select bits, verified that they were indeed being set and tested my RTC driver. It worked perfectly!!! Since the RTC is functioning correctly using the LSE as the clock source, there is no need to check the LSE oscillator!!
Thank you very much for your assistance. I wan't to tell you that the most valuable advice that you gave me is to modify the HAL drivers as needed in order to get them to work correctly. I had forgotten that they are open source and have not been subjected to rigorous testing!!
2020-03-26 01:07 PM
Can you please share your modifications?
Thanks,
JW
2020-03-26 01:39 PM
I added a line of code to the #define __HAL_RCC_LSE_CONFIG(__STATE__) macro in the stm32f7xx_hal_rcc.h header to set the RTCSEL_0 bit (to select the LSE (32 KHz.) external oscillator as the RTC clock source):
/**
* @brief Macro to configure the External Low Speed oscillator (LSE).
* @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not supported by this macro.
* User should request a transition to LSE Off first and then LSE On or LSE Bypass.
* @note As the LSE is in the Backup domain and write access is denied to
* this domain after reset, you have to enable write access using
* HAL_PWR_EnableBkUpAccess() function before to configure the LSE
* (to be done once after reset).
* @note After enabling the LSE (RCC_LSE_ON or RCC_LSE_BYPASS), the application
* software should wait on LSERDY flag to be set indicating that LSE clock
* is stable and can be used to clock the RTC.
* @param __STATE__ specifies the new state of the LSE.
* This parameter can be one of the following values:
* @arg RCC_LSE_OFF: turn OFF the LSE oscillator, LSERDY flag goes low after
* 6 LSE oscillator clock cycles.
* @arg RCC_LSE_ON: turn ON the LSE oscillator.
* @arg RCC_LSE_BYPASS: LSE oscillator bypassed with external clock.
*/
#define __HAL_RCC_LSE_CONFIG(__STATE__) \
do { \
if((__STATE__) == RCC_LSE_ON) \
{ \
SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); \
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The following line of code was added:
SET_BIT(RCC->BDCR, RCC_BDCR_RTCSEL_0); \
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
} \
else if((__STATE__) == RCC_LSE_OFF) \
{ \
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); \
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \
} \
else if((__STATE__) == RCC_LSE_BYPASS) \
{ \
SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \
SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); \
} \
else \
{ \
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); \
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \
} \
} while(0)
/**
* @}
*/