2023-06-28 04:24 AM - edited 2023-06-28 04:34 AM
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 🙂
2023-06-28 08:31 AM
This is ST's rendition of http://efton.sk/STM32/gotcha/g27.html and links therein.
JW
2023-06-28 08:38 AM
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;
2023-06-28 11:37 AM - edited 2023-06-28 11:39 AM
> 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
2023-06-29 04:22 AM
I was confusing write access to backup domain with write access to the RTC.
One needs the wait, the other one evidently does not.