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