gnupic@linuxhacker.org

gnupic@linuxhacker.org


Subject: More problems with SDCC/PIC
From: Rick Mann
Date: Fri, 26 Sep 2003 23:24:47 -0700

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


gnupic@linuxhacker.org