2004-11-22 06:20 AM
2004-11-19 05:17 AM
Hi,
I am having problems with the RTC peripheral on the ST10F269. I am trying to use the RTC to get an estimate of CPU usage by measuring the amount of time spent during Idle Mode. The problem I am having is that in a small number of cases, the RTC appears to go backwards. It seems to be going backwards in two different ways: 1) There appears to be some latency between the DIVIDER reaching zero and being reloaded and the basic reference clock being incremented. In other words, in one time measurement I can see the RTCDL/RTCDH registers being very small (1 or 2) and in the next measurement they are several counts less than the PRESCALER, but the RTCL register has not changed. 2) Occasionally the RTCDL register has a ''hiccup'' and increases by a fixed amount (4096 on the processor next to me.) It seems to happen when the RTCDL register passes a particular value. Am I completely out to lunch in trying to use the RTC peripheral in this way? Any ideas about possible sources of these problems? Confused, tchristney2004-11-22 06:20 AM
Hi,
My problem is not with how the RTC operates, but with its behaviour on my system. We are using a 10 MHz oscillator, which implies that the RTCD should decrement every 6.4 us. I am loading RTCP with 156250 to give me a 1 second period on the RTC registers. This all works as expected unless I look at very small time slices. I would have expected the RTC registers to atomically increment when either the RTCD registers reach zero or when they are reloaded with the RTCP registers. Neither seems to be the case. There is an unknown (i.e. unmeasured by me) latency before the RTC registers are incremented. This could be an artefact of what I am trying to do - especially if the increment is done in an interrupt handler (see below.) The second problem is perhaps more serious. Occasionally I am seeing the RTCDL register's bit 12 get set when the value goes from 0xCFDF to 0xCFDE, i.e. it actually goes from 0xCFDF to 0xDFDE. Here is some code showing what I am trying to do - this is running as the lowest priority task in Keil's RTX Full.Code:
struct hilo_s { unsigned int lo; unsigned int hi; }; typedef union rtcd_s { struct hilo_s reg; long val; } rtcd_t; typedef union rtc_s { struct hilo_s reg; unsigned long val; } rtc_t; typedef struct rtc_state_s { rtcd_t divider; rtc_t clock; } rtc_state_t; void get_rtc_state( rtc_state_t * rtc_p ) { register unsigned int rtcdl; register unsigned int rtcdh; register unsigned int rtcl; register unsigned int rtch; _atomic_(0); rtcdl = RTCDL; rtcdh = RTCDH; rtcl = RTCL; rtch = RTCH; _endatomic_(); rtc_p->divider.reg.lo = rtcdl; rtc_p->divider.reg.hi = rtcdh & 0xF; rtc_p->clock.reg.lo = rtcl; rtc_p->clock.reg.hi = rtch; } long timed_idle( void ) { rtc_state_t start, end; IEN = 0; // disable interrupts _nop_(); get_rtc_state( &start ); // get the state of the RTC _atomic_(2); // renable interrupts (allows PEC transfers) IEN = 1; _idle_(); // enter idle mode IEN = 0; // disable interrupts _nop_(); get_rtc_state( &end ); // get the state of the RTC IEN = 1; // enable interrupts return (get_diff( &start, &end ) ); } Now if timed_idle() returns a negative value, I print out the register values collected into the structures start and end. This is my evidence for the behaviours mentioned above. Perhaps the problem stems from the entry/exit to/from IDLE mode. We will probably have to have a HW based CPU usage measurement, but it would be nice if this approach could at least give a reasonable approximation.