View previous topic :: View next topic |
Author |
Message |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
is this too crazy compiler behavior?? |
Posted: Sat Dec 10, 2011 5:17 pm |
|
|
Been using ver 4.085 very happily - mostly with 18F parts - since 4.085 was released.
Just moved a simple timer0 , polled handler - to count down 10msec increments - that works like a charm on many 18f parts like 18f4620 4520 2423 452 etc etc etc - with timer0 in 8 bit mode -
Today I tried to use the same code on an 18f887 - but found that
--woundtix - on the f887 caused a near instant exit!
the routine exited instantly in under 1 sec when told to use a 10 sec delay.
I traced my problem to decrementing a declared
unsigned int16 woundtix - where - in each case using 8 mhz int clock- no PLL or fuse funnies etc . and polled from main() -
Check out this LST extract - where I was forced to switch to using
the second method of decrementing to keep the code working properly
on the 16F part .. bizarre - or is it me ??
Code: |
.................... void Time0Up(void) {
.................... if ( T0IF ) { // [IF] timer rollover flag set
*
01EC: BTFSS 0B.2
01ED: GOTO 203
.................... set_timer0(100); // [THEN] start next round of 10 msec
01EE: MOVLW 64
01EF: MOVWF 01
.................... T0IF = 0; // clear t0if
01F0: BCF 0B.2
....................
.................... if ( woundtix ) --woundtix; // BAD --unsigned INT16
01F1: MOVF 31,W // THIS attempt to decrement caused VERY
01F2: IORWF 32,W // rapid reduction of unsigned int16 woundtix
01F3: BTFSC 03.2 // aND WAS replaced by the following method
01F4: GOTO 1F9 // which gives the proper result
01F5: MOVF 31,W // put low byte in workreg - test zero
01F6: BTFSC 03.2 // if !=zero skip the dec upper byte
01F7: DECF 32,F // what abt carry ??
01F8: DECF 31,F // ????
.................... if ( woundtix ) WoundTix=woundtix-1; // works
01F9: MOVF 31,W // as intended
01FA: IORWF 32,W
01FB: BTFSC 03.2
01FC: GOTO 203
01FD: MOVLW 01
01FE: SUBWF 31,F
01FF: MOVLW 00
0200: BTFSS 03.0
0201: MOVLW 01
0202: SUBWF 32,F
.................... }
.................... // count A 10ms event stream as well
.................... // end of line checking for timing all done
.................... if ( 0 == WoundTix ) { // do stuff
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Dec 11, 2011 8:15 am |
|
|
Quote: | Today I tried to use the same code on an 18f887 |
16F887?
The skip before is the carry.
The code is working correctly so far. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Dec 11, 2011 9:46 am |
|
|
all i know is that the FIRST version - using --woundtix;
does NOT "count right" - based on a stopwatch test -
and ONLY when compiled for a 16f887 !!!
same code - same everything - works perfectly on an 18F4620 --
i was only porting the code from the 18f to reduce the cost of production on a fully tested and working prodcut.
anyway - the second one DOES perform properly -- on both PICS-
it was only after a lot of head scratching that i resorted to:
var=var-1; syntax - and was puzzled as heck as to what was going on.
i only posted because i was shocked to find very basic code that was "broken" like that. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 11, 2011 3:01 pm |
|
|
I didn't find a problem.
First I made the program below in MPLAB. I put breakpoints on the line
that sets woundtix to 0xFFFF and on the while(1) line at the end. I enabled
the MPLAB stopwatch function. I ran the program until it stopped at the
first breakpoint in MPLAB simulator and then I zeroed the Stopwatch.
Then I ran it to the last breakpoint. I got a stopwatch duration of
170.4924 ms for the loop code:
Code: |
#include <16F887.h>
#fuses HS, NOWDT
#use delay(clock=20M)
//==========================================
void main()
{
int16 woundtix;
woundtix = 0xFFFF;
while(woundtix != 1)
{
if(woundtix) --woundtix;
}
while(1);
} |
Then I edited the above program and replaced the loop code with this:
Code: |
while(woundtix != 1)
{
if(woundtix) woundtix = woundtix-1;
}
|
This time I got 196.706 ms. It's a bit longer than the first program, but
not enormously longer. But the longer execution time is be expected
because it takes a couple more ASM instructions to do the subtraction,
compared to the decrement.
These tests were done with vs. 4.085. So I didn't see a problem. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Dec 11, 2011 4:04 pm |
|
|
My point is, I don't see a problem with the code shown in your post.
if(woundtix) --woundtix compiles to identical assembly level code in recent CCS C versions. Nevertheless,
to make the problem understandable, please post a complete compilable example that allows to reproduce it.
There may be something that doesn't reveal in the shown example. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Dec 11, 2011 8:06 pm |
|
|
found it after more head scratching
there are various #includes - involved here
i was fooling myself with a fixed #bit T0IF definition that was correct for 18F family - located earlier in the program - but no so hot for 18F cuz it reads as an address beyond 16F reg space - as a '1' no matter how often i tried to clear it .....so T0IF was ALWAYS set etc etc etc
when i changed what i thought was the faulty math - i had also at the same time - switched to the include file i had used with a much older 16F project -- that happened to use the correct register bit address for T0IF -
it was ending early because T0IF would not stay clear - no ta math bug ;-))
i am happy to report that both means of decrementing do work after all.
mea culpa |
|
|
andrewg
Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia
|
|
Posted: Sun Dec 11, 2011 9:25 pm |
|
|
Code: | T0IF = 0; // clear t0if |
Is that your only use for T0IF? If so, then: Code: | clear_interrupt(INT_TIMER0); | would be the portable way of doing that. _________________ Andrew |
|
|
|