Hello.
I'm having troubles with a custom delay functions that never returns. Same code 
compiled with PICC Lite compiler perform as expected.

This code works fine:

void delay_ms(unsigned int ms)
{
     int i;
     while (ms--) for (i = 0; i < 440; ++i);
}

But the delay_ms() below never returns and prints endless line of 'd'-s.

#define TMR0_PER_MS 20 // TMR0_PER_MS/(20MHz/4 clocks per cycle/256 prescaler) 
= 
0.001s (1ms)

void tx(char c) {
     while (!TXIF); // wait for transmitter to become free
     TXREG = c;
}

unsigned char start_timer(void)
{
     unsigned char tmr;
     T0IF = 0;
     // here is a short window of TMR0 overflow
     tmr = TMR0;
     if (tmr != 255)
         T0IF = 0;
     return tmr;
}

int time_since(unsigned char tmr_start)
{
     int tm;
     if (T0IF) { // if timer overflow
         tm = 255 - tmr_start + TMR0;
     } else {
         tm = TMR0 - tmr_start;
         if (tm < 0) // overflow happened just after T0IF is read
             tm = 255 - tmr_start;
     }
     return tm;
}

void delay_ms(unsigned int ms)
{
     unsigned char tmr_start, debug_skip_i = 0;
     while (ms--) {
         tmr_start = start_timer();
         if (!debug_skip_i++)
             tx('d');
         while (time_since(tmr_start) < TMR0_PER_MS);
     }
}

It doesn't matter how big is the delay_ms() argument: 5000 or 50 - it loops 
endlessly in while(ms--).
Changing delay_ms() argument to unsigned char make it exit while() loop, but 
the 
resulting delay is wrong and much less than required. Ie.
int i;
for (i = 0; i < 100; ++i) delay_ms(100);
produces almost no delay.

The start_timer()/time_since() might look like an overkill but I use them in 
other parts of the code.

Here are the assembler listings generated by the compiler:
---------------------------------------
1. simple but good

_delay_ms       ;Function start
; 2 exit points
;       .line   96; "pic-fire.c"        void delay_ms(unsigned int ms)
         BANKSEL r0x1012
         MOVWF   r0x1012
         MOVF    STK00,W
         MOVWF   r0x1013
_00137_DS_
;       .line   108; "pic-fire.c"       while (ms--) for (i = 0; i < 440; ++i);
         BANKSEL r0x1013
         MOVF    r0x1013,W
         MOVWF   r0x1014
         MOVF    r0x1012,W
         MOVWF   r0x1015
         MOVLW   0xff
         ADDWF   r0x1013,F
         BTFSS   STATUS,0
         DECF    r0x1012,F
         MOVF    r0x1014,W
         IORWF   r0x1015,W
         BTFSC   STATUS,2
         GOTO    _00143_DS_
         MOVLW   0xb8
         MOVWF   r0x1014
         MOVLW   0x01
         MOVWF   r0x1015
_00142_DS_
         MOVLW   0xff
         BANKSEL r0x1014
         ADDWF   r0x1014,F
         BTFSS   STATUS,0
         DECF    r0x1015,F
         MOVF    r0x1014,W
         IORWF   r0x1015,W
         BTFSS   STATUS,2
         GOTO    _00142_DS_
         GOTO    _00137_DS_
_00143_DS_
         RETURN
; exit point of _delay_ms


---------------------------------------
2. using timer, wrong

_delay_ms       ;Function start
; 2 exit points
;       .line   85; "pic-fire.c"        void delay_ms(unsigned int ms)
         BANKSEL r0x1012
         MOVWF   r0x1012
         MOVF    STK00,W
         MOVWF   r0x1013
;       .line   88; "pic-fire.c"        while (ms--) {
         CLRF    r0x1014
_00142_DS_
         BANKSEL r0x1013
         MOVF    r0x1013,W
         MOVWF   r0x1015
         MOVF    r0x1012,W
         MOVWF   r0x1016
         MOVLW   0xff
         ADDWF   r0x1013,F
         BTFSS   STATUS,0
         DECF    r0x1012,F
         MOVF    r0x1015,W
         IORWF   r0x1016,W
         BTFSC   STATUS,2
         GOTO    _00145_DS_
;       .line   89; "pic-fire.c"        tmr_start = start_timer();
         CALL    _start_timer
         BANKSEL r0x1015
         MOVWF   r0x1015
;       .line   90; "pic-fire.c"        if (!debug_skip_i++)
         MOVF    r0x1014,W
         MOVWF   r0x1016
         INCF    r0x1014,F
         MOVF    r0x1016,W
         BTFSS   STATUS,2
         GOTO    _00139_DS_
;       .line   91; "pic-fire.c"        tx('d');
         MOVLW   0x64
         CALL    _tx
_00139_DS_
;       .line   92; "pic-fire.c"        while (time_since(tmr_start) < 
TMR0_PER_MS);
         BANKSEL r0x1015
         MOVF    r0x1015,W
         CALL    _time_since
         BANKSEL r0x1017
         MOVWF   r0x1017
         MOVF    STK00,W
         MOVWF   r0x1016
;signed compare: left < lit(0x14=20), size=2, mask=ffff
         MOVF    r0x1017,W
         ADDLW   0x80
         ADDLW   0x80
         BTFSS   STATUS,2
         GOTO    _00153_DS_
         MOVLW   0x14
         SUBWF   r0x1016,W
_00153_DS_
         BTFSC   STATUS,0
         GOTO    _00142_DS_
;genSkipc:3225: created from rifx:0xbfb4db30
         GOTO    _00139_DS_
_00145_DS_
         RETURN
; exit point of _delay_ms

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to