K20 RTC with Interrupts

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

K20 RTC with Interrupts

Jump to solution
3,132 Views
knipsknaps
Contributor II

Folks,

 

we are using a K20N512VLL100 (Datecode 1N30D) and are trying to tame the RTC and its interrupts.

 

We want to use an Alarm IRQ (periodically generated every second) to have a substitute for the seconds interrupt (which we think is not implemented, because we did not find any "dedicated interrupt vector" as mentioned in the manual).

 

Here is our (rather simple) init code for the RTC:

 

...

/*enable the clock to SRTC module register space*/

SIM_SCGC6 |= SIM_SCGC6_RTC_MASK;

 

/* Only VBAT_POR has an effect on the SRTC, RESET to the part does not,

   so you must manually reset the SRTC to make sure everything is in a known state */

 

/*clear the software reset bit*/

 

RTC_CR = RTC_CR_SWR_MASK;

RTC_CR  &= ~RTC_CR_SWR_MASK;  

 

/* Enable RTC interrupt in NCVIC */

 

NVICICPR2 |= 0x4; //Clear RTC pending interrupts in NVIC   

NVICISER2 |= 0x4; //Enable RTC interrupts in NVIC


/*Enable the oscillator*/

RTC_CR |= RTC_CR_OSCE_MASK;

 

/*Wait to all the 32 kHz to stabilize, refer to the crystal startup time

 in the crystal datasheet*/

 

for(i=0;i<0x600000;i++);

 

RTC_CCR = 0x00;

 

RTC_TSR = 0; // Initialize Time ....later only if VBat was lost 


RTC_TAR = RTC_TSR + 10; // First RTC alarm should come up in 10 seconds

 

/* Enable the counter */


RTC_SR |= RTC_SR_TCE_MASK;

...

 

Now we expect all is done....here is our RTC-ISR:

 

...

if ((RTC_SR & RTC_SR_TIF_MASK)== 0x01) 

