Reading RTC Count register

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi I am using a ATtiny817 xplained Mini , I am trying to read RTC CNT register but i could not see the value being updated? Adding to that should i disable the Overflow interrupt flag before reading?

 

uint16_t Cnt = RTC.CNT; //Can i read by this way?

 

Thanks,

Jaivvignesh | Associate Firmware Developer

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jaivvignesh wrote:
but i could not see the value being updated?
That rather suggests it's not the line reading it we need to see but the lines above that configured the RTC and attempted to start it (but seem to have failed).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My concern is whether we can read it by that way ?

Thanks,

Jaivvignesh | Associate Firmware Developer

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Yes that is how you would read a 16 bit register. If I build:

volatile uint16_t result;

int main(void)
{
	result = RTC.CNT;
	while(1);
}

it generates:

	result = RTC.CNT;
  56:	80 91 48 01 	lds	r24, 0x0148	; 0x800148 <__TEXT_REGION_LENGTH__+0x700148>
  5a:	90 91 49 01 	lds	r25, 0x0149	; 0x800149 <__TEXT_REGION_LENGTH__+0x700149>
  5e:	80 93 00 3e 	sts	0x3E00, r24	; 0x803e00 <_edata>
  62:	90 93 01 3e 	sts	0x3E01, r25	; 0x803e01 <_edata+0x1>

as you can see the 16 bit read is actually done with two 8 bit reads and two 8-bit stores.

 

BTW as you will have read in the 817 datasheet:

 

You can see above that the compiler does reads from 0x148 then 0x149 so it guarantees the low, then high read order when you read the combined 16 bit "CNT" register.

Last Edited: Fri. Oct 11, 2019 - 09:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As the quote above says, I think you need to read low byte then the temporary register.  Maybe something like ...

 

uint16_t read_rtc() {
  union { uint16_t tv; struct { uint8_t lo; uint8_t hi; }; } time;
  time.lo = RTC.CNTL; /* read low byte first */
  time.hi = RTC.TEMP; /* read high byte from temp buffer */
  return time.tv;
}

Not sure about the ordering of lo vs hi.  I wrote that way because AVR is little endian.

Last Edited: Fri. Oct 11, 2019 - 05:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, you do not have to do that. As Cliff demonstrated, the compiler does that for you. Simply

 

result = RTC.CNT;

works.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

No, you do not have to do that. As Cliff demonstrated, the compiler does that for you. Simply

 

result = RTC.CNT;

works.

 

Jim

 

Well, I'm not convinced since CNT is at offset 8, 9, while TEMP is at offset 4, according to the datasheet.  If you don't get the buffered value you risk reading an incremented value (i.e., 0xFF, 0x00 increments to 0x00, 0x10, and you read as 0xFF, 0x10).

 

Last Edited: Fri. Oct 11, 2019 - 08:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>Well, I'm not convinced 

 

The read of the low register triggers a read of the high register in the same cycle, and the high byte gets put into the temp register. The value you read from the low byte is now 'paired' with the byte in the temp register. The read of the high byte (to complete the 16bit read) then reads the temp register (even though you specified the high byte).

 

A read of the high byte is a read of the temp register.

The write of a low byte is a write to the temp register.

Its all transparent to us, and with the compiler knowing what is required, you just simply access the 16bit register as a 16bit register.

 

What can be a problem, and is easy to overlook, is if you are in your main code wanting to read CNT for some reason, and you also have an isr that also reads or writes to that register. Your main code read of the low byte is just done, now the isr fires, the isr reads or writes to CNT (and possibly a new value is in now in temp), now your main code continues to read the high byte (transparently via temp), but the high byte (temp) may now be unrelated to the copy you were supposed to have that matches your low byte read. In this case you would have to protect the CNT read in the main code. I'm not sure how common this is, and I can't say I pay as much attention to it as I should, but it probably doesn't happen a whole lot since the isr will be the one dealing with these registers when using an isr.

 

So I guess the thing to watch out for, is if you are accessing a 'moving' 16bit register that utilizes a temp register, and you access it in any non-isr code, you may want to check if you have an isr also accessing that register.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks.