|
|
View previous topic :: View next topic |
Author |
Message |
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
Is get_timerX() atomic? |
Posted: Thu Jan 31, 2019 3:44 pm |
|
|
I'm wondering whether the get_timerX() CCS function disables interrupts during the read of the 16-bit timer1 value, and re-enables interrupts after the function exits. I can't find this information either by searching this forum or by reading the compiler manual.
My worry is that if this function does not disable interrupts during the read/return, the timer1 overflow interrupt can occur in between reading 2 bytes, then timerX overflows back to 0x0000, and return the incorrect timer1 value to the place get_timerX() was originally called. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Thu Jan 31, 2019 4:16 pm |
|
|
make small program, compile, dump listing. The code will be there...might need to say 'list' though...I'm too dang cold to think.....rrrgh...
Jay
Ok, I added these two lines of code..
542: x=get_timer0();
08FE 50D6 MOVF 0xfd6, W, ACCESS
0900 6E27 MOVWF 0x27, ACCESS
543: x=get_timer3();
0902 50B2 MOVF 0xfb2, W, ACCESS
0904 6E27 MOVWF 0x27, ACCESS
..appears they only read the SFR.
now you'll have to read the datasheet to see if the PIC internal hardware does anything....
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19536
|
|
Posted: Fri Feb 01, 2019 2:27 am |
|
|
It won't be atomic.
CCS does not protect anywhere by default against events like this.
This is why you have to either disable interrupts yourself, or use a 'multiple
read' test like:
Code: |
do {
val=get_timer0();
} while (val !=get_timer0());
|
Here the code reads the timer, then tests that the timer is still the same.
If it isn't, it loops and reads it again.
This is a standard way to load multi byte values, that may be changed
by interrupts.
However, the timer hardware itself does ensure that the timer can't advance
during an actual read/write. Most of the PIC timers support what is called
'16bit' mode, and this will be enabled by the default CCS code. In this,
when you read or write the low byte of the timer register, the high byte
is automatically loaded into the buffer register at the same moment.
When reading, you have to read low, then high, and when writing, you
have to store the high byte first, and then write the low byte. In the
case of the read, the value is recorded at the moment you read from
the low register, while when writing, the physical write occurs when you
write to the low register.
So the transfer itself is 'atomic', but the actual timer operation is not.
The timer will still be running when the value is latched, so an interrupt
can occur. The CCS code cannot 'know' that you are using the interrupt
to handle presumably a 'high' counter to extend the number of bits being
used, so if this changes while you are reading the timer register, this
extended value will not match the value you receive from the timer itself.
However you will have an issue even if you disable interrupts. Think about it
The timer is running. You disable interrupts and read the 'pair' of the
timer value itself, and your extended counter. You then enable interrupts.
However the timer wrapped between the moment you read the timer
register, and the extended register, or between reading the extended
register, and the timer register. Either way, the count in the extended
counter, mismatches the count in the timer register itself....
The approach shown above of repeat reading, can be extended to the
longer timer value (however many bits you are using), and is the safe
way to handle such a read. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|