{     RTC_SR &= 0x07;  //clear TCE, or RTC_TSR can  not be written   

       RTC_TSR = 0x00000000;  //clear TIF  

else if ((RTC_SR & RTC_SR_TOF_MASK) == 0x02) 

{    RTC_SR &= 0x07;  //clear TCE, or RTC_TSR can  not be written     

      RTC_TSR = 0x00000000;  //clear TOF 

}  

else if ((RTC_SR & RTC_SR_TAF_MASK) == 0x04) 

{   RTC_TAR += 1; // Write new alarm value, to generate an alarm every second add 1 

}

 

Now, we get a strange behavior:

 

After this init we got a interrupt with Bit 0 (TIF) of RTC_SR set. This is handled by the ISR properly. But never we get an Alarm Interrupt TAF (RTC_SR Bit 2) set. But the Alarm flag TAF is set, we checked this by polling it in our main loop.

 

When we disable all RTC interrupt sources in RTC_IER, of course no ISR call is done. But independent which interrupt we enable (even if we only enable only the alarm interrupt) we always get the TIF interrupt, but never an TAF alarm interrupt...

 

What is our mistake ?

 

Thanks, Ulf



0 Kudos
Reply
1 Solution
1,761 Views
knipsknaps
Contributor II

Thanks, Folks,

 

your hints made us solve the problem. In future we will have to read the manuals carefullier to understand the details of this complex device.

 

Regards, Ulf

View solution in original post

0 Kudos
Reply
6 Replies
1,761 Views
mjbcswitzerland
Specialist V

Hi Ulf

 

I don't see where you enable the RTC interrupt (RTC_IER = RTC_IER_TAIE).

 

TIF means that the timer is invalid and it won't actually count in this state. To clear it, write RTC_SR = 0; and then RTC_SR = RTC_SR_TCE; This will reset that flag and allow the counter to run.

 

To generate a seconds interrupt you need to set

RTC_TAR = RTC_TSR;

and not +1 ("TAF is set whenever TAR equals the TSR and the TSR increments". This is a bit strange, but, if it is read carefully, it means that the interrupt is not generated when the count value increments to match the alarm value but when the increment takes place after the match).

 

The uTasker project includes RTC support (tested on K40 and K60 and assumed the same on K20), including full Gregorian time/calendar support - see http://www.utasker.com/forum/index.php?topic=1656.0 

The interface was in fact made equivalent to the M522xx RTC interface so it retains compatibility with Coldfire RTC projects by also supporting the features of that RTC - like minutes interrupts, hours interrupts, day interrupts, stop-watch and an alarm at a specified date and time (realised in SW though since the Kinetis RTC is simpler).

 

Regards

 

Mark

 

0 Kudos
Reply
1,761 Views
egoodii
Senior Contributor III

Note of course that RTC_IER is a new register, available only in later documentation & chips.

 

--ERGII

0 Kudos
Reply
1,761 Views
mjbcswitzerland
Specialist V

Hi

 

My K60 board arrived in Dec. 2010 and the chip (1M42M) has the RTC_IEC register.

I think that the K20s are much newer so should be equivalent.

 

Regards

 

Mark

 

0 Kudos
Reply
1,761 Views
knipsknaps
Contributor II

Hi Mark,

 

thank you for your hints, but unfortunately they do not make the thing work.

 

HW-Reset will automatically enable the Alarm interrupt and all the other ones (RTC_IER is set to 0x07 by reset). That is the reason why we don not enable the Alarm interrupt. 

 

We changed the interrupt behavior to clear TIIF as well to clear TOIF, ok.

 

We also changed the setting of TAR in the way you told: Set it to TSR to get the interrupt generated every second AFTER comparison is true. 

 

If you look at our ISR you can see that we catch the contents of RTC_SR in the beginning. We get many RTC interrupts with RTC_SR = 0x20. Our documentation says: Bit 5 is not used and always reads 0....what is going on here?

 

Unfortunately the seconds interrupt does not work anyway. Any other ideas?

 

Regards

 

Ulf

0 Kudos
Reply
1,761 Views
mjbcswitzerland
Specialist V

Hi Ulf

 

Below is the code from the uTasker project. It should be possible to use this more or less directly to verify that your HW is operating correctly:

 

Initialisation code:

        POWER_UP(6, SIM_SCGC6_RTC);                                      // ensure the RTC is powered        if (RTC_SR & RTC_SR_TIF) {                                       // if timer invalid            RTC_SR = 0;                                                  // ensure stopped            RTC_TSR = 0;                                                 // write to clear RTC_SR_TIF in status register when not yet enabled            RTC_CR = (RTC_CR_OSCE | RTC_CR_CLKO);                        // enable oscillator but don't supply clock to other peripherals            return WAIT_STABILISING_DELAY;                               // the oscillator requires some time to stabilise so the user should call again after this time has expired        }        rtc_interrupt_handler[iIRQ] = ((INTERRUPT_SETUP *)ptrSettings)->int_handler; // enter the handling interrupt        RTC_SR = 0;                                                      // temporarily disable RTC to avoid potentially missed seconds count        fnConvertSecondsTime(RTC_TSR);                                   // take the present seconds count value and convert to time and date        RTC_TAR = (RTC_TSR);                                             // set timer alarm interrupt at next second        fnEnterInterrupt(irq_RTC_ID, PRIORITY_RTC, _rtc_handler);        rtc_interrupts |= (0x01 << iIRQ);                                // flag interrupt(s) enabled        RTC_IER = RTC_IER_TAIE;                                          // enable alarm interrupt        RTC_SR = RTC_SR_TCE;                                             // enable couter

 fnConvertSeconds() can be comment out since it converts the present count value to a data/time only.

rtc_interrupts is not needed since it is used by the ISR to simulate a number of Coldfire RTC interrupts.

The details about entering interrupts can be changed to suit the framework. you use.

 

Note that the full initialisation is only performed once (when the RTC is invalid) and subsequent starts leave the RTC and its oscillator alone.

 

In the case of return WAIT_STABILISING_DELAY the user recalls the initialisation after a pause of 1s in order to allow the 32kHz oscillator to stabilise (when debugging and stepping the code this is not necessary since one just needs to step slowly). Also make sure that you have the power input to the RTC connected to a battery or the appropriate voltage since the RTC will otherwise not run.

 

The interrupt handler just does:

 

static __interrupt void _rtc_handler(void){    RTC_TAR = (RTC_TSR);  // reset interrupt flag and set timer alarm interrupt to next second    .... plus some extra stuff to simulate Coldfire RTC operation}

 

Regards

 

Mark

 

 

0 Kudos
Reply
1,762 Views
knipsknaps
Contributor II

Thanks, Folks,

 

your hints made us solve the problem. In future we will have to read the manuals carefullier to understand the details of this complex device.

 

Regards, Ulf

0 Kudos
Reply