What is rollover and why should I worry about it?

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
I am working with an RTCC clock on my PIC. The data sheet says

The RTCSYNC bit indicates a time window during which the RTCC Clock Domain registers can be safely read and written without concern about a rollover. When RTCSYNC = 0, the registers can be safely
accessed by the CPU. Whether RTCSYNC = 1 or 0, the user should employ a
firmware solution to ensure that the data read did not fall on a rollover boundary, resulting in an invalid or partial read. This firmware solution would consist of reading each register twice and then comparing the two
values. If the two values matched, then, a rollover did not occur.

So first off what is rollover and why should I worry about it?

If I wait for RTCSYNC to be 0 like the datasheet says, it really slows down the reading of the register.

Do I really need to worry about it? Seems to work OK without waiting for RTCSYNC.
 

nsaspook

Joined Aug 27, 2009
13,079
A fast counter of a 16 or more bit register being read 8 bits at a time. The low 8 bits are at 255 with the upper bits are 0 at the time the lower bits are read. Between the time you read the upper 8 bits the lower 8 rollover to 0 and sent 1 bit to the upper 8. So now you think you have 0x01ff in the counter instead of 0x0100 (the correct value) when you read the upper 8 bits.

Most PIC 16 bit timer counters are buffered to store both 8 bit values in a latch when the lower 8 is read to fix this problem.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
A fast counter of a 16 or more bit register being read 8 bits at a time. The low 8 bits are at 255 with the upper bits are 0 at the time the lower bits are read. Between the time you read the upper 8 bits the lower 8 rollover to 0 and sent 1 bit to the upper 8. So now you think you have 0x01ff in the counter instead of 0x0100 (the correct value) when you read the upper 8 bits.

Most PIC 16 bit timer counters are buffered to store both 8 bit values in a latch when the lower 8 is read to fix this problem.

Sorry but what?


Are you saying the MCU updates the lower register which rolls over into the higher byte register, incrementing it. If read at the wrong time I could for example read a 0x00 in the higher order register and then read a 0x00 in the lower order register which was previously 0xFF?


If so why should it matter here? There is a different register for Year, Month, Day, Hour, Minute, Seconds.

Though they are in pairs:

RTCPTR<1:0>
RTCC Value Register Window
RTCVAL<15:8> RTCVAL<7:0>
00 MINUTES SECONDS
01 WEEKDAY HOURS
10 MONTH DAY
11 YEAR

Or would this rollover occur at midnight?
 

MrChips

Joined Oct 2, 2009
30,704
Rollover is a perpetual problem when multiple registers are used in counting. This is not limited to occur only at midnight.

Here is an example. Suppose you have two registers, one for seconds and the other for minutes. Let us assume the time in minutes:seconds is 03:59.

If you read 3 minutes first, there is a chance that when you read the seconds you will read 00, resulting in 3:00 being read.

If you read 59 seconds first, there is a chance you will read 4 minutes, resulting in 4:59 being read. We know that both 3:00 and 4:59 are incorrect because the correct time is 4:00.

This is a problem with all multiple byte or register counting systems, including 8-bit, 16-bit, 32-bit, etc, multiple timer/counters when they are cascaded.

There are only two solutions:

(1) the hardware must have latching capabilities whereby all registers are latched simultaneously on the opposite edge of the counting clock.

(2) stop the clock while reading.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,079
Ditto MrChips and.

3. Reread the registers to see if they changed.

This firmware solution would consist of reading each register twice and then comparing the two
values. If the two values matched, then, a rollover did not occur.
 

Markd77

Joined Sep 7, 2009
2,806
From PICmicroTM Mid-Range MCU Family Reference Manual
If you want to go for method 3.

Example 12-2:
Reading a 16-bit Free-Running Timer
Rich (BB code):
; All interrupts are disabled
MOVF TMR1H, W   ; Read high byte
MOVWF TMPH   ;
MOVF TMR1L, W   ; Read low byte
MOVWF TMPL   ;
MOVF TMR1H, W   ; Read high byte
SUBWF TMPH, W   ; Sub 1st read with 2nd read
BTFSC STATUS,Z   ; Is result = 0
GOTO CONTINUE   ; Good 16-bit read
;
; TMR1L may have rolled over between the read of the high and low bytes.
; Reading the high and low bytes now will read a good value.
;
MOVF TMR1H, W   ; Read high byte
MOVWF TMPH   ;
MOVF TMR1L, W   ; Read low byte
MOVWF TMPL   ;
; Re-enable the Interrupt (if required)
CONTINUE   ; Continue with your code
 

MrChips

Joined Oct 2, 2009
30,704
Method #4:

Read the manuals very carefully.

When reading and writing multiple byte data, the manual will specify the order of reading.

For example, to read 16 bits, read low-byte followed by high-byte. To write 16 bits, write high-byte followed by low-byte.

These are only examples. Read the programming manual.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
Thanks guys, I get rollover now.

The data sheet recommends reading the registers twice till they match but that sort of defeats another feature.

The registers are accessed with a two byte pointer. When you read the RYCVALH (RTCVALL being it's mate) the pointer is decremented by 1. A assume this is so you can read all 4 register values without having to change the value of the pointer. Well once you read the H register the first time it is going to decrement the pointer so to read it again you would need to reset the pointer. So I am not exactly sure why they decrement the pointer for you.

The datasheet does not specify any particular order for reading the registers There are actually 7 different registers accessible in pairs (pointer value can be 0 to 3).
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
This is kind of related to the post above but I figured I would make it separator as to not to confuse things.

The datasheet says:

The RTCSYNC bit indicates a time window during which the RTCC Clock Domain registers can be safely read and written without concern about a rollover. When RTCSYNC = 0, the registers can be safely accessed by the CPU. Whether RTCSYNC = 1 or 0, the user should employ a firmware solution to ensure that the data read did not fall on a rollover boundary, resulting in an invalid or partial read. This firmware solution would consist of reading each register twice and then comparing the two values. If the two values matched, then, a rollover did not occur.

Well if I wait for RTSYNC to go to zero, it takes nearly a second to read each register. That's 7 seconds to get all of the needed values.

It is not clear if you can wait for RTSYNC to go low then read all 7 registers or if you need to wait for it to go low for each register read.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
Huh? That can't be right, can it?
Yep. If I wait for RTSYNC. If I do not wait then it is immediate.

That is why I am unsure if I am doing it right. I am waiting once for each read, with each read taking nearly a second. You should see how long it takes to update weekday, month, day, year, hours, minutes seconds.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
What is curious is the data sheet says

The RTCSYNC bit indicates a time window during which the RTCC Clock Domain registers can be safely read and written
.

But it does not really list what those are from the remaining description you would think that it includes RTCVAL and RTCVALH but the block diagram (the only place RTCC Clock Domain is mentioned) does not include those registers. They are in the CPU Clock Domain according to the diagram.
 

MMcLaren

Joined Feb 14, 2010
861
Sounds like the RTCSYNC interval is one second. Is the RTCSYNC "window" shorter than that?

Got a link to the documentation that you're citing?

Regards, Mike
 
Last edited:

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
Once you sync to RTCSYNC read all registers without waiting.

Have you worked with these on board RTCCs? You are aware to get to all the registers you need to set the point 4 times? It is supposed to auto decrement for you but I have yet to get that to work reliably plus as I mentioned I don't see how it would work reading the registers more than once.


I changed my code where I read the registers all at the same time but waiting for each register read but it still really improved the speed of reading the registers.
 
Top