cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F050G4 RTC Alarm Problems

BenMack99
Senior
Posted on October 31, 2013 at 09:23

Hi All, a couple of questions about the RTC Alarm. I have got the RTC Alarm working (using LSI), and raising an interrupt (RTC_IRQHandler()) successfully, but I'm stuck on the following:-

1) I would like an alarm once a second, so I can put the core in stop mode, and have it wake up once a second. The reference manual implies that if I set the ALRMASSR MASKSS to zero, and set all the ALRMAR MSK bits, then I should get an interrupt once a second, but I don't. I used RTC->ALRMAR = 0x80808080; RTC->ALRMASSR = 0x00000000; 2) Whilst I can set RTC->ALRMAR in the first place, I cannot modify it within RTC_IRQHandler() for the next alarm. I'm disabling WPR. I have attached my test code below. You'll notice the debug vars ben1, ben2, ben3 - if I pause a few seconds after the first alarm interrupt, ben2 (ALRMAR) is still 0x80808 You'll notice from commented code that I also tried the library functions for setting the alarm, and even tried RTC_EnterInitMode(), same problem. Any suggestions?

#include ''stm32f0xx.h''
#include ''stm32f0xx_gpio.h''
#include ''stm32f0xx_rcc.h''
#include ''stm32f0xx_pwr.h''
#include ''stm32f0xx_rtc.h''
#include ''stm32f0xx_exti.h''
#include ''stm32f0xx_misc.h''
#define PORT_LED GPIOB
#define PIN_LED_G GPIO_Pin_6
#define PIN_LED_R GPIO_Pin_7
#define LED_G_ON GPIOB->BSRR=PIN_LED_G
#define LED_G_OFF GPIOB->BRR=PIN_LED_G
#define LED_G_TOGGLE GPIOB->ODR ^= PIN_LED_G
#define LED_R_ON GPIOB->BSRR=PIN_LED_R
#define LED_R_OFF GPIOB->BRR=PIN_LED_R
#define LED_R_TOGGLE GPIOB->ODR ^= PIN_LED_R
uint32_t ben1, ben2, ben3;
int
main(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
RTC_InitTypeDef RTC_InitStructure;
//RTC_TimeTypeDef RTC_TimeStructure;
//RTC_TimeTypeDef bentemp_rtc;
//ErrorStatus benerrorstatus;
//uint32_t benui32;
// Outputs Port B
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = PIN_LED_G | PIN_LED_R;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Init RTC Clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 
// Enable the PWR clock
PWR_BackupAccessCmd(ENABLE); 
// Enable access to the Backup domain registers (PWR->CR |= PWR_CR_DBP;)
RCC_LSICmd(ENABLE); 
// Enable the LSI OSC
while
(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); 
// and wait until ready
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); 
// Set RTC clock source to LSI (RCC->BDCR |= RCC_RTCCLKSource_LSI;) must set PWR_CR_DBP first
RCC_RTCCLKCmd(ENABLE); 
// Enable RTC Clock (RCC->BDCR |= RCC_BDCR_RTCEN;)
RTC_WaitForSynchro(); 
// Wait for RTC APB registers synchronisation
// Set RTC prescaler register RTC_PRER
RTC_InitStructure.RTC_AsynchPrediv = 99;
RTC_InitStructure.RTC_SynchPrediv = 399; 
/* (40KHz / 100) - 1 = 399*/
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
// Init RTC time register
// ben note the RTC_SetTime() function doesn't appear to work...
RTC->WPR = 0xCA; 
// Disable the write protection for RTC registers
RTC->WPR = 0x53; 
// ditto
RTC_EnterInitMode(); 
// Enter initialisation mode
RTC->TR = (uint32_t)0x00000000; 
// Set the RTC_TR register
RTC->ISR &= ~RTC_ISR_INIT; 
// Exit initialisation mode
RTC->WPR = 0xFF; 
// Enable the write protection for RTC registers
// Init EXTI line 17
EXTI->RTSR |= EXTI_IMR_MR17; 
// set rising edge bit
EXTI->IMR |= EXTI_IMR_MR17; 
// set interrupt mask bit
// Enable the RTC Interrupt
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// Set RTC alarm
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
RTC->ALRMAR = 0x80808005; 
// MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=0 ST=0 SU=5 secs
//RTC->ALRMAR = 0x80808080; // MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=1(ignore seconds)
//RTC->ALRMASSR = 0x00000000; // MASKSS=0 so the alarm is set when the seconds unit is incremented
RTC->CR |= RTC_CR_ALRAIE; 
// enable alarm interrupt ben was RTC_ITConfig(RTC_IT_ALRA, ENABLE);
RTC->CR |= RTC_CR_ALRAE; 
// enable alarm
RTC->WPR = 0xFF;
// and finally clear any pending interrupts
RTC_ClearITPendingBit(RTC_IT_ALRA);
EXTI_ClearITPendingBit(EXTI_Line17);
while
(1)
{
ben1 = RTC->TR;
ben2 = RTC->ALRMAR;
}
}
void
RTC_IRQHandler(
void
)
{
LED_G_TOGGLE;
/*
// set next alarm
RTC_WaitForSynchro(); //ben only if we read TR -
//uint32_t fred = RTC->ALRMAR & 0x0000007F;
uint32_t fred = RTC->TR & 0x0000007F;
fred += 5;
if (fred > 59)
fred = 0;
ben3 = fred;
*/
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
//RTC->ALRMAR = 0x80808000 | fred; // MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=0 ST/U = fred secs
RTC->ALRMAR = 0x80808009; 
// MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=0 ST/U = fred secs
RTC->WPR = 0xFF;
/* RTC_WriteProtectionCmd(DISABLE);
RTC_EnterInitMode();
//RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &alarm);
RTC->ALRMAR = 0x80808009; // MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=0 ST/U = fred secs
RTC_WriteProtectionCmd(ENABLE);
RTC_ExitInitMode();
*/
RTC_ClearITPendingBit(RTC_IT_ALRA);
EXTI_ClearITPendingBit(EXTI_Line17);
}

