gnupic@linuxhacker.org
I was really hoping to use SDCC to develop my code, as I get the
implication that others are successfully using it. However, each time I
try to do something, it doesn't quite work.
In particular, I keep coming back to what seems to be a problem with
SDCC properly defining local variables (at least, loosely related to
this problem).
I'm trying to convert my ASM code into C. I'd like to duplicate this
simple 10 ms delay:
> ; --------------------------------------------------------------
> ;
> ; Delay10MS - Delay for milliseconds
> ;
> ; W contains the number of milliseconds to delay. The actual
> ; delay time is 10 X W milliseconds.
> ;
> ; Note that this routine is not exact, for two reasons. On the
> ; one hand, there are some cycles burned setting up the delay
> ; and in looping over the core delay routine. For another, if
> ; the crystal is not a power of two, then the prescaler gives us
> ; an atomic time unit that does not translate easily into integral
> ; millisecond periods.
> ;
> ; But, it's close enough for our purposes.
> ;
> ; --------------------------------------------------------------
>
> Delay10MS
> movwf temp1 ; Remember user-specified wait
>
> bcf INTCON,T0IE ; Disable the TMR0 interrupt, we're polling instead
> movlw b'10000111'
> bsf STATUS,RP0 ; Select Bank 1
> movwf OPTION_REG
> bcf STATUS,RP0 ; Select Bank 0
>
> delayFor10ms
> movlw d'217' ; 10 ms = 10e6 us / 256 = ~39 ticks of Timer 0
> movwf TMR0
> bcf INTCON,T0IF ; Clear the interrupt flag
>
> btfss INTCON,T0IF
> goto $-1 ; Loop until Timer 0 overflows
>
> bcf INTCON,T0IF
>
> decfsz temp1,F ; We need to delay 10 ms multiple times
> goto delayFor10ms
>
> return
This works by setting up a timer and then spinning in a tight loop
until the timer fires. Not very efficient, but works for my purposes.
When I try the following C code:
> void
> Delay10MS(UInt8 inCount)
> {
> T0IE = 0;
> OPTION_REG = 0x73;
>
> while (inCount-- > 0)
> {
> TMR0 = 217;
> T0IF = 1;
> while (T0IF == 0);
> T0IF = 0;
> }
> }
I get the following errors:
[arrow:lzd/Hardware/TurtleTimer] rmann% sdcc -mpic14 -p16f877 -I
/usr/share/gpasm/header/ turtle.c
Processor: 16f877
No registers saved on this pass
CLRF/MOVFW. instruction after MOVFW is:
*** pass 1, Saved 1 registers, total saved 1 ***
turtle.asm:469:Error [113] Symbol not previously defined (r0x20).
turtle.asm:482:Error [113] Symbol not previously defined (r0x20).
turtle.asm:488:Error [113] Symbol not previously defined (r0x20).
turtle.asm:489:Error [113] Symbol not previously defined (r0x20).
turtle.asm:490:Error [113] Symbol not previously defined (r0x20).
turtle.asm:491:Error [113] Symbol not previously defined (r0x20).
turtle.asm:501:Error [113] Symbol not previously defined (r0x20).
turtle.asm:506:Error [113] Symbol not previously defined (r0x20).
turtle.asm:508:Error [113] Symbol not previously defined (r0x20).
turtle.asm:510:Error [113] Symbol not previously defined (r0x20).
turtle.asm:516:Error [113] Symbol not previously defined (r0x20).
Can I not pass parameters to methods in SDCC/PIC?
The code that's generated also seems inefficient at best and incorrect
at worst:
> ;***
> ; pBlock Stats: dbName = C
> ;***
> ;entry: _Delay10MS ;Function start
> ; 2 exit points
> ;has an exit
> ;6 compiler assigned registers:
> ; r0x68
> ; r0x69
> ; r0x6A
> ; r0x6B
> ; r0x6C
> ; r0x6D
> ;; Starting pCode block
> _Delay10MS ;Function start
> ; 2 exit points
> ;#CSRC turtle.c 38
> ; Delay10MS(UInt8 inCount)
> MOVWF r0x20
> ;#CSRC turtle.c 40
> ; T0IE = 0;
> BCF (_T0IE >> 3), (_T0IE & 7)
> ;#CSRC turtle.c 41
> ; OPTION_REG = 0x73;
> MOVLW 0x73
> BSF STATUS,5
> MOVWF _OPTION_REG
> ;#CSRC turtle.c 43
> ; while (inCount-- > 0)
> MOVLW 0x01
> BCF STATUS,5
> MOVWF r0x20
> ;;99 CLRF r0x20
> ;; peep 11 - Removed redundant move
> ;;100 MOVF r0x20,W
> MOVLW 0x00
> _00108_DS_
> MOVF r0x20,W
> MOVWF r0x20
> DECF r0x20,F
> MOVF r0x20,W
> BTFSC STATUS,2
> GOTO _00111_DS_
> ;#CSRC turtle.c 45
> ; TMR0 = 217;
> MOVLW 0xd9
> MOVWF _TMR0
> ;#CSRC turtle.c 46
> ; T0IF = 1;
> BCF (_T0IF >> 3), (_T0IF & 7)
> MOVF r0x20,W
> BTFSS STATUS,2
> BSF (_T0IF >> 3), (_T0IF & 7)
> ;#CSRC turtle.c 47
> ; while (T0IF == 0);
> CLRF r0x20
> BTFSS (_T0IF >> 3), (_T0IF & 7)
> INCF r0x20,F
> _00105_DS_
> MOVF r0x20,W
> BTFSS STATUS,2
> GOTO _00105_DS_
> ;#CSRC turtle.c 48
> ; T0IF = 0;
> BCF (_T0IF >> 3), (_T0IF & 7)
> MOVF r0x20,W
> BTFSS STATUS,2
> BSF (_T0IF >> 3), (_T0IF & 7)
> GOTO _00108_DS_
> _00111_DS_
> RETURN
> ; exit point of _Delay10MS
I'm okay with the setup and teardown being a bit more complex, but the
loop "while (T0IF == 0);" (designated above by the comment #CSRC
turtle.c 47) expands into
> ;#CSRC turtle.c 47
> ; while (T0IF == 0);
> CLRF r0x20
> BTFSS (_T0IF >> 3), (_T0IF & 7)
> INCF r0x20,F
> _00105_DS_
> MOVF r0x20,W
> BTFSS STATUS,2
> GOTO _00105_DS_
Which seems far too complex and even incorrect (it never branches back
to the btfss T0IF).
Now, I realize SDCC/PIC is not complete, but is this an error in the
compiler? What about the "symbol not defined" errors for "r0x20"?
As always, answer are much appreciated!
TIA,
--
Rick