cancel
Showing results for 
Search instead for 
Did you mean: 

RTC calibration (STM32L011G4)

A L
Associate II
Posted on April 11, 2018 at 22:27

Hi there! - After looking around for quite a while, I'm still not exactly sure how to calibrate the RTC on my STM32L011G4 board. - For our project, we are using an external LSE crystal (768 kHz) for the RTC. - Do I need to use the RTC_SmoothCalib method (example for other MCU types), or is there another way to adjust the RTC accuracy? I have an accurate 1s clock source from a GPS module hooked up and counting rising edges with EXTI interrupt... That works nicely. But how could the number of LSE clock ticks happening between the external 1s pulses be counted to adjust the calibration registers? (RTC_CALR)There are only 2 timers, and no 32-bit one on the STM32L.. - Any help / hints would be appreciated. I'm simply overwhelmed by all the cryptic options described in the docs...

#rtc #rtc-calibration #lse #calibration #stm32l011g4 #stm32l0x1

Note: this post was migrated and contained many threaded conversations, some content may be missing.
20 REPLIES 20
Posted on April 12, 2018 at 08:11

It wouldn't work, as the lse is too coarse. Each count is 30ppm and you have to count sub cycle for this approach to be useful.

Or simply count for 30 seconds (the finest calibration step is just below one ppm).

JW

Steve Melnikoff
Associate III
Posted on April 12, 2018 at 10:42

If you're able to connect the 1PPS signal from the GPS to the RTC's timestamp input (RTC_TS), you can then gather timestamps from the RTC which you know to be precisely one second apart.

You can then adjust the RTC's calibration value such that the number of ticks between timestamps comes out to the frequency of ck_apre (which is output by the asynchronous prescaler).

By default, this is set to 256 Hz. However, if you to set the asynchronous predivider to zero, the synchronous one to 32759, and the initial calibration value to 0x100, following the instructions in the reference manual, it gives you much greater resolution, and hence better accuracy.

Posted on April 13, 2018 at 02:14

Thanks for the interesting hints Steve!

Just for the record: I was able to record time stamps by connecting the 1 PPS signal to RTC_TS (PA2 in my case). The HAL_RTCEx_TimeStampEventCallback() callback fires on every rising edge of the 1 PPS now, after enabling it with HAL_RTCEx_SetTimeStamp_IT().

Looking at the

http://www.st.com/resource/en/reference_manual/dm00108282.pdf

in the RTC section, I'm trying to understand how the RTC can actually be calibrated. I do see 2 important registers: RTC_CALR (which I initially though to be the main calibration register - only tested this once very briefly on another STM32 by writing extreme values into it), and RTC_PRER. I'm reading up on these now... /more on the insights later.
Posted on April 13, 2018 at 15:22

I'm still a bit confused, and don't understand all the options to use/calibrate the RTC peripheral in the STM32 yet.

So, to keep things simple for now: I simply accumulated the number of LSE cycles in the 1 PPS interrupt callback function for 32 seconds in total. And then I took the difference between the sum of the captured values and the expected number of LSE ticks (32 * 32768). - With my current test hardware, I get a 'cumulative error' of about -16 ticks. - This is less than a 30 ppm error, i.e. less than 1 LSE clock tick per second.

After that, I've tried to adjust the RTC with the 'Smooth Digital Calibration' method (RTC_CALR), by using this HAL function: HAL_RTCEx_SetSmoothCalib().

But For some reason I cannot see any difference, even when I use the calibration with maximum correction parameters like this (still -16 ticks):

HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_8SEC, RTC_SMOOTHCALIB_PLUSPULSES_SET, 0x000001FF);

However, after letting the board run for a couple of hours the RTC's error becomes visible like expected after using HAL_RTCEx_SetSmoothCalib() with maximum parameter. - I assume that the adjustments made by the 'smooth calibration block' are not visible yet after measuring for a such a short time...

Please correct me if I'm on the wrong track. - I plan to use a high frequency clock source later on.