#stm32 #wakeup #rtc #timer
8 REPLIES 8
BenMack99
Senior
Posted on October 31, 2013 at 10:09

The plot thickens....   I've just discovered I am only able to set the alarm registers the first time I run the code after power-cycling the board, so I am clearly not initialising something correctly.   I have modified my init code (see below) so I set the alarm registers at the same time as TR, still the same. If I tweak values (e.g. ALRMAR 0x80808081)

and run again (either in debug mode or just loading straight to flash) I don't see the new value until I power-cycle the board.   A clue is that I couldn't get RTC_SetTime() to work in the first place, hence writing my own init code...   RTC->WPR = 0xCA;

// Disable the write protection for RTC registers

RTC->WPR = 0x53;

// ditto

RTC_EnterInitMode();

// Enter initialisation mode

RTC->TR = (uint32_t)0x00000000;

// Set the RTC_TR register

RTC->ALRMAR = 0x80808080;

// MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=1(ignore seconds)

RTC->ALRMASSR = 0x0F000000;

// MASKSS=15 so the alarm is set when SS == 0

RTC->CR |= RTC_CR_ALRAIE;

// enable alarm interrupt ben was RTC_ITConfig(RTC_IT_ALRA, ENABLE);

RTC->CR |= RTC_CR_ALRAE;

// enable alarm

RTC->ISR &= ~RTC_ISR_INIT;

// Exit initialisation mode

RTC->WPR = 0xFF;

// Enable the write protection for RTC registers  

BenMack99
Senior
Posted on October 31, 2013 at 10:19

Well at least I have answered my question 1) - I do indeed get a 1Hz interrupt with

RTC->ALRMAR = 0x80808080;

RTC->ALRMASSR = 0x00000000;

I'm guessing my init problem is that I should be resetting the backup domain at start-up? Any tips welcome, in the meantime back to reading the manual to see what I have missed....
BenMack99
Senior
Posted on November 06, 2013 at 14:06

Well I've tried a backup domain reset, still no joy. I've read the ref manual many times, still can't work it out. I simply cannot set ALRMAR except straight after a power-cycle.

