Calibration of stm32f103 clock

Post here first, or if you can't find a relevant section!
Post Reply
User avatar
k008
Posts: 15
Joined: Sat Apr 29, 2023 5:19 pm

Calibration of stm32f103 clock

Post by k008 »

Tell me how to calibrate the clock in stm32f103.
Now I work like this:

Code: Select all

#include <STM32RTC.h>
STM32RTC& rtc = STM32RTC::getInstance();
setup() {
rtc.setClockSource(STM32RTC::LSE_CLOCK);
rtc.begin(); // initialize RTC 24H format
}
Calibration and initialization seem to be done like this:

Code: Select all

if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN) //Check the clock, if not enabled, then initialize
{
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; //Enable PWR and Backup clocking
PWR->CR |= PWR_CR_DBP; //Allow access to Backup area
RCC->BDCR |= RCC_BDCR_BDRST; //Reset Backup area
RCC->BDCR &= ~RCC_BDCR_BDRST;
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE; //Select LSE source (quartz 32768) and apply clocking
RCC->BDCR |= RCC_BDCR_LSEON; //Enable LSE
while ((RCC->BDCR & RCC_BDCR_LSEON) != RCC_BDCR_LSEON){} //Wait for power-on
BKP->RTCCR |= 3; //RCC calibration
while (!(RTC->CRL & RTC_CRL_RTOFF)); //check if RTC register changes are finished
RTC->CRL |= RTC_CRL_CNF; //Enable writing to RTC registers
RTC->PRLL = 0x7FFF; //Set the divider to 32768 (32767+1)
BKP->RTCCR |= BKP_RTCCR_CCO; //Enable the Temper pin
RTC->CRL &= ~RTC_CRL_CNF; //Disable writing to RTC registers
while (!(RTC->CRL & RTC_CRL_RTOFF)); //Wait for writing to finish
RTC->CRL &= (uint16_t)~RTC_CRL_RSF; //Synchronize RTC
while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){} //Wait for synchronization
PWR->CR &= ~PWR_CR_DBP; //prohibit access to Backup area
}
But what is the correct way to do calibration if you use STM32RTC.h?
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: Calibration of stm32f103 clock

Post by STM32ardui »

k008 wrote: Sun Oct 06, 2024 6:59 am But what is the correct way to do calibration if you use STM32RTC.h?
STM32RTC-libaray can't do it by itself.

You have to use getHandle() and then use this handle in HAL_RTCEx_SetSmoothCalib().
User avatar
k008
Posts: 15
Joined: Sat Apr 29, 2023 5:19 pm

Re: Calibration of stm32f103 clock

Post by k008 »

And the code I gave above won't work?
Can you show an example of how you propose to do it?
Also, clarify the order of using the library and calibration. That is, at what point, which registers can be edited. Can I initialize the clock, and then do the calibration or should this be done immediately at the time of initialization?
STM32ardui
Posts: 142
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: Calibration of stm32f103 clock

Post by STM32ardui »

I don't used registers directly. So I can't say, if your example works or not. Have you tried it?

My code is like this:

Code: Select all

#include <STM32RTC.h>
#include <stm32g0xx_hal_rcc_ex.h>

uint8_t  ret;         
STM32RTC& rtc = STM32RTC::getInstance();

void setup() {
  rtc.setClockSource(STM32RTC::LSE_CLOCK);
  rtc.begin(false,STM32RTC::HOUR_24);
  RTC_HandleTypeDef hrtc = *rtc.getHandle();

  ret = HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC, RTC_SMOOTHCALIB_PLUSPULSES_SET, 493);
}
I used it on a STM32G0B1CBT6 and let it run for 24 hours and changed value for CALM until I had better accuracy.
ag123
Posts: 1898
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: Calibration of stm32f103 clock

Post by ag123 »

well, there is an appnote for it
https://www.st.com/resource/en/applicat ... ronics.pdf

And of course cross reference the ref manual rm0008.

That would help more than anyone here who may not have tried it before.
'calibration' is probably an 'incorrect' term, adjustments more like it. There are limits to how much you can adjust with the registers.
With badly out of sync 32k crystals some from Ebay, Aliexpress etc, those can drift by minutes a day, not seconds per month.
there are some codes for doing big adjustments, but that you would need to port it yourself over if you want to use it.
https://github.com/rogerclarkmelbourne/ ... /RTCAdjust

a 'simple' way is to get *good* accurate crystals or chip oscillators maybe from epson etc, probably won't need any 'adjustments' (ever).
https://www.epsondevice.com/crystal/en/ ... ator/tcxo/
32768 hz is a fixed number, chip oscillators made for purpose possibly 'guarantees' it with a small variation.
cheap lousy crystals and oscillators can give you like 10khz to 60khz in a random sample and sold to you as 32768 hz, they didn't bother, you can go ahead and adjust whatever you need.

