Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo


Does pic16 support function call arguments?

  • I have been working on a piece of code where I try to pass arguments in function calls & it doesn't work.  I'm using the nightly build from Dec. 12, 2004.

    If I make a global variable & use that for passing purposes, that works, but standard funtion argument passing isn't working.

    Any help would be very appreciated.


    C file:

    #include <pic18f452.h>

    /* Set up the stack */
    #pragma stack 0x5ff 31

    #define USE_ASSEMBLY (1)

    void fn_a( char c )
        if( 0x57 == c ) {
            /* do_something_1 */
        } else {
            /* do_something_2 */

    void main( void )
        fn_a( 0x57 );

    do_something_2 always gets executed.

    Here's the makefile:

    CC    = /usr/bin/sdcc
    ASM    = /usr/bin/gpasm
    LNK    = /usr/bin/gplink
    CFLAGS    = -mpic16 -p18f452
    SOURCES    = serial.c

    serial.hex : serial.c
        $(CC) $(CFLAGS) $<

    • Brian Cherdak
      Brian Cherdak

      A couple of thoughts:

      1) Typically in logical compares (i.e if( 0x57 == c ) , the constant is on the right hand side of the comparison.  Your style jumped out at me.  I don't know if SDCC is that picky about things.

      2) This could be an endian thing, I do 8051 not PIC, so I don't know.  For instance, by passing the constant 0x57, you could be passing a 16 bit integer as either 0057 hex or, 5700 hex.  Your function is only comparing 57 hex. Try either passing a declared variable of type char or casting the constant (e.g. (char) 0x57)  to see if that changes things. Also, try the comparison to 0 to detect if it's an endian thing.

      Best Regards

    • This is a little off-topic, but how come that you can compile the serial.c file for PIC18F452? Is the linux port of SDCC more complete (just kidding...) from the Windoze port that I'm using (install version).


    • Brian,

      I have tried your suggestion of swapping my if args -- they are working correctly, it has something to do with the arguments getting passed in.

      Additionally I tried your other suggestion of assigning the value to a char variable & passing that in - no luck.

      I have upgraded to the latest CVS code (Jan 7th, 2005) and still no luck.

      Regarding how I'm able to compile to 18f452 & you can't -- I'm not sure.  It probably depends on the version you are running (cvs or released) or some difference due to windows building.

      I think my arg problem may have something to do with the stack, but I'm at a loss for what I'd need to do differently to fix a stack problem.

      Any ideas or examples that run on an actual pic?


      • Brian Cherdak
        Brian Cherdak


        Yes, It does sound like a stack prob. You need to check the assembly listing file to see if the stack is initialized to a valid memory address.  I'm an 8051'er myself and I can show you the listing in main where the stack is initialized.  I think that there are some command line args that specify stack start and stack depth.

        You can also see if there is a flag to specify register passing vs. call frames on the stack.  Try the register model and see if it works.  If so, then the problem is definitely stack.

        Finally, if you have a nice hardware debug environment, try writing a function that passes back the argument.  If the stack doesn't exist, you get something like 0xFF or 0x0 for any function you pass.  In fact, you could try your subroutine but compare to 0xff and see if the true case always works.


    • Yes, pic16 DOES support argument passing.  The problem was that I thought that when I did a #pragma for the stack & the size that I was specifying the upper bound in memory of the stack.  What #pragma stack REALLY points to is the LOWER bound in memory of the stack.

      I will add to a bug I have open about #pragma stack (related to pic16) a request to clarify this.

      Thanks for everyone's help.


    • The reason the upper & lower bounds made the difference for me was that memory from 0x000 -> 0x5ff exists for a 18f452 & memory from 0x600  on (to a point) doesn't exist unless you add external hardware.  I have added no hardware & was trying to use memory that doesn't exist & returns '0' if it is read from.