MCF52259 RTC issues - can anyone clarify correct operation?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MCF52259 RTC issues - can anyone clarify correct operation?

Jump to solution
2,864 Views
FridgeFreezer
Senior Contributor I

Micro is MCF52259 LQFP144, IDE is CW7.2 using C.

 

Having got things up & running on our first run of prototype boards, I've just programmed code into a 2nd gen prototype and the RTC fails to start. Using the same init routines on a working board, I can't make the RTC stop!

 

The circuity is exactly the same on both; RTC is using an external 32.768KHz crystal across RTC_EXTAL/RTC_XTAL and backup battery on VSTBY.

 

I suspect that during the struggle to get the RTC working in development, the RTC registers have been written with the magic combination to make it work, and then the backup battery has preserved the settings for posterity. The reference manual (Rev.2) for the mirco has a couple of cryptic references to things which are not explained:

 

First:

The real-time clock control (RTCCTL) register is used to enable the real-time clock module and specify
the reference frequency information for the prescaler

 

This register is only shown as having two bits implemented: 0x80 for RTC_Enable and 0x01 for RTC_Software_Reset. Althgough my init routine sets this register to 0x80, a read of it returns 0x01 on both working & non-working boards. There is no mention of anything to do with the prescaler.

 

Second:

9.4.1 RTC Register Access Protocol
1. Perform dummy read access to a non-RTC address location.
2. Perform dummy read to the targeted RTC address location.
3. Perform actual read or write access to the targeted RTC address location.
Steps 1 and 2 can be combined into one cycle that is a dummy read access to a non-RTC but targeted RTC
address location. Then the protocol is:
1. Perform dummy read access to a non-RTC, targeted RTC address location.
2. Perform actual read or write access to targeted RTC address location.

 

No further explanation is given on this, and frankly I'm clueless as to what it really means, can anyone shed any light on what sort of routine one is expected to use to conform to this protocol?

 

Third, and not helping my befuddlement:

Figure 9-15 shows sample code for initializing the RTC.
MCF_CLOCK_RTCCR=0b01010110; //RTCCC
MCF_RTCGOCL = 0x00002000; //32KHz
MCF_CLOCK_RTCCR=0b01010111; //RTCCC
MCF_RTC_HOURMIN = MCF_RTC_HOURMIN_HOURS(((uint32)time_temp % 24));
MCF_RTC_HOURMIN = MCF_RTC_HOURMIN_MINUTES(((uint32)time_temp % 60));
MCF_RTC_SECONDS = MCF_RTC_SECONDS_SECONDS(((uint32)time_temp % 60));

 

Not much help as I can't see any dummy reads or indeed any configuration of the RTCCTL register.

 

My init routine currently looks like this:

MCF_RTC_RTCCTL |= MCF_RTC_RTCCTL_EN; // Enable RTC

MCF_CLOCK_RTCCR = 0    | MCF_CLOCK_RTCCR_RTCSEL    // Crystal source
                        | MCF_CLOCK_RTCCR_REFS        // External xtal
                        | MCF_CLOCK_RTCCR_OSCEN        // Oscillator enabled
                        | MCF_CLOCK_RTCCR_EXTALEN;    // EXTAL enabled
MCF_RTC_RTCGOCU = 0x00000000;
MCF_RTC_RTCGOCL = 0x00002000; // 32.768KHz XTAL

Not that it's much use as the boards which have a running RTC just keep running and the ones that don't won't!

 

I have searched back and a there are a couple of threads on this subject but none seem to contain a solution or the full answers.

 

I have looked at the Freescale code examples and haven't found any great insights, here are a couple of snippets:

(from rtc_main.c)

void rtc_write_prescaler (uint32 value)
{
    // Set RTC clk source, enable RTC etc.
     MCF_CLOCK_RTCCR = 0x57; // This is = ~(ENABLE | RESET) so disabling the RTC
     
     MCF_RTC_RTCGOCU = 0x00000000;
     MCF_RTC_RTCGOCL = value;
}

 

