Skip to main content
PHolt.1
Senior
June 28, 2023
Question

32F417: HAL_RCCEx_PeriphCLKConfig() questions

  • June 28, 2023
  • 3 replies
  • 1716 views

Hello All,

The above function is used to config various clocks. For the RTC it contains this

 

 

 

		/* Enable Power Clock*/
		__HAL_RCC_PWR_CLK_ENABLE();

		/* Enable write access to Backup domain */
		PWR->CR |= PWR_CR_DBP;

		// Wait for above to stabilise
		tickstart = HAL_GetTick();
		while((PWR->CR & PWR_CR_DBP) == RESET)
		{
			if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
			{
				return HAL_TIMEOUT;
			}
		}

 

 

 

They have a 1-2ms timeout on the write access enable bit. But there is no timeout in other HAL code for the same code e.g.

 

 

 

HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
{
 uint32_t tmpreg = 0U;
 
 /* Check the parameters */
 assert_param(IS_RTC_FORMAT(Format));
 assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving));
 assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation));
 
 /* Process Locked */ 
 __HAL_LOCK(hrtc);
 
 hrtc->State = HAL_RTC_STATE_BUSY;
 
 if(Format == RTC_FORMAT_BIN)
 {
 if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
 {
 assert_param(IS_RTC_HOUR12(sTime->Hours));
 assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
 } 
 else
 {
 sTime->TimeFormat = 0x00U;
 assert_param(IS_RTC_HOUR24(sTime->Hours));
 }
 assert_param(IS_RTC_MINUTES(sTime->Minutes));
 assert_param(IS_RTC_SECONDS(sTime->Seconds));
 
 tmpreg = (uint32_t)(((uint32_t)RTC_ByteToBcd2(sTime->Hours) << 16U) | \
 ((uint32_t)RTC_ByteToBcd2(sTime->Minutes) << 8U) | \
 ((uint32_t)RTC_ByteToBcd2(sTime->Seconds)) | \
 (((uint32_t)sTime->TimeFormat) << 16U)); 
 }
 else
 {
 if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
 {
 tmpreg = RTC_Bcd2ToByte(sTime->Hours);
 assert_param(IS_RTC_HOUR12(tmpreg));
 assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); 
 } 
 else
 {
 sTime->TimeFormat = 0x00U;
 assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
 }
 assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
 assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
 tmpreg = (((uint32_t)(sTime->Hours) << 16U) | \
 ((uint32_t)(sTime->Minutes) << 8U) | \
 ((uint32_t)sTime->Seconds) | \
 ((uint32_t)(sTime->TimeFormat) << 16U)); 
 }
 
 /* Disable the write protection for RTC registers */
 __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
 
 /* Set Initialization mode */
 if(RTC_EnterInitMode(hrtc) != HAL_OK)
 {
 /* Enable the write protection for RTC registers */
 __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); 
 
 /* Set RTC state */
 hrtc->State = HAL_RTC_STATE_ERROR;
 
 /* Process Unlocked */ 
 __HAL_UNLOCK(hrtc);
 
 return HAL_ERROR;
 } 
 else
 {
 /* Set the RTC_TR register */
 hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK);
 
 /* Clear the bits to be configured */
 hrtc->Instance->CR &= (uint32_t)~RTC_CR_BCK;
 
 /* Configure the RTC_CR register */
 hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation);
 
 /* Exit Initialization mode */
 hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; 
 
 /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
 if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET)
 {
 if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
 { 
 /* Enable the write protection for RTC registers */
 __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); 
 
 hrtc->State = HAL_RTC_STATE_ERROR;
 
 /* Process Unlocked */ 
 __HAL_UNLOCK(hrtc);
 
 return HAL_ERROR;
 }
 }
 
 /* Enable the write protection for RTC registers */
 __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
 
 hrtc->State = HAL_RTC_STATE_READY;
 
 __HAL_UNLOCK(hrtc); 
 
 return HAL_OK;
 }
}

 

Old hands will know that e.g.

__HAL_LOCK(hrtc);
hrtc->State = HAL_RTC_STATE_BUSY;

is completely junk code, but I just pasted the whole function here :)

 

This topic has been closed for replies.

3 replies

waclawek.jan
Super User
June 28, 2023

This is ST's rendition of http://efton.sk/STM32/gotcha/g27.html and links therein.

JW

PHolt.1
PHolt.1Author
Senior
June 28, 2023

Sure; what I don't get is why do the wait in one place and not in the other.

If I understand your article correctly, it would be ok to just do

PWR->CR |= PWR_CR_DBP;
PWR->CR;
waclawek.jan
Super User
June 28, 2023

> If I understand your article correctly, it would be ok to just do

If the explanation I provided is correct, then yes. I am not ST but I think that explanation is plausible; and that's what the mentioned erratum says, too.

> what I don't get is why do the wait in one place and not in the other.

I don't know what is "other place". In the "other" code you quoted I see no access to PWR_CR; there may be indirect, I am not interested in debugging Cube, explaining it, not even touching it with a stick.

RTC is on the same bus (APB1) as PWR, so if you write to PWR and then to RTC, writes to RTC won't happen until the write to PWR is completed.

JW

PHolt.1
PHolt.1Author
Senior
June 29, 2023

 

I was confusing write access to backup domain with write access to the RTC.

One needs the wait, the other one evidently does not.