cancel
Showing results for 
Search instead for 
Did you mean: 

Hi! I use STM32L051 RTC and twice during three days at +55 deg.C I have incorrect reading of time. For a 1 minute RTC counts 3599.87 s, at next minute all works as should be - 1 min after spending 1 min. Sometimes I get 62.7 s by 1 minute. Thanks.

MZubk
Associate
// in 1/32768 parts of second, 1 hour (3600*32768) max.
uint32_t cRTC::getCurrentTime32768(){
	volatile uint32_t time = 0;
	volatile uint16_t takenTime = 0;
	volatile uint16_t takenSSR;
	volatile uint16_t dummy;
 
	//reading either RTC_SSR or RTC_TR locks the values in the higher-order calendar shadow registers
	// until RTC_DR is read! Locking ensure consistency of readden data.
 
	awaitShadowRegUpdate();
	takenTime = (uint16_t)RTC->TR;
 
	awaitShadowRegUpdate();
	takenSSR = (uint16_t)RTC->SSR;
 
	awaitShadowRegUpdate();
	dummy = (uint16_t)RTC->DR;
 
	time = ( ( (takenTime  &  0xF0) >> 4 ) * 10 ) + (takenTime & 0xF); // seconds
	time += 60 * ( ( ( (takenTime & 0xF000) >> 12 ) * 10 ) + ( (takenTime & 0xF00) >> 8 ) ); // minutes
	time = (time*32768) + (32767 - takenSSR);
  return time;
}
uint32_t cRTC::spentTime32768(uint32_t* startTime){ // with update startTime automatically
	volatile uint32_t spent = 0;
	volatile uint32_t currentTime = cRTC::getCurrentTime32768();
 
	if(currentTime >= *startTime){
		spent = currentTime - *startTime;
	} else {
		spent = currentTime + ((3600*32768) - *startTime);
	}
 
	*startTime = currentTime;
 
	return spent;
}
extern "C" void EXTI2_3_IRQHandler(void){
		if(READ_BIT(EXTI->RTSR, EXTI_RTSR_TR2)) {// catched rising edge
			EXTI->RTSR &= ~EXTI_RTSR_TR2; // Disable rising Trigger
			EXTI->FTSR |=  EXTI_FTSR_TR2; // Enable falling Trigger
 
			motorStartTime = cRTC::getCurrentTime32768();
			motorIsON = true;
		}
		else {
			EXTI->FTSR &= ~EXTI_FTSR_TR2; // Disable falling Trigger
			EXTI->RTSR |=  EXTI_RTSR_TR2; // Enable rising Trigger
 
			int32_t lastMotorSec = cRTC::spentTime32768(motorStartTime);
			motorIsON = false;
		}
 
  EXTI->PR |= EXTI_PR_PR2; // Clear Pending Interrupt Flag by writing 1 (PA2)
}

3 REPLIES 3
TDK
Guru

Read each value twice or more until they are all the same on consecutive readings to ensure consistent results.

https://www.st.com/resource/en/errata_sheet/es0251-stm32l05xxxl06xxx-device-errata-stmicroelectronics.pdf

What does awaitShadowRegUpdate do here?

If you feel a post has answered your question, please click "Accept as Solution".

Some complete, stand-alone, compilable code, with dumps of the registers, and final computations would go a long way to getting anyone interested in this.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thank You TDK, now I know that shadow registers can be updated unconsistently. Now I use BYPSHAD=1 and read twice each register and compare each, up to 10 times to get equal content. Now I testing my code.