For C30, there is a GetTickCopy() function which basically tries to copy the ticks in some global module variable, to be read by GetTick() and similar functions.
DWORD dwTempTicks; WORD_VAL wTemp; IEC0bits.T1IE = 1; // Enable interrupt Nop(); IEC0bits.T1IE = 0; // Disable interrupt // Get low 2 bytes wTemp.Val = TMR1; vTickReading[0] = wTemp.v[0]; vTickReading[1] = wTemp.v[1]; //((WORD*)vTickReading)[0] = TMR1; // Correct corner case where interrupt increments byte[4+] but // TMR1 hasn't rolled over to 0x0000 yet dwTempTicks = dwInternalTicks; // Issue nr. #1 //if(((WORD*)vTickReading)[0] == 0xFFFFu) if(wTemp.Val == 0xFFFFu) // Issue nr. #2 dwTempTicks--; // Get high 4 bytes vTickReading[2] = ((BYTE*)&dwTempTicks)[0]; vTickReading[3] = ((BYTE*)&dwTempTicks)[1]; vTickReading[4] = ((BYTE*)&dwTempTicks)[2]; vTickReading[5] = ((BYTE*)&dwTempTicks)[3]; } while(IFS0bits.T1IF); IEC0bits.T1IE = 1; // Enable interrupt
For issue nr. #1, the dwInternalTicks is updated in TMR interrupt so one can observe this is a potentially unexpected behavior when TMR interrupt will hit between the DWORD assignment which is not atomic on 16 bit cores like PIC24. Must be protected like this, where flag is set in TMR interrupt.
do{ flag = 0; dwTempTicks = dwInternalTicks; } while(flag);
Issue nr. #2 takes me few days of deep digging for occasional abnormal behavior.
If wTemp.Val become 0xFFFF while dwTempTicks is 0 then the correction dwTempTicks-- will be wrong applied and GetTick() function will return a huge value.
All timeouts running at this moment will be corrupted. I just comment this correction :)
Anyhow, I also noticed Tick() variables declared "static volatile" which I guess makes volatile redundant.
In some circumstances, the GetTick() returns the ticks in the past (lower than actual reading) which shouldn't happen in any circumstances. This is due to bad reading of TMR1 in GetTickCopy() which is used as 16 bit LSB of returned ticks. TMR1 can rollover during read in current implementation.
I preferred to ignore LSB and all the problems vanished but I'm sure can be found some workaround.
vTickReading[0] = 0;
vTickReading[1] = 0;
Edi