2024-08-09 10:24 AM
Hi Folks,
I'm having an issue with just reading and writing new values to the RTC. I'm using a custom board that contains a 32.786Khz crystal and in CubeIDE the LSE is setup properly. I also have a battery connected to Vbatt,
I'm using the following to read the RTC values:
if (HAL_RTC_GetTime(&hrtc, &rtcTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
if (HAL_RTC_GetDate(&hrtc, &rtcDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
And to write the RTC values:
if (HAL_RTC_SetTime(&hrtc, &rtcTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
if (HAL_RTC_SetDate(&hrtc, &rtcDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
This code seems to work as long as I don't hit the reset button or turn off the power.
Why wouldn't the Vbatt voltage keep the values as set? Is there something else I need to do to
write the values into memory?
Thanks,
Richard
Solved! Go to Solution.
2024-08-12 08:12 AM
I got it working by only using half of what you originally suggested. This is what works (so far):
/* USER CODE BEGIN Check_RTC_BKUP */
if((RCC->BDCR & 0x8000) == 0) // rtc enabled ? <-- this 2 lines
{
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
}
PWR->CR2 |= 0x01; // bren enable 2
/* USER CODE END RTC_Init 2 */
}
I have reset the board multiple times and cycled the power multiple times and the clock data stays as programmed.
Thanks for your help. You saved me multiple hours.
Richard
2024-08-09 10:52 AM
What does your code look like at initialization? If I recall correctly, the HAL generated stuff will reset the time on startup. You'll need to circumvent that with a check of some sort.
Set a breakpoint prior to where RTC gets initialized and see if the register values are still there. Probably they are.
2024-08-09 01:13 PM
Yes, the HAL code will start and init the RTC , as you (user) expect. ok.
BUT on next start - it will do the same. Not what you want... :)
Now you want : init new chip, set to a time, but on next start, just dont touch the clock, let time run as expected.
This is simple, if you put some code in the "user areas" , to get this behaviour:
static void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
if((RCC->BDCR & 0x8000) == 0) // rtc enabled ? <-- this 2 lines
{
/* USER CODE END RTC_Init 0 */
and at end of mx..init :
/* USER CODE BEGIN RTC_Init 2 */
}
PWR->CR2 |= 0x01; // bren enable 2
/* USER CODE END RTC_Init 2 */
-> so you just let mx..init run only, if RTC is not enabled = at first start.
After this its enabled and the IF { ... } goes without the init and just lets the RTC running.
2024-08-09 03:52 PM
I'm not quite following what you are suggesting. Here is the STM32CubeIDE generated RTC.C code:
/* RTC init function */
void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
I'm not 100% sure I know where to put the 2 lines you've recommended. Also what should I do with the Initialize RTC and Set Time and Date code starting at line 31? Do I need this if I'm setting up the clock in my code later?
Thanks,
Richard
2024-08-10 12:57 AM - edited 2024-08-10 12:59 AM
:)
I copied the " /* user code ... */ " lines, to show, where to insert this few lines.
Just put the 2x 2 lines in these user code areas, thats all.
This way you can use Cube to modify something and gen.code - and this will stay as before, because in user code area only.
Then the full init is done at first programming a chip, or removed the rtc battery, if RTC is not running at program start.
If RTC running, no init is done, so RTC keeping time and running, as expected.
You can read (or write ) time in your program then, as you like. (But never do "init" again, it will start the RTC with the default values and you loose actual time setting on every init you do, when clock was already running.)
2024-08-11 09:38 AM
AScha.3,
Here's my function with your two lines included:
void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
if((RCC->BDCR & 0x8000) == 0) // rtc enabled ? <-- this 2 lines
{
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
}
PWR->CR2 |= 0x01; // bren enable 2
/* USER CODE END RTC_Init 2 */
}
Something breaks when I run the code. When I try to set the time with:
if (HAL_RTC_SetTime(&hrtc, &rtcTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
The code falls into the Error_Handler. If I run the function without the two new lines the code runs fine. It resets the RTC so the values
aren't saved but that is normal since it is being reset again. Is there something else you can recommend that I try? Does it make
sense that those 2 lines break the function?
Thanks again,
Richard
2024-08-11 11:53 AM - edited 2024-08-11 11:54 AM
Now the best thing to do is not to use Cube at all, then you'll have full control over your code, and it can then be easily debugged just by having a look at the registers and into the RM.
The Cube functions apparently anticipate something to be set, which "normally" is set in HAL_RTC_Init(). Maybe you can still run that function, except I don't know (and I don't care to know) if it still does this.
You can also try to guess what's missing - one of the things is disabling the debug domain protection (by setting the DBP bit), @AScha.3 's last line is supposed to take care of that (check if it does so in your STM32 model), but maybe your STM32 has an RTC enable bit in RCC and then that needs to be set, too.
And, of course, you can simply debug Cube as your own code - it's open source - so just step through HAL_RTC_SetTime(), find out where does it return the error and why, and proceed accordingly.
It's probably obvious, that I don't use Cube/CubeMX.
JW
2024-08-11 01:15 PM
My code is on H743 , working since some months, showing time and date. But maybe on H7A3 something little bit different - I cannot try now, going to holiday. :)
Basically it should work, try to find out what is wrong now. Maybe Jan is right, need to insert/add something.
2024-08-12 08:12 AM
I got it working by only using half of what you originally suggested. This is what works (so far):
/* USER CODE BEGIN Check_RTC_BKUP */
if((RCC->BDCR & 0x8000) == 0) // rtc enabled ? <-- this 2 lines
{
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
}
PWR->CR2 |= 0x01; // bren enable 2
/* USER CODE END RTC_Init 2 */
}
I have reset the board multiple times and cycled the power multiple times and the clock data stays as programmed.
Thanks for your help. You saved me multiple hours.
Richard
2024-08-12 11:53 AM
Good !
Just - this is exactly as I ment, inserting the 2 lines at begin and at end of the init.
So you got it working now, as mine. :)