The RTC is then enabled again later with:

 

MCF_RTC_RTCCTL = MCF_RTC_RTCCTL_EN;

But when I do the same thing the RTC doesn't spring into life.

 

I'm sure there's something daft I'm missing but I can't for the life of me see what it is.

Labels (1)
0 Kudos
1 Solution
1,027 Views
vier_kuifjes
Senior Contributor I

Make sure registers MCF_RTC_RTCGOCU and MCF_RTC_RTCGOCL (as well as all other RTC registers) are defined / accessed as 32 bit registers, even though they may only contain 16 bits. I have had the same problem with the 52259 CPU. No matter what I did, I could not get the RTC running. The problem for me was (in coldfire lite) that there was a bug in the RTC register definitions. They should be something like this to work:

 

 

/*********************************************************************
*
* Real-Time Clock (RTC)
*
*********************************************************************/

/* Register read/write macros */
#define MCF_RTC_HOURMIN                      (*(vuint32*)(0x40180000))
#define MCF_RTC_SECONDS                      (*(vuint32*)(0x40180004))
#define MCF_RTC_ALRM_HM                      (*(vuint32*)(0x40180008))
#define MCF_RTC_ALRM_SEC                     (*(vuint32*)(0x4018000C))
#define MCF_RTC_RTCCTL                       (*(vuint32*)(0x40180010))
#define MCF_RTC_RTCISR                       (*(vuint32*)(0x40180014))
#define MCF_RTC_RTCIENR                      (*(vuint32*)(0x40180018))
#define MCF_RTC_STPWCH                       (*(vuint32*)(0x4018001C))
#define MCF_RTC_DAYS                         (*(vuint32*)(0x40180020))
#define MCF_RTC_ALRM_DAY                     (*(vuint32*)(0x40180024))
#define MCF_RTC_RTCGOCU                      (*(vuint32*)(0x40180034))
#define MCF_RTC_RTCGOCL                      (*(vuint32*)(0x40180038))

 

The ones in red were originally defined as vuint16 (in coldfire lite), which caused the RTC to not work.

 

 

My RTC init routine looks as simple as this. I'm using the main crystal as reference, not the RTC crystal...

 

 

