cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to Set RTC on STM32F4

Rogers.Gary
Senior II
Posted on July 28, 2014 at 21:38

Hi,

I'm following an example as provided by the STD PERIPHERALS library, on an STM32F4 Discovery board. In spite of what's being written in the config routine, when I set the define for LSI, I read back this:

Year =  20

Month =  07

Date =  36

Hours =  15

Mins =  32

Secs =  35

When I set the define for LSE, I read back this:

Year =  00

Month =  01

Date =  01

Hours =  00

Mins =  00

Secs =  00

Neither of which matches the values being written in the config routine. For the LSE, a 32.768KHz xtal was installed, with 2 caps, and is oscillating happily.

Here's the config routine:

&sharpdefine RTC_CLOCK_SOURCE_LSE            /* LSE used as RTC source clock */

&sharpdefine FIRST_DATA         0x32F2

static void RTC_Config(void)

{

    /* Enable the PWR clock */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    /* Allow access to RTC */

    PWR_BackupAccessCmd(ENABLE);

    

    &sharpif defined (RTC_CLOCK_SOURCE_LSI)  /* LSI used as RTC source clock*/

    /* The RTC Clock may varies due to LSI frequency dispersion. */

      /* Enable the LSI OSC */

      RCC_LSICmd(ENABLE);

      /* Wait till LSI is ready */  

      while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)

      {

      }

      /* Select the LSI as RTC Clock Source */

      RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

      /* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/

      uwSynchPrediv = 0xFF;

      uwAsynchPrediv = 0x7F;

    &sharpelif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */

      /* Enable the LSE OSC */

      RCC_LSEConfig(RCC_LSE_ON);

      /* Wait till LSE is ready */  

      while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

      {

      }

      /* Select the LSE as RTC Clock Source */

      RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

     /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/

      uwSynchPrediv = 0xFF;

      uwAsynchPrediv = 0x7F;

    &sharpelse

      &sharperror Please select the RTC Clock source inside the main.c file

    &sharpendif /* RTC_CLOCK_SOURCE_LSI */

      

      /* Enable the RTC Clock */

      RCC_RTCCLKCmd(ENABLE);

      /* Wait for RTC APB registers synchronisation */

      RTC_WaitForSynchro();

      /* Write to the first RTC Backup Data Register */

      RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);

      /* Set the Time */

      RTC_TimeStructure.RTC_Hours   = 0x08;

      RTC_TimeStructure.RTC_Minutes = 0x00;

      RTC_TimeStructure.RTC_Seconds = 0x00;

      /* Set the Date */

      RTC_DateStructure.RTC_Month = RTC_Month_July;

      RTC_DateStructure.RTC_Date = 0x27;  

      RTC_DateStructure.RTC_Year = 0x14;

      RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Monday;

      /* Calendar Configuration */

      RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;

      RTC_InitStructure.RTC_SynchPrediv =  uwSynchPrediv;

      RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;

      RTC_Init(&RTC_InitStructure);

      

      /* Set Current Time and Date */

      RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);  

      RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);

}

I would be forever grateful if anyone....could tell me what the issue is. I have been in grief for a day now trying to figure out what is wrong. What i find really perplexing is, the routine above is directly from ST. Why doesnt it work on either LSI, or LSE?  Totally at a loss here....please HELP.

#stm32 #rtc
8 REPLIES 8
Rogers.Gary
Senior II
Posted on July 29, 2014 at 07:01

Hi,

Can anyone who's got a working RTC configuration please post it here, or check mine out to see if they might know what the issue is? I really need to get this working.

Thanks....

Posted on July 29, 2014 at 18:22

Well, it works for me. Make sure you have the solder bridges removed, and you probe the clock indirectly via the MCO pin, or measure via TIM5

LSI:32080, LSE:32770
LSE On
LSE Ready
LSE ByPass Off
RTC Clock Enabled
RTC Clock Source LSE
08:00:00 27/07/14
08:00:01 27/07/14
08:00:02 27/07/14
08:00:03 27/07/14
08:00:04 27/07/14
08:00:05 27/07/14
08:00:06 27/07/14
08:00:07 27/07/14
08:00:08 27/07/14
08:00:09 27/07/14

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on July 29, 2014 at 20:39

Hi clive1,

Thank you for answering.

I had not removed the solder bridges. I have now done that, and ensured there was not any connection between the 2 points where they were. The oscillator I installed still appears to be working. I verified the MCU is getting the signal at pins 8 & 9.

However, the RTC still is not configuring...

Please forgive my ignorance. The documentation isn't clear about MCO. The only MCO connection is port PA8.

1 - If MCO is PA8, I am not getting any signal there. Is that the correct point to check?

2 - What should the frequency of the MCO be?

3 - How (& why) would I check with TIM5?

Thanks again,

Gary

Posted on July 29, 2014 at 21:09

I pasted in your code, though admittedly I have LSI and LSE running already, as part of my original test framework for the STM32F4-DISCO. I picked up a strip of the 768 KHz parts as most of the Disco boards don't have them, and standby works better from LSE. These need to be 6-7pF crystals, not the 9 or 12pF type. Sticking scope probes on the pins will alter the circuit characteristics.