'adjustment' is a simple concept, if the clock drifts 1 minute faster a month, then simply subtract that much every month (and vice versa). probably won't need any special purpose registers etc to do that. ;)
User avatar
k008
Posts: 15
Joined: Sat Apr 29, 2023 5:19 pm

Re: Calibration of stm32f103 clock

Post by k008 »

ag123 wrote: Tue Oct 08, 2024 7:29 am well, there is an appnote for it
https://www.st.com/resource/en/applicat ... ronics.pdf

And of course cross reference the ref manual rm0008.
It is based on this guide that I provided the code in the first post, the question is how to use it correctly
'adjustment' is a simple concept, if the clock drifts 1 minute faster a month, then simply subtract that much every month (and vice versa). probably won't need any special purpose registers etc to do that. ;)
when the watch runs on battery, the brain can't think, bad option
STM32ardui wrote: Tue Oct 08, 2024 5:30 am I used it on a STM32G0B1CBT6 and let it run for 24 hours and changed value for CALM until I had better accuracy.
your option is not suitable for stm32f103
ag123
Posts: 1898
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: Calibration of stm32f103 clock

Post by ag123 »

k008 wrote: Sat Oct 12, 2024 7:02 am
ag123 wrote: Tue Oct 08, 2024 7:29 am well, there is an appnote for it
https://www.st.com/resource/en/applicat ... ronics.pdf

And of course cross reference the ref manual rm0008.
It is based on this guide that I provided the code in the first post, the question is how to use it correctly
AN2604 STM32F101xx and STM32F103xx RTC calibration
https://www.st.com/resource/en/applicat ... ronics.pdf
The digital calibration circuit removes 0 to 127 cycles every 2 ^ 20 clock cycles (see Figure 2.).

CAL[6:0]bits in BKP_RTCCR register

Table 1: ...
well, apparently the value in BKP_RTCCR simply slows down the LSE value (lets say 32768 hz) according to the value in BKP_RTCCR register.
Hence, say if you have a crystal that runs 200 seconds too fast each month, look in table 1 that calibration value should be 17.
Hence, store 17 in BKP_RTCCR. That would slow down the RTC by 200 seconds each month.

There are some specific requirements for accessing the backup registers, those should be covered in RM0008.

This concept isn't too different from say to use some simple codes to do this same adjustment, say with some variables. Just that it is 'hardware assisted'. Hence, you won't need to do that in program codes.
Last edited by ag123 on Sat Oct 12, 2024 9:35 am, edited 1 time in total.
User avatar
k008
Posts: 15
Joined: Sat Apr 29, 2023 5:19 pm

Re: Calibration of stm32f103 clock

Post by k008 »

That's the thing, the code calibrates the pointer upwards, here are the lines that control the quartz frequency and the additional coefficient to calculate the time faster.

And the question is exactly how to combine the simplicity of the RTC library control and the given code. As far as I understand, the RTC does approximately the same thing during initialization as the calibration code, so it is impossible to use the library and calibration together. Perhaps you can tell me how to do this correctly
BKP->RTCCR |= 3; //RCC calibration
RTC->PRLL = 0x7FFF; //Set the divider to 32768 (32767+1)
ag123
Posts: 1898
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: Calibration of stm32f103 clock

Post by ag123 »

I've not used this yet, but assuming
you are using STM32RTC
after you run the setup() codes, e.g.
https://github.com/stm32duino/STM32RTC/ ... pleRTC.ino

Code: Select all

void setup()
{
  Serial.begin(9600);

  // Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
  // By default the LSI is selected as source.
  //rtc.setClockSource(STM32RTC::LSE_CLOCK);

  rtc.begin(); // initialize RTC 24H format

  // Set the time
  rtc.setHours(hours);
  rtc.setMinutes(minutes);
  rtc.setSeconds(seconds);

  // Set the date
  rtc.setWeekDay(weekDay);
  rtc.setDay(day);
  rtc.setMonth(month);
  rtc.setYear(year);

  // you can use also
  //rtc.setTime(hours, minutes, seconds);
  //rtc.setDate(weekDay, day, month, year);
}
my guess is that you can add your register tweaks after those codes run.
if you reset the device between the RTC setup runs, you would also need to figure out some way to skip initialization if RTC is already running.
Alternatively, as the source codes is in the repository, you can make changes to the local copy of the source codes.
Post Reply

Return to “General discussion”