voidmcf52259_rtc_init(void){ // initialize RTC divider    MCF_RTC_RTCCTL = MCF_RTC_RTCCTL_EN;    MCF_CLOCK_RTCCR = 0;                                                 // select system clock for RTC    MCF_RTC_RTCGOCU = (unsigned short)((20000000) >> 16); // based on 80MHz system clock    MCF_RTC_RTCGOCL = (unsigned short)(20000000);        MCF_RTC_SECONDS = 0;         // set actual time to 0    MCF_RTC_HOURMIN = 0;    MCF_RTC_DAYS = 0;}

 

 

View solution in original post

0 Kudos
10 Replies
1,027 Views
TomE
Specialist II

> MCF_RTC_HOURMIN = MCF_RTC_HOURMIN_HOURS(((uint32)time_temp % 24));
> MCF_RTC_HOURMIN = MCF_RTC_HOURMIN_MINUTES(((uint32)time_temp % 60));
> MCF_RTC_SECONDS = MCF_RTC_SECONDS_SECONDS(((uint32)time_temp % 60));

>

> Not much help as I can't see any dummy reads or indeed any configuration of the RTCCTL register.

That's the least of its problems. Assuming "time_temp" contains a count of seconds, what does "time_temp % 24" result in? Nothing at all sensible. Certainly not hours. And why are the Minutes and Seconds being set to identical values?

Also, since the Hours and Minutes are stored in different fields in the same HOURMIN register, the result of the first two calculations have to be added and then stored in that register, otherwise the second write overwrites what the first one did. So that's at least four bugs in three lines.

That got past an editor?

And then copied it verbatim into the MCF52210, 52211, 52223, 52235 and 52259 manuals without correction, and through four revisions (in the case of the MCF52259)?.

Tom


0 Kudos
1,027 Views
FridgeFreezer
Senior Contributor I

Hi Tom, you have an eagle eye! I assume the first line should be MCF_RTC_DAYS = blah.

Eeeeeh, it does my heart good to be back on the FS forums with minor problems like rubbish RTC documentation and a support forum that requires me to disable Ghostery in my browser before I can reply :smileygrin: I'm working on a TI SoC at the moment and the experience makes Freescale look like shining beacons of help, support, and competence!

0 Kudos
1,027 Views
TomE
Specialist II

> I assume the first line should be MCF_RTC_DAYS = blah.

Really? Look closer at that mess.

The current "blah" is "Time % 24". That just gets you a number that changes every SECOND and wraps after 23. Wrong by a factor of 3600. The proper code was probably something like this before someone edited it by removing all the essential divide lines:

    time_t nTime = time(NULL);

    printf("Seconds = %ld\n", nTime % 60);
    nTime /= 60;
    printf("Minutes = %ld\n", nTime % 60);
    nTime /= 60;
    printf("Hours = %ld\n", nTime % 24);
    nTime /= 24;
    printf("Days = %ld\n", nTime % 7);

And of course, the Minutes and Hours values would have to be calculated separately and then combined to fit into the HOURMIN register.

Unlike Freescale, I usually test my code before I publish it.

Tom

0 Kudos
1,027 Views
tbdin
Contributor I

I need to periodically poll & call specific functions every say 100 ms and i doing this without OS. I am using MCF52259 Processor and CW7.2. For the timer Implementation, Have the following queries.. I am beginner to CW and also to the low level programming..

1. For triggering every 100 ms, i need to configure the RTC registers. Assume, with the below solution, the RTC is configured. Can you explain how to read the time?. Which register should is read?.

2. Can you suggest how to trigger an IRQ every 100ms.

 

 

Dinesh

 

 

0 Kudos
1,027 Views
TomE
Specialist II

You need working sample code.

 

Check the Freescale pages for the MCF52259 for App Notes and Sample Code. I'm checking this and there doesn't seem to be much support for these chips, does there?

 

You'll find that older chips have better support documentation. Find the timer module you want to program, then look for the OLDEST Coldfire chip that has that module in it, and look for Application Notes and Sample Code for that chip.

 

You want 10Hz interrupts. The Reference Manual states:

 

"Once-per-day, once-per-hour, once-per-minute, and once-per-second interrupts."

 

So the RTC isn't the module to do what you want. So I don't think you've read the manual if you didn't know that. The RTC only runs from the RTC_EXTAL too. You probably want to run 10Hz timers from the normal XTAL instead. That also means you can't use this module for this purpose.

 

You could use a crystal on EXTAL and then make the RTC run 10 times too fast, but it would be running at 8192/819 or 10.00244Hz.

 

The MCF52259 has four Programmable Interrupt Timers, four General Purpose Timers and four DMA Timers. Any of these can be programmed to generate interrupts.

 

Here's another approach to get code samples. Download the "Coldfire initialisation" program from HERE (not from Freescales'web site, their one is too old):

 

http://www.microapl.co.uk/CFInit/cfinit_main.html

 

It doesn't support the MCF52259, but a quick check of the MCF52235 indicates it has the same RTC, PIT< GPT and DMA Timers. So generate some code for them.

 

Then you'll have to write interrupt service routines. For these you'll need to read the peripheral and interrupt controller chapters VERY closely. You could also try downloading some of the linux source:

 

Read the following:

 

https://community.freescale.com/message/70585#70585

 

That refers to:

 

http://lxr.free-electrons.com/source/arch/m68knommu/platform/coldfire/pit.c?v=2.6.32

 

That shows working (but buggy) PIT code with service routines, but you'll have to download everything to work out what the special macros and functions are doing. Take a few guesses, it should be enough to get you started.

 

Tom

 

 

 

 

0 Kudos
1,027 Views
FridgeFreezer
Senior Contributor I

With reference to the 10Hz interrupt problem, we use PIT0/1 as a faster raster for timed processes. It may not be microsecond accurate but as long as things happen at regular intervals that's often more important than happening at a specific frequency.

0 Kudos
1,027 Views
TomE
Specialist II

FridgeFreezer wrote:

> With reference to the 10Hz interrupt problem, we use PIT0/1 as a faster raster

 

"raster"? "Timer" or "Master"?

 

> for timed processes. It may not be microsecond accurate

 

There's no reason why it can't be nanosecond accurate. It should be as accurate as the crystal driving it, AS LONG AS you don't fall into one of the two "Bear PITs" that this peripheral was designed with.

 

See this forum article for details:

 

https://community.freescale.com/message/70583#70583

 

 

0 Kudos
1,027 Views
FridgeFreezer
Senior Contributor I

Raster, as in http://en.wikipedia.org/wiki/Raster_scan - just a (mis-used) term for slicing something in time or otherwise.

 

I agree there's no reason the PIT can't be accurate, but my point was that for a lot of operations it doesn't matter if it runs at 100Hz or 100.5Hz as long as the frequency is stable. Using it as a time clock would obviously be a no-no, but for running regular samples, polling comms, etc. the frequency can often be anything within a wide bound, people will pick a number like 100Hz but it would work just as well +/-20% or more.

0 Kudos
1,028 Views
vier_kuifjes
Senior Contributor I

Make sure registers MCF_RTC_RTCGOCU and MCF_RTC_RTCGOCL (as well as all other RTC registers) are defined / accessed as 32 bit registers, even though they may only contain 16 bits. I have had the same problem with the 52259 CPU. No matter what I did, I could not get the RTC running. The problem for me was (in coldfire lite) that there was a bug in the RTC register definitions. They should be something like this to work:

 

 

/*********************************************************************
*
* Real-Time Clock (RTC)
*
*********************************************************************/

/* Register read/write macros */
#define MCF_RTC_HOURMIN                      (*(vuint32*)(0x40180000))
#define MCF_RTC_SECONDS                      (*(vuint32*)(0x40180004))
#define MCF_RTC_ALRM_HM                      (*(vuint32*)(0x40180008))
#define MCF_RTC_ALRM_SEC                     (*(vuint32*)(0x4018000C))
#define MCF_RTC_RTCCTL                       (*(vuint32*)(0x40180010))
#define MCF_RTC_RTCISR                       (*(vuint32*)(0x40180014))
#define MCF_RTC_RTCIENR                      (*(vuint32*)(0x40180018))
#define MCF_RTC_STPWCH                       (*(vuint32*)(0x4018001C))
#define MCF_RTC_DAYS                         (*(vuint32*)(0x40180020))
#define MCF_RTC_ALRM_DAY                     (*(vuint32*)(0x40180024))
#define MCF_RTC_RTCGOCU                      (*(vuint32*)(0x40180034))
#define MCF_RTC_RTCGOCL                      (*(vuint32*)(0x40180038))

 

The ones in red were originally defined as vuint16 (in coldfire lite), which caused the RTC to not work.

 

 

My RTC init routine looks as simple as this. I'm using the main crystal as reference, not the RTC crystal...

 

 

voidmcf52259_rtc_init(void){ // initialize RTC divider    MCF_RTC_RTCCTL = MCF_RTC_RTCCTL_EN;    MCF_CLOCK_RTCCR = 0;                                                 // select system clock for RTC    MCF_RTC_RTCGOCU = (unsigned short)((20000000) >> 16); // based on 80MHz system clock    MCF_RTC_RTCGOCL = (unsigned short)(20000000);        MCF_RTC_SECONDS = 0;         // set actual time to 0    MCF_RTC_HOURMIN = 0;    MCF_RTC_DAYS = 0;}

 

 

0 Kudos
1,027 Views
FridgeFreezer
Senior Contributor I

Cheers Mark,

An old header file from CW7.1 seems to have crept in, now sorted!

0 Kudos