There are two MCO pins on F2/F4 parts, you can route internal clocks and fractions thereof under 60-84MHz out. You can measure LSE directly, and should be 32768 Hz at DIV1.

void ClockMCO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOs clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure MCO (PA8) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Output LSE clock (768KHz) on MCO pin (PA8) */
RCC_MCO1Config(RCC_MCO1Source_LSE, RCC_MCO1Div_1);
}

TIM5_CH4 can be routed to the RTC clock, and you can benchmark it for accuracy against the HSE/PLL, ie period of an LSE/LSI cycle in 8 or 168 MHz ticks. The code here misses a few tricks, but is illustrative : STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Project\STM32F4xx_StdPeriph_Examples\RTC\RTC_LSI\main.c
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on July 29, 2014 at 21:38

Clive1,

Again, thanks. I ran the test code you provided and there is a perfect square wave at the correct (LSE) frequency on PA8. Is it possible you can post 2 other things for me and I'll do some further testing? 1 - The function calls to display (in your original post) that displayed the following:

LSI:32080, LSE:32770
LSE On
LSE Ready
LSE ByPass Off
RTC Clock Enabled
RTC Clock Source LSE

2 - I know this sounds silly, but did you use the exact (RTC_Config) function I put at the start of this thread? If so, can you then tell me what calls you are using to display the date/time? Maybe that's where things are going weird. Not sure what else to look for at this point... Regards, Gary
Posted on July 29, 2014 at 22:00

#define RTC_CLOCK_SOURCE_LSE /* LSE used as RTC source clock */
#define FIRST_DATA 0x32F2
void RTC_Configuration(void)
{
RTC_InitTypeDef RTC_InitStructure;
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
uint32_t uwSynchPrediv, uwAsynchPrediv;
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Allow access to RTC */
PWR_BackupAccessCmd(ENABLE);
#if defined (RTC_CLOCK_SOURCE_LSI) /* LSI used as RTC source clock*/
/* The RTC Clock may varies due to LSI frequency dispersion. */
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */ 
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
}
/* Select the LSI as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
uwSynchPrediv = 0xFF;
uwAsynchPrediv = 0x7F;
#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
/* Enable the LSE OSC */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */ 
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
/* Select the LSE as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
uwSynchPrediv = 0xFF;
uwAsynchPrediv = 0x7F;
#else
#error Please select the RTC Clock source inside the main.c file
#endif /* RTC_CLOCK_SOURCE_LSI */
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Write to the first RTC Backup Data Register */
RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);
/* Set the Time */
RTC_TimeStructure.RTC_Hours = 0x08;
RTC_TimeStructure.RTC_Minutes = 0x00;
RTC_TimeStructure.RTC_Seconds = 0x00;
/* Set the Date */
RTC_DateStructure.RTC_Month = RTC_Month_July;
RTC_DateStructure.RTC_Date = 0x27; 
RTC_DateStructure.RTC_Year = 0x14;
RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Monday;
/* Calendar Configuration */
RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;
RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
/* Set Current Time and Date */
RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure); 
RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
if (RCC->BDCR & 0x1)
printf(''LSE On
'');
else
printf(''LSE Off
'');
if (RCC->BDCR & 0x2)
printf(''LSE Ready
'');
else
printf(''LSE Not Ready
'');
if (RCC->BDCR & 0x4)
printf(''LSE ByPass On
'');
else
printf(''LSE ByPass Off
'');
if (RCC->BDCR & 0x8000)
printf(''RTC Clock Enabled
'');
else
printf(''RTC Clock Disabled
'');
switch(RCC->BDCR & 0x300)
{
case 0x100 : puts(''RTC Clock Source LSE''); break;
case 0x200 : puts(''RTC Clock Source LSI''); break;
case 0x300 : printf(''RTC Clock Source HSE/%d'', (RCC->CFGR >> 16) & 0x1F); break;
default : puts(''RTC Clock Unknown'');
}
}
//******************************************************************************
void RTC_TimeShow(void)
{
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
/* Get the current Time */
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);
/* Display time Format : hh:mm:ss DD/MM/YY */
printf(''%0.2d:%0.2d:%0.2d %0.2d/%0.2d/%0.2d
'',
RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds,
RTC_DateStructure.RTC_Date, RTC_DateStructure.RTC_Month, RTC_DateStructure.RTC_Year );
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on July 29, 2014 at 22:11

Hi Clive1...

Here's what you were doing:

RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);   This is the really dumb thing I was doing: RTC_GetTime(RTC_Format_BCD, &RTC_TimeStructure);

RTC_GetDate(RTC_Format_BCD, &RTC_DateStructure);   All good now (except the red shade of my face)   Thanks for being prompt, courteous and very helpful.   Regards,  Gary

Posted on July 29, 2014 at 22:37

You could use BCD and ''%02X'', as I recall the register are held in BCD (silicon is simpler), so going to binary(decimal) takes more compute cycles, but eases other math.

Personally I prefer the 32-bit RTC count of the F1 parts, but a lot of code to handle the calendering tends to get broken during implementation. ie Leap Years, Day-Of-Week, Day-Of-Year and human centric D/M/Y stuff.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..