Any hints to make the most simple calibration method work would be appreciated.

As a sidenote: This STM32L011 RTC test board is just a personal side-project of mine to learn more about the RTC and low-power modes of the STM32, later on. But I don't have a very accurate frequency counter at hand, for checking... - And I have only only basic understanding of all the peripherals.

Posted on April 13, 2018 at 16:07

You may want to read the data sheet and Hal user manual. The calibration registers is set to work over 20 bits (32 second) so it should kick in after 32 second. On the next 32 second measurement, the measurement should be more accurate and the error ticks should go down.

No idea what the right functions are to use for Hal.

Posted on April 14, 2018 at 18:13

Some more tests have been done...

When I understand you correctly, then you suggested that it is actually possible to use the SubSeconds field for calibration, because the two prescalers/dividers applied to the RTC clock source (that divide the 768 kHz in my case down to 1 second pulses for the calendar) are also used to update the sub second register (RTC_SSR). As described in the

/external-link.jspa?url=http%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Freference_manual%2Fdm00108pdf

(section 4.3 Clock and prescalers), the 'asynchronous prescaler' (ck_apre) generates the clock signal used by the SubSeconds counter, hence it increases in resolution by making that prescaler smaller (full input clock speed when equal to 1), and the synchronous prescaler (applied after first clock division by the asynchronous prescaler) larger, while making sure that the resulting 1 second interval for the actual RTC calender keeps exactly 1 second long.

To do this with HAL level code / STM32CubeMX, I will try to use the RTC initialization structure's AsynchPrediv / SynchPrediv fields for this:

hrtc.Instance = RTC;

hrtc.Init.HourFormat = RTC_HOURFORMAT_24;

hrtc.Init.AsynchPrediv = 127; // change this

hrtc.Init.SynchPrediv = 255; // change this

hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;

hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;

hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;

hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if (HAL_RTC_Init(&hrtc) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

Please correct me if I'm wrong.

After setting up the RTC time stamp capturing (with HAL_RTCEx_SetTimeStamp_IT() / HAL_RTCEx_TimeStampEventCallback()), the SubSecond field of the captured RTC time stamps can be used to measure the deviation of the LSE clock from the accurate 1 PPS signal.

I'm trying to do this right now...

Another observation made: I can only capture timestamps (with interrupts), after an RTC alarm has been triggered (HAL_RTC_SetAlarm_IT() / HAL_RTC_AlarmAEventCallback()). When I do not enable the alarm at all, no RTC timestamps are captured...

A L
Associate II
Posted on April 15, 2018 at 21:27

Ok. This has been quite bumpy a ride. But I think I've found a simple solution, a more general approach than trying to solve it with the limited ressource of the tiny L0.

So, here some notes for others to replicate this:

Since the

http://www.st.com/en/microcontrollers/stm32l011g4.html

does not include a 32-bit timer and since my test hardware has no accurate system clock source on the board (no HSE crystal, only LSE), and also has very limited amount of RAM/flash, I've decided to use another board for the calibration process that comes with those features. The

http://www.st.com/en/evaluation-tools/stm32f4discovery.html

in my case.

To make this work, both -- the accurate 1 PPS signal from the GPS module and the 1 Hz RTC calibration output from the target board (STM32L011) -- were connected to two channels of the TIM2 peripheral (32-bit timer) of the STM32F4, and configured in 'Input Capture direct mode' (PA1 -> TIM2_CH2 -> 1 PPS from GPS module / PA15 -> TIM2_CH1 -> RTC calibration output (1 Hz) from target board).

The short test program on the STM32F4 board first captures the number of internal clock ticks (at 25 MHz, driven by external 8 MHz crystal (HSE)) happening between the accurate 1 PPS (TIM2_CH2). After that, the program stops the Input Capture process on TIM2_CH2 and starts it on TIM2_CH1, to capture the clock ticks between the to-be-calibrated RTC 1 Hz output of the target board.

(While testing, I've noticed that quartz crystals are actually indeed much more stable/accurate RC oscillators; the measured clocks of an internal (16 MHz HSI) clock source were drifting around a lot. I think a stable/accurate high speed clock source is absolutely crucial for time calibration, it is almost impossible to calibrate the RTC on MCUs without a fast/stable clock as a reference...)

Currently the test output looks like that:

------------------------------

starting capturing process

starting to capture 1 PPS signal (GPS module)

000: captured ticks (1 PPS): 25001603

001: captured ticks (1 PPS): 25001604

002: captured ticks (1 PPS): 25001597

003: captured ticks (1 PPS): 25001593

004: captured ticks (1 PPS): 25001593

005: captured ticks (1 PPS): 25001594

006: captured ticks (1 PPS): 25001595

007: captured ticks (1 PPS): 25001595

008: captured ticks (1 PPS): 25001595

009: captured ticks (1 PPS): 25001597

average: 25001596.000000 ticks

starting to capture 1 Hz RTC calibration output (target)

000: captured ticks (RTC calib.): 24998275

001: captured ticks (RTC calib.): 24998278

002: captured ticks (RTC calib.): 24998277

003: captured ticks (RTC calib.): 24998279

004: captured ticks (RTC calib.): 24998281

005: captured ticks (RTC calib.): 24998275

006: captured ticks (RTC calib.): 24998281

007: captured ticks (RTC calib.): 24998284

008: captured ticks (RTC calib.): 24998281

009: captured ticks (RTC calib.): 24998283

average: 24998280.000000 ticks

capture process finished

RTC crystal runs too slow!

correction: 132.62033462524414062500 ppm

all done

------------------------------

Next up I have to calibrate the target board, and verify the result...

A L
Associate II
Posted on April 16, 2018 at 00:41

Alright, it finally seems to work. Now I just need to let it run for a longer time (hours/days) to see how accurate the calibration is... Thanks for the initial hints, it helped quite a bit.

Before the calibration it looks like this: it measures both clock sources for 32 seconds (+ ignored 5 seconds at the beginning of each measurement), compares the results, and calculates the correction value to be used in the Smooth Calibration register:

------------------------------

starting capturing process

starting to capture 1 PPS signal (GPS module)

000: captured ticks (1 PPS): 25001590

001: captured ticks (1 PPS): 25001591

002: captured ticks (1 PPS): 25001580

003: captured ticks (1 PPS): 25001580

004: captured ticks (1 PPS): 25001580

005: captured ticks (1 PPS): 25001581

006: captured ticks (1 PPS): 25001581

007: captured ticks (1 PPS): 25001582

008: captured ticks (1 PPS): 25001583

009: captured ticks (1 PPS): 25001583

010: captured ticks (1 PPS): 25001583

011: captured ticks (1 PPS): 25001584

012: captured ticks (1 PPS): 25001585

013: captured ticks (1 PPS): 25001586

014: captured ticks (1 PPS): 25001586

015: captured ticks (1 PPS): 25001587

016: captured ticks (1 PPS): 25001587

017: captured ticks (1 PPS): 25001588

018: captured ticks (1 PPS): 25001589

019: captured ticks (1 PPS): 25001589

020: captured ticks (1 PPS): 25001590

021: captured ticks (1 PPS): 25001591

022: captured ticks (1 PPS): 25001590

023: captured ticks (1 PPS): 25001579

024: captured ticks (1 PPS): 25001580

025: captured ticks (1 PPS): 25001581

026: captured ticks (1 PPS): 25001582

027: captured ticks (1 PPS): 25001582

028: captured ticks (1 PPS): 25001582

029: captured ticks (1 PPS): 25001584

030: captured ticks (1 PPS): 25001584

031: captured ticks (1 PPS): 25001585

average: 25001584.000000 ticks

starting to capture 1 Hz RTC calibration output (target)

000: captured ticks (RTC calib.): 24998260

001: captured ticks (RTC calib.): 24998259

002: captured ticks (RTC calib.): 24998259

003: captured ticks (RTC calib.): 24998261

004: captured ticks (RTC calib.): 24998262

005: captured ticks (RTC calib.): 24998262

006: captured ticks (RTC calib.): 24998249

007: captured ticks (RTC calib.): 24998251

008: captured ticks (RTC calib.): 24998252

009: captured ticks (RTC calib.): 24998251

010: captured ticks (RTC calib.): 24998253

011: captured ticks (RTC calib.): 24998252

012: captured ticks (RTC calib.): 24998256

013: captured ticks (RTC calib.): 24998255

014: captured ticks (RTC calib.): 24998255

015: captured ticks (RTC calib.): 24998256

016: captured ticks (RTC calib.): 24998257

017: captured ticks (RTC calib.): 24998258

018: captured ticks (RTC calib.): 24998259

019: captured ticks (RTC calib.): 24998259

020: captured ticks (RTC calib.): 24998258

021: captured ticks (RTC calib.): 24998260

022: captured ticks (RTC calib.): 24998260

023: captured ticks (RTC calib.): 24998261

024: captured ticks (RTC calib.): 24998263

025: captured ticks (RTC calib.): 24998263

026: captured ticks (RTC calib.): 24998252

027: captured ticks (RTC calib.): 24998252

028: captured ticks (RTC calib.): 24998256

029: captured ticks (RTC calib.): 24998248

030: captured ticks (RTC calib.): 24998254

031: captured ticks (RTC calib.): 24998254

average: 24998256.000000 ticks

capture process finished

correction factor:

24998256.000000 / 25001584.000000 =

0.99986690282821655273

RTC crystal runs too slow!

correction: -133.09716796875000000000 ppm

correction value (ticks +/- 32 s interval):

MINUS 140

use this on the target:

HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC, RTC_SMOOTHCALIB_PLUSPULSES_RESET, 140);

all done

------------------------------

And after the calibration:

------------------------------

starting capturing process

starting to capture 1 PPS signal (GPS module)

000: captured ticks (1 PPS): 25001590

001: captured ticks (1 PPS): 25001590

002: captured ticks (1 PPS): 25001588

003: captured ticks (1 PPS): 25001579

004: captured ticks (1 PPS): 25001581

005: captured ticks (1 PPS): 25001581

006: captured ticks (1 PPS): 25001581

007: captured ticks (1 PPS): 25001582

008: captured ticks (1 PPS): 25001582

009: captured ticks (1 PPS): 25001583

010: captured ticks (1 PPS): 25001584

011: captured ticks (1 PPS): 25001584

012: captured ticks (1 PPS): 25001585

013: captured ticks (1 PPS): 25001586

014: captured ticks (1 PPS): 25001586

015: captured ticks (1 PPS): 25001587

016: captured ticks (1 PPS): 25001588

017: captured ticks (1 PPS): 25001588

018: captured ticks (1 PPS): 25001588

019: captured ticks (1 PPS): 25001589

020: captured ticks (1 PPS): 25001590

021: captured ticks (1 PPS): 25001590

022: captured ticks (1 PPS): 25001587

023: captured ticks (1 PPS): 25001578

024: captured ticks (1 PPS): 25001580

025: captured ticks (1 PPS): 25001580

026: captured ticks (1 PPS): 25001580

027: captured ticks (1 PPS): 25001581

028: captured ticks (1 PPS): 25001582

029: captured ticks (1 PPS): 25001582

030: captured ticks (1 PPS): 25001583

031: captured ticks (1 PPS): 25001583

average: 25001584.000000 ticks

starting to capture 1 Hz RTC calibration output (target)

000: captured ticks (RTC calib.): 25001310

001: captured ticks (RTC calib.): 25002073

002: captured ticks (RTC calib.): 25001310

003: captured ticks (RTC calib.): 25002074

004: captured ticks (RTC calib.): 25001311

005: captured ticks (RTC calib.): 25001313

006: captured ticks (RTC calib.): 25001312

007: captured ticks (RTC calib.): 25002076

008: captured ticks (RTC calib.): 25001301

009: captured ticks (RTC calib.): 25002065

010: captured ticks (RTC calib.): 25001302

011: captured ticks (RTC calib.): 25002066

012: captured ticks (RTC calib.): 25001304

013: captured ticks (RTC calib.): 25001304

014: captured ticks (RTC calib.): 25001306

015: captured ticks (RTC calib.): 25002069

016: captured ticks (RTC calib.): 25001306

017: captured ticks (RTC calib.): 25002070

018: captured ticks (RTC calib.): 25001309

019: captured ticks (RTC calib.): 25002071

020: captured ticks (RTC calib.): 25001309

021: captured ticks (RTC calib.): 25001310

022: captured ticks (RTC calib.): 25001310

023: captured ticks (RTC calib.): 25002074

024: captured ticks (RTC calib.): 25001312

025: captured ticks (RTC calib.): 25002075

026: captured ticks (RTC calib.): 25001312

027: captured ticks (RTC calib.): 25002078

028: captured ticks (RTC calib.): 25001303

029: captured ticks (RTC calib.): 25001302

030: captured ticks (RTC calib.): 25001304

031: captured ticks (RTC calib.): 25002065

average: 25001594.000000 ticks

capture process finished

correction factor:

25001594.000000 / 25001584.000000 =

1.00000035762786865234

RTC crystal runs too fast!

correction: -0.35762786865234375000 ppm

calibration complete! NO FURTHER CORRECTION REQUIRED

all done

------------------------------

TODO: Update RTC Smooth Calibration parameters on the fly, while the microcontroller is running, with the same technique...

Posted on April 16, 2018 at 00:47

 ,

 ,

the measured clocks of an internal (16 MHz HSI) clock source was drifting around a lot. I think a stable/accurate high speed clock source is absolutely crucial for time calibration, so I think it is almost impossible to calibrate the RTC on MCUs without a fast/stable clock as a reference...

For a

https://community.st.com/0D70X000006SwQbSAK

with similar motivation I concocted a demo to measure internal oscillators against LSE, and the finding was, not surprisingly, similar.

132ppm deviation for a 32.768kHz crystal sounds a wee bit more than it should be - the poorest quality crystals should be up to 100ppm. Make sure the loading capacitors are properly calculated (see ), and that the crystal surroundings is as RF-quiet as possible (which includes but is not limited to very short leads to the crystal and capacitors and careful grounding arrangement).

JW

Posted on April 16, 2018 at 01:12

Thanks for the hint JW! Nice to read more on a similar topic in the other thread, I have a lot to learn about how to use the STM32 peripherals properly...

waclawek.jan wrote:

132ppm deviation for a 32.768kHz crystal sounds a wee bit more than it should be - the poorest quality crystals should be up to 100ppm. Make sure the loading capacitors are properly calculated (see ), and that the crystal surroundings is as RF-quiet as possible (which includes but is not limited to very short leads to the crystal and capacitors and careful grounding arrangement).

Interesting, yes, I actually had problems with those RTC 32.768 kHz crystals before... On another project (using an STM32F7x) I needed to replace the loading capacitors multiple times to get the oscillator running. I also tried to tweak things with STM32CubeMX in the RCC settings (LSE_Drive_Capability, LSE Startup Timout Value), but it only started to resonate with very 'unusual' caps of 2 x 2.7 pF, a

https://abracon.com/Resonators/ABS07-120-32.768kHz-T.pdf

by Abracon was used in both projects. The MCU didn't even want to start executing code when wrong caps were installed, even the LSE wasn't used... Strange. - I do not understand this in great detail, tried to read more on how to calculate trace widths, caps etc. But I still needed to do things by trial'n'error at the end... ;p

Edit: IIRC there's quite a lot of useful info on this topic in this app note:

http://www.st.com/content/ccc/resource/technical/document/application_note/c6/eb/5e/11/e3/69/43/eb/CD00221665.pdf/files/CD00221665.pdf/jcr:content/translations/en.CD00221665.pdf