![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
vsmguy
Joined: 13 Jan 2007 Posts: 91
|
delay_us has a spurious check that introduces error |
Posted: Mon Jul 12, 2010 9:58 pm |
|
|
For delays less than 153uS, CCS C generates the delay inline yeilding a 100% accurate delay.
Above 154uS ( and < 256uS ), CCS C uses a function call.
This function has a spurious check that introduces error into what, otherwise, could have been a 100% accurate delay.
Let's have a look:
Code: | .................... volatile int8 a = 255;
0199: MOVLW FF
019A: MOVWF 21
....................
.................... delay_us( a );
019B: MOVF 21,W 1
019C: MOVWF 22 1
019D: GOTO 01D 2
( .. function body below .. )
.................... #use delay(clock=20000000)
*
001D: MOVLW 03 1
001E: SUBWF 22,F 1
001F: BTFSS 03.0 1/2 ( is argument value < 3uS ? If so, exit. Hence, this function delays a min of 13 ticks. whatever be the argument value )
0020: GOTO 02B 2
0021: MOVLW 22 1
0022: MOVWF 04 1
0023: BCF 03.7 1
0024: MOVF 00,W 1
0025: BTFSC 03.2 1/2
0026: GOTO 02B 2
[ I DO NOT understand why this check ( lines 25 and 36 ) are there as this is ALWAYS going to fail ( there is not code path leading to 25 either! ).
I am complaining about these lines ( esp. the check at 25 that always fail because this introduces the error in the delay ( the GOTO is essentially a NOP ) - otherwise this would have been a 100% accurate delay :-( ]
0027: GOTO 029 2
0028: GOTO 029 2
0029: DECFSZ 00,F 1/2
002A: GOTO 028 2
[ Loop 27 to 2A gives consumes 5( argument - 1 - 3 (subtracted at line 1E)) + 4 ticks ]
002B: BCF 0A.3 1
002C: BCF 0A.4 1
002D: GOTO 19E (RETURN) 2 |
Hence,
Quote: | for uS = 200, total ticks = 8 ( till & incl. skipped/nop line 20 ) + 6 + [ 5(196) + 4 = 984 ] + 4 = 1002 ticks ( expected 200/0.2 = 1000 ticks )
for uS = 255, total ticks = 8 ( till & incl. skipped/nop line 20 ) + 6 + [ 5(251) + 4 = 1259 ] + 4 = 1277 ticks ( expected 255/0.2 = 1275 ticks )
|
This is an error of 0.002% - not good for time critical code!
This could be fixed by CCS by removing the spurious check at lines 25 and 26.
What's the raison d'etre for those lines?
If I am missing something here, please let me know! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 12, 2010 10:18 pm |
|
|
You are the first person to care if it's off by .002 % or whatever.
Ring up CCS and demand satisfaction. |
|
![](templates/subSilver/images/spacer.gif) |
vsmguy
Joined: 13 Jan 2007 Posts: 91
|
|
Posted: Mon Jul 12, 2010 10:41 pm |
|
|
It's not about the inaccuracy.
It's about the spurious check making the delay inaccurate.
Had those two lines not being there - it would have been 100% accurate.
( why handcode a delay - as I have to do now for accuracy - when you could have the library do it! )
BTW - Does my analysis look correct? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19387
|
|
Posted: Tue Jul 13, 2010 2:40 am |
|
|
What compiler version?.
You comment on their not being routes to some parts of the code. Yet looking through the code, I can see routes to every line. So 'no', I don't think your analysis is correct. The test at 25, is for if the incoming value equalling 22uSec.
Seriously, you are not going to generate a variable delay, that gives 100% accuracy over the entire possible range. The CCS fixed delays do (easy, since they can pad the code with single nops as needed), but a variable delay, will always have the overhead of reading the variable, tetsing to see what it is, etc. etc.. The listing you post, is not exactly what is generated by the current compiler, which takes fractionally longer to loop, and so has a higher minimum value, but does then give accurate values at the top end. In a sense you have the trade off, that increasing the accuracy at the 'top', has increased the minimum time taken.
If you want 'uSec' accuracy, program a timer, and just test when the interrupt flag sets.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
vsmguy
Joined: 13 Jan 2007 Posts: 91
|
|
Posted: Tue Jul 13, 2010 5:26 am |
|
|
Ttelmah wrote: | What compiler version?. |
4.107
Ttelmah wrote: |
You comment on their not being routes to some parts of the code. Yet looking through the code, I can see routes to every line. |
[/quote]
I was talking about no loop/goto pointing back to 25.
The check at 25 is to check if the ( input argument - 3 ) is 0 is not - which is very pointless, as an input check has already been done at 1F.
Ttelmah wrote: |
So 'no', I don't think your analysis is correct.
|
Leaving out the above analysis of 25, don't you agree with the remaining portion? :-)
Ttelmah wrote: |
The test at 25, is for if the incoming value equalling 22uSec.
|
The test at 25, is for if the incoming value stored at INDF ( 00 ).
The INDF was loaded with register 22 at lines 21 and 22.
The value of register 22 is a copy of the input parameter less 3 ( lines 1D, 1E ) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19387
|
|
Posted: Tue Jul 13, 2010 6:48 am |
|
|
Start at the beginning.
The code subtracts 3.
If there is a _carry_ (the requested uSec value was less than this), it drops out immediately. If it drops out at this point, including the exit code, it uses 11uSec, which is 2.2uSec.
Then it does some initialisation using five more machine cycles, and tests if the subtraction had resulted in zero. If so, it drops out at the second test. Again as close as possible.
Nothing 'points back to 25'. The code jumps to the exit at 2B.
The only code path, except the earlier exit, _always_ leads to location 25.
Code: |
#include <16f877A.h>
#fuses HS, NOLVP, NOWDT, PUT
#use delay (clock = 20000000)
void main ()
{
int8 a2;
a2=255;
delay_us(a2);
a2=3;
delay_us(a2);
a2=2;
delay_us(a2);
while(true);
}
|
Put this into MPLAB. Put a breakpoint at the entry to each delay. Reset the stopwatch at this point. Put another breakpoint on the instruction after each delay. You get:
255uSec (spot on)
3.4uSec (still less than 0.5uSec error)
2.2uSec (same comment)
This last is the minimum delay generated by the code. 11 instructions.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Jul 13, 2010 3:48 pm |
|
|
Quote: | This is an error of 0.002% - not good for time critical code! | I'm curious what kind of application requires this accuracy. Could you please enlighten us?
If you tell us what you want to achieve we might be able to suggest you another solution.
Just wondering.... 0.002% == 20ppm
Have you checked the accuracy of your clock? Most likely your crystal will have a larger frequency spread over your application's operating temperature range. |
|
![](templates/subSilver/images/spacer.gif) |
vsmguy
Joined: 13 Jan 2007 Posts: 91
|
|
Posted: Tue Jul 13, 2010 6:50 pm |
|
|
ckielstra wrote: |
Just wondering.... 0.002% == 20ppm
Have you checked the accuracy of your clock? Most likely your crystal will have a larger frequency spread over your application's operating temperature range. |
I was being pedantic :-D |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Jul 13, 2010 11:57 pm |
|
|
Quote: | I was being pedantic. |
Your previously reported result is incorrect though, or at least not valid for PCM V4.107. As Ttelmah mentioned, you get a delay exact to the us, for longer delay values and int8 delay parameter. The said error of 1002 versus 1000 cycles would mean 0.2 rather than 0.002 %, by the way.
Using an int16 parameter introduces an additional error however. Apparently CCS didn't see a necessity to provide separate delay_us versions for 8 and 16 bit parameters, which would be inappropriate also in my opinion.
In a practical designs, the programmed delay always adds to the execution time of the delayed action, so an empirical correction seems unavoidable in any case.
I basically appreciate pedantic software development - in the right place. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|