For loop becomes infinite on 18f4550

  • WizardStan

    WizardStan - 2013-08-24

    Perhaps I am being completely daft. Can someone take a look and tell me what I'm doing wrong.
    $ sdcc -v
    SDCC : mcs51/gbz80/z80/z180/r2k/r3ka/ds390/pic16/pic14/TININative/ds400/hc08/s08 3.3.0 #8604 (May 11 2013) (Linux)
    $ gpasm -v
    gpasm-1.2.0 #980 (Aug 19 2013)

    #include <pic18f45k50.h>
    void main(void)
        char f = 0;
        unsigned char c1;
        unsigned char c2;
        PORTA = 0;
        DDRA = 0;
        PORTB = 0;
        DDRB = 0;
        while (1)
            if (f == 0)
                PORTA = 0x55;
                f = 1;
            } else
                PORTA = 0xAA;
                f = 0;
            for (c1 = 0; c1 < 100; c1++)
                PORTB = 0x40;
                PORTB = 0x80;
            for (c2 = 0; c2 < 100; c2++)
                PORTB = 0x10;
                PORTB = 0x20;

    $ sdcc --use-non-free -mpic16 -p18f4550 main.c
    + /usr/local/bin/sdcpp -nostdinc -Wall -Dpic18f4550 -D18f4550 -DSDCC_PIC18F4550 -DSTACK_MODEL_SMALL -DSTACK_MODEL_SMALL -obj-ext=.o -DSDCC_USE_NON_FREE -DSDCC_USE_NON_FREE -DSDCC=3_3_0 -DSDCC=330 -DSDCC_REVISION=8604 -DSDCC_REVISION=8604 -DSDCC_pic16 -DSDCC_pic16 -Dpic16 -DSTDC_NO_COMPLEX -DSTDC_NO_THREADS -DSTDC_NO_ATOMICS -DSTDC_NO_VLA -isystem /usr/local/bin/../share/sdcc/include/pic16 -isystem /usr/local/share/sdcc/include/pic16 -isystem /usr/local/bin/../share/sdcc/include -isystem /usr/local/share/sdcc/include -isystem /usr/local/bin/../share/sdcc/non-free/include/pic16 -isystem /usr/local/share/sdcc/non-free/include/pic16 -isystem /usr/local/bin/../share/sdcc/non-free/include -isystem /usr/local/share/sdcc/non-free/include main.c
    + /usr/local/bin/gpasm -DSTACK_MODEL_SMALL -D__STACK_MODEL_SMALL -o main.o -c main.asm
    + /usr/local/bin/gplink -I/usr/local/bin/../share/sdcc/lib/pic16 -I/usr/local/share/sdcc/lib/pic16 -I/usr/local/bin/../share/sdcc/non-free/lib/pic16 -I/usr/local/share/sdcc/non-free/lib/pic16 -w -r -o main main.o crt0i.o libdev18f4550.lib libsdcc.lib
    message: using default linker script "/usr/local/share/gputils/lkr/18f4550_g.lkr"

    When I compile this code, I expect PORTA pins to flip flop between 010101 and 101010, and PORTB pins 4/5 and 6/7 to flicker really fast. What I get is PORTA fixed on 0x55 and PORTB pins 6/7 lit (but dimmer, due to manual PWM).
    If I cut out the if/else statement then I get PORTB flickering really fast between 4/5 and 6/7 as I expect.
    My instinct is that something in that if statement is causing the for(c1) loop to become infinite. Somehow, I don't know why. I can replicate it with a loop within a loop as well. "for(c1...) { for (c2...) {} }", PORTB pins 4/5 are lit up and 6/7 blink once as it starts and then never again
    These are not uncommon structures so I can't imagine it's a bug or it would have been caught and flagged as major a long time ago. I have to be doing something wrong.
    Can anyone offer any insight please?
    Thank you!

  • Raphael Neider

    Raphael Neider - 2013-08-24


    the 45k50 and the 4550 are distinct devices, maybe you should decide on one of them consistently (-p18f45<X>50, #include <pic18f45<X>50.h>).

    The problem more likely is once more the XINST config bit. Make sure to DISABLE the extended instruction set (#pragma config XINST=OFF).

    Happy hacking,

  • WizardStan

    WizardStan - 2013-08-24

    There is no pic18f4550.h*. There are only pic18f45j50.h and pic18f45k50.h files. The 45k50 header (being a drop in replacement for the 4550) contains all the registers at the same locations as the spec sheet I've got so I assumed that that was still the correct one. When I compile with "-p18f45k50" the resulting asm and hex are identical (apart from the one asm line which reads 45k50 instead) but I know that the 45k50 has been updated so is likely to have at least some new features (haven't fully explored, I'm fine with my old 4550s). If I encounter any other problems though I'll keep that in mind. Given that the 45k50 is a drop in replacement for the 4550 I don't expect there to be any so long as I stick to the stuff in the 4550 sheet but we shall see.

    BUT the specific problem in this case was indeed the XINST config. I thought it's supposed to default to off but my programmer for reasons is setting it to on. I manually force it to off and everything is beautiful again. I spent hours slamming my head against this last night. Thank you so much! And to be sure, I removed all config information from the hex file and it is still setting it on by default.

    (*) Ok, I lied. There IS an 18f4550.h. I swear I went looking for it and it wasn't there before. I tried #include it first and when that didn't work I did "find -name pic18f45*.h | sort" and I swear it wasn't there, just the 45j50 and 45k50. Apparently I am insane.

    Last edit: WizardStan 2013-08-24
  • Raphael Neider

    Raphael Neider - 2013-08-24

    I have now (sdcc rev. 8814) added a warning if

    (a) the targeted device supports XINST,
    (b) no #pragma config XINST=OFF is found in the current file, and
    (c) the current file defines main().

    This does trigger incorrect warnings if the #pragma is present in a different source file, but is probably the best I can do from within the compiler.

    This should prevent some head slamming and increase productivity ;-)


Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks