2022-11-02 12:55 PM
Hi STM32F103 Programmers
I am fighting with my RTC. I have it working but have problems with accessing the Alarm registers for the second time. I can't find the reason why I can't.
I program the RTC direct using Bit fields and when needed register bit shift operations That works quite well till now and I do it on various peripherals without a problem. I have mapped all peripherals on structs with uint32_t members and assigned all bits to these registers.
I develop this code on the VSC for the STM32F103.
The code for configuring the RTC is working, It accesses the CNT and the ALR registers with no problem. All bits to access the RTC are configured DBP, RTOFF, RTCEN....... This is the code
void RTC_Config() {
RCC_PRB *PRCC = (RCC_PRB*)RCC_BASE; // Map the Periferals structs to the addresses of the periferals
PWR_PRB *PPWR = (PWR_PRB*)PWR_BASE;
RTC_PRB *PRTC = (RTC_PRB*)RTC_BASE;
NVIC_PRB *PNVIC = (NVIC_PRB*)NVIC_BASE;
BKP_PRB *PBKP = (BKP_PRB*)BKP_BASE;
uint32_t PRL_Div, TRclk, RTclk=1; // RTclk=1sec
//__NVIC_EnableIRQ(EXTI0_IRQn);
//PNVIC->ISER0.RTC_IRQ = 0x01; // Enable global RTC_IRQn;
//PNVIC->IPR0.RTC_PRI = 0x01; // Set the RTC_IRQn Interupt priority
//PNVIC->ISER1.RTC_Alarm_IRQ = 0x01; // Enable RTC_ALARM_IRQ;
//NVIC_SetPriority (RTC_IRQn, 10);
//NVIC_EnableIRQ(RTC_IRQn);
//RCC->APB1ENR |= RCC_APB1ENR_BKPEN;
PRCC->APB1ENR.PWREN= 0x01; // Enable clock PWR register block
PRCC->APB1ENR.BKPEN= 0x01; // Enable clock backup Register block
PPWR->CR.DBP = 0x01; // Disable backup domain write protection DBP=1
PRCC->BDCR.RTCEN = 0x01; // Enable the RTC Clock
STM32_Config();
PBKP->RTCCR.CAL = 0x00; // Calibrate RC Oscilator if needed;
PRCC->BDCR.LSEON = 0x01; // Enable LSE Clock
while (PRCC->BDCR.LSERDY==0x00); // Readonly flag, LSEBYP=1 LSE clock is ready
PRCC->BDCR.RTCSEL = 0x01; // set clock as LSE 32.768 kHz, Ones selected RTCEL is locked.
PRTC->CRL.RSF = 0x00; // Clear RSF Registers Synchronized Flag bit by writing a zero.
while( PRTC->CRL.RSF == 0x00) delay(1); // test RSflag=1, at low LSE frequencies 50hz it can take up to a minute. Weird delay(1) is needed otherwise it hangs
//while( (RTC->CRL & RTC_CRL_RSF) == 0x00); // test RSflag=1, at low LSE frequencies 50hz it can take up to a minute. Weird works without delay(1)
while( PRTC->CRL.RTOFF==0x00); // All registers are loaded RTOFF=1
PRTC->CRL.CNF = 0x01; // Enter Configuration Mode CNF=1
//PRTC->CRH.SECIE = 0x01; // Enable second Interupt;
//PRTC->CRH.ALRIE = 0x01; // Enable Alarm Interupt;
switch(PRCC->BDCR.RTCSEL) {
case 0b00 : { TRclk=0; } break; // No Clock selected
case 0b01 : { TRclk=32768; } break; // TRclk=extrenal LS Xtal value
case 0b10 : { TRclk=40000; } break; // Uncalibrated RC clock value. Calibration possible.
case 0b11 : { TRclk=HSE_VALUE>>7;} break; // TRclk=HSE/128 = 8E6/128 = 62500
default : {} ;
}
PRL_Div= (uint32_t)(((float)TRclk/(float)RTclk)+0.5);
PRTC->PRLH.PRL = (PRL_Div-1)>>16; // High bits [19:16], PRLvalue = Div-1
PRTC->PRLL.PRL = (PRL_Div-1) & 0xFFFF; // Low bits [15:00], PRLvalue = Div-1
PRTC->CNTH.CNT = 0x0023; // Load CNTH with current EPOCH value otr 0x00
PRTC->CNTL.CNT = 0xFFF8; // Load CNTL with current EPOCH value otr 0x00
PRTC->ALRH.ALR = 0x0024; // Set the Alarm Flag High
PRTC->ALRL.ALR = 0x0005; // Set the Alarm Flag Low
delay(1);
PRTC->CRL.CNF = 0x00; // Leave the Configuration Mode, Write registyer Cycle starts
while( PRTC->CRL.RTOFF==0x00); // Test if All registers are loaded RTOFF=1
}
I also have an interrupt routine which I don't use as an interrupt routine yet. I call it from the main loop. All RTC related interrupt masks are off.
void RTC_IRQHandler(void) {
RTC_PRB *PRTC = (RTC_PRB*)RTC_BASE;
PWR_PRB *PPWR = (PWR_PRB*)PWR_BASE;
if( PRTC->CRL.SECF==0x01) { PRTC->CRL.SECF=0x00; printf("S."); }
if( PRTC->CRL.ALRF==0x01) {
PRTC->CRL.ALRF=0x00;
printf("A%u.", PPWR->CR.DBP);
while( PRTC->CRL.RTOFF==0x00);
PRTC->CRL.CNF = 0x01;
PRTC->ALRH.ALR = 0x0024; // Set the Alarm Flag High
PRTC->ALRL.ALR = 0x0020;
PRTC->CRL.CNF = 0x00;
delay(1);
while( PRTC->CRL.RTOFF==0x00);
} // Reset the Sec Interrupt flag
if( PRTC->CRL.OWF ==0x01) { PRTC->CRL.OWF =0x00; printf("O."); }
while( PRTC->CRL.RTOFF==0x00);
}
I can read access the CNT and ALM and CR registers with no problem. The CNT is counting up per second. When the alarm goes off and it does, this Int routine is called and it should config the alarms to a new value. It doesn't do that. I have no idea why. I tested access to the alarm registers in other ways but with no success.
Can anyone help me why I can't access my alarm registers for the second and third..... time.
Thanks