Hello,
cab wrote:
CW 10.2 (1.0.0) Win7x64 MC9S08LG32
The problem is, what happens when RTCMOD is reached? The interrupt occurs sometime later, but BAM! as soon as RTCMOD=250, RTCCNT is zeroed--but rtcMs has not been increased. So until the interrupt occurs, getMs() has lost 250ms. No way to avoid occasional mistakes--the user could be -reading- rtcMs when RTCMOD rolls over.
If we are to believe the example shown in Fig. 15.6 of the reference manual, RTCCNT should remain at the RTCMOD value for a full prescaled clock period, with the count being zeroed very closely to the flag being set (probably within a bus cycle, or so). This would imply that any problems you have experienced are more likely to be caused by other non-related interrupts delaying the execution of the RTC ISR.
This also means that, for a required timeout period of 250ms, the RTCMOD register should have a value of 249. A value of 250 would actually give a period of 251ms. However, with the use of the 1kHz oscillator, with its poor accuracy, this is rather academic.
My solution to the delayed ISR processing would be to simply monitor the flag status, and correct the returned value if the flag is set (signifying that the ISR has not yet been processed). Then let the ISR processing subsequently occur in the normal fashion. When temporarily disabling interrupts within the getMS() function, it is better to globally disable all interrupts rather than just the RTC interrupt.
A final, but important issue is that, because the global variable rtcMs is updated within the ISR, it needs to be defined as volatile, for the benefit of the getMs() function, or any other function that reads the variable.
volatile ulong rtcMs = 0;ulong getMs(void){ ulong ms; __asm sei; // Disable interrupts ms = rtcMs + RTCCNT; if (RTCSC_RTIF) ms += 250; // Corrected value __asm cli; // Re-enable interrupts return ms;}
Regards,
Mac