Any ideas, anyone???

Posted on November 06, 2013 at 14:47

Just a blind shot: add

PWR_BackupAccessCmd(ENABLE); 
// Enable access to the Backup domain registers (PWR->CR |= PWR_CR_DBP;)

also into the ISR? JW
BenMack99
Senior
Posted on November 06, 2013 at 19:35

Hi, thanks for the response

I'm calling PWR_BackupAccessCmd(ENABLE); at the start of configuring the RTC I'm calling RTC_EnterInitMode() to set the ISR Here's my current code, works fine at power-up, but doesn't set ALRMAR if called during normal operation (and ALRMAR has been set to a different value at power-up)

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Enable the PWR clock
PWR_BackupAccessCmd(ENABLE); // Enable access to the Backup domain registers
RCC_LSICmd(ENABLE); // Enable the LSI OSC
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); // and wait until ready
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // Set RTC clock source to LSI
RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock 
RTC_WaitForSynchro(); // Wait for RTC APB registers synchronisation
// Set RTC prescaler register RTC_PRER
RTC_InitStructure.RTC_AsynchPrediv = 99;
RTC_InitStructure.RTC_SynchPrediv = 399; /* (40KHz / 100) - 1 = 399*/
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
// Init RTC time register
RTC->WPR = 0xCA; // Disable the write protection for RTC registers
RTC->WPR = 0x53; // ditto
RTC_EnterInitMode(); // Enter initialisation mode
RTC->TR = (uint32_t)0x00000035; // Set the RTC_TR register
RTC->ALRMAR = 0x80808080; // MSK4=1(ignore day/date), MSK3=1(ignore hours), MSK2=1(ignore minutes), MSK1=1(ignore seconds)
RTC->ALRMASSR = 0x00000000; // MASKSS=0 so the alarm is set when the seconds unit is incremented
RTC->CR |= RTC_CR_ALRAIE; // enable alarm interrupt ben was RTC_ITConfig(RTC_IT_ALRA, ENABLE);
RTC->CR |= RTC_CR_ALRAE; // enable alarm
RTC->ISR &= ~RTC_ISR_INIT; // Exit initialisation mode
RTC->WPR = 0xFF; // Enable the write protection for RTC registers

Posted on November 06, 2013 at 19:51

Try to use the library functions, I seem to recall a speed/race issue with the Write Protect.

Haven't personally spent a lot of time with the F0, bit off my roadmap.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
BenMack99
Senior
Posted on November 07, 2013 at 15:27

Thanks for the reply Clive.

I have tried the library functions and couldn't even set the TR with RTC_SetTime() - this of course may be a clue, I should probably revisit that. Regards write protect, the library functions simply do what I do, e.g. in RTC_SetTime():-

RTC->WPR = 0xCA;
RTC->WPR = 0x53;
 .....
 RTC->WPR = 0xFF; 

In general I prefer my own code to the library functions, as it tends to be much simpler and easier to debug. The reference and programming manuals are written in terms of what you do to registers, not what library routines you call. That said I always check the library code to see how they have done it. I may be wrong here of course, I'm obviously doing something wrong.... Cheers
BenMack99
Senior
Posted on November 13, 2013 at 14:57

A brief update, I solved it, turned out to be obvious....

Before setting the alarm register, you need to disable the alarm. I'm sure I tried this before, must have suffered finger trouble See Table 4 in http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00025pdf Example code

RTC->WPR = 0xCA; // disable the write protection for RTC registers
RTC->WPR = 0x53; // ditto
RTC->CR &= ~RTC_CR_ALRAE; // disable alarm
while (!(RTC->ISR & RTC_ISR_ALRAWF)); // and wait for write flag
RTC->ALRMAR = i; // set new value
RTC->CR |= RTC_CR_ALRAE; // enable alarm
RTC->WPR = 0xFF; // enable the write protection for RTC registers

or using lib functions RTC_AlarmCmd(DISABLE); RTC_SetAlarm(***); RTC_AlarmCmd(ENABLE);