Change of Start Code for PIC 16FXX

2007-07-18
2013-03-12
  • franciscojar
    franciscojar
    2007-07-18

    Hi all!!!

    It is my first post, I hope the community can help me.

    I develop a PIC16F family programs in Ubuntu linux, but the start code does not fine to me.

    If I write:

    code.c
    ---------------------
    #define __PIC16F818
    #include "pic/pic16f818.h"

    void Int(void) interrupt 0
    {
    _asm nop _endasm;
    }

    void main(void)
    {
    _asm nop _endasm;
    }

    -----------------------

    Compile using:

    sdcc -mpic14 -p16f818 --lib-path /usr/share/sdcc/lib/pic -o bin code.c

    Appears:

    bin.asm, bin.cod, bin.hex, bin.lst, bin.o, bin.p

    bin.lst contains (I cutted the declarations to show you only the code):
    --------------------------
                                               STARTUP    code
    000000   0000     nop                          nop
                                                   pagesel __sdcc_gsinit_startup
    000001   2818     goto    0x18                    goto    __sdcc_gsinit_startup
                                               ;--------------------------------------------------------
                                               ; interrupt and initialization code
                                               ;--------------------------------------------------------
                                               c_interrupt    code    0x4
                                               __sdcc_interrupt
                                               ;***
                                               ;  pBlock Stats: dbName = I
                                               ;***
                                               ;entry:  _Int    ;Function start
                                               ; 0 exit points
                                               ;; Starting pCode block
                                               _Int    ;Function start
                                               ; 0 exit points
                                               ;    .line    4; "code.c"    void Int(void) interrupt 0
    000004   00f2     movwf    0x72                   MOVWF    WSAVE
    000005   0e03     swapf    0x3, w                 SWAPF    STATUS,W
    000006   0183     clrf    0x3                     CLRF    STATUS
    000007   1283     bcf    0x3, 0x5                 BCF    STATUS,5
    000008   1303     bcf    0x3, 0x6                 BCF    STATUS,6
    000009   00f1     movwf    0x71                   MOVWF    SSAVE
    00000a   080a     movf    0xa, w                  MOVF    PCLATH,W
    00000b   00f0     movwf    0x70                   MOVWF    PSAVE
    00000c   018a     clrf    0xa                     CLRF    PCLATH
    00000d   0000     nop                          nop
    00000e   0870     movf    0x70, w                 MOVF    PSAVE,W
    00000f   008a     movwf    0xa                    MOVWF    PCLATH
    000010   0183     clrf    0x3                     CLRF    STATUS
    000011   0e71     swapf    0x71, w                SWAPF    SSAVE,W
    000012   0083     movwf    0x3                    MOVWF    STATUS
    000013   0ef2     swapf    0x72, f                SWAPF    WSAVE,F
    000014   0e72     swapf    0x72, w                SWAPF    WSAVE,W
                                               END_OF_INTERRUPT
    000015   0009     retfie                       RETFIE   
                                              
                                               code_init    code
                                               __sdcc_gsinit_startup
                                                   pagesel _main
    000018   2816     goto    0x16                    goto _main
                                               ;--------------------------------------------------------
                                               ; code
                                               ;--------------------------------------------------------
                                               code_code    code
                                               ;***
                                               ;  pBlock Stats: dbName = M
                                               ;***
                                               ;entry:  _main    ;Function start
                                               ; 2 exit points
                                               ;has an exit
                                               ;; Starting pCode block
                                               _main    ;Function start
                                               ; 2 exit points
    000016   0000     nop                          nop
    000017   0008     return                       RETURN   
                                               ; exit point of _main
    ------------------------

    The "STARTUP code" is:

    000000  nop       (why?????)
    000001  goto 0x18 (go to the end of main + 1)
    .....
    000018  goto 0x16 (go to main)

    I want to change the "STARTUP code" to:
    000000  BCF  GIE  (Put GIE bit on STATUS = 0)
    000001  BTSC GIE  (Check if the GIE bit = 0)
    000002  goto  0   (if GIE is not 0, try again)
    000003  goto 0x16 (go to main)

    The above code is to ensure GIE bit is clear and no interrupts can ran.
    I found this code at microchip website and is fine when microcontroller was
    reseted by electrical noise

    I red in this forum writing _sdcc_external_startup() with the own code is fine,
    but if I write:

    code.c
    ---------------------
    #define __PIC16F818
    #include "pic/pic16f818.h"

    /* Prototypes of functions */
    void Int(void);
    void _sdcc_external_startup(void);

    void Int(void) interrupt 0
    {
    _asm nop _endasm;
    }

    void main(void)
    {
    _asm nop _endasm;
    }

    /* This is the start up code that I want */
    void _sdcc_external_startup(void)
    {
    _asm;
      ORG 0x00
    begin:
      bcf INTCON,7
      btfsc INTCON,7
      goto begin
      goto _main
    _endasm;
    }

    -----------------------

    Compile using:

    sdcc -mpic14 -p16f818 --lib-path /usr/share/sdcc/lib/pic -o bin code.c

    sdcc shows:

    message: using default linker script "/usr/share/gputils/lkr/16f818.lkr"
    error: multiple sections using address 0x4
    error: no target memory available for section "STARTUP"

    and only appears:

    bin.asm, bin.o, bin.p

    on bin.asm the code is:

    STARTUP    code
        nop
        pagesel __sdcc_gsinit_startup
        goto    __sdcc_gsinit_startup
    ;--------------------------------------------------------
    ; interrupt and initialization code
    ;--------------------------------------------------------
    c_interrupt    code    0x4
    __sdcc_interrupt
    ;***
    ;  pBlock Stats: dbName = I
    ;***
    ;entry:  _Int    ;Function start
    ; 0 exit points
    ;; Starting pCode block
    _Int    ;Function start
    ; 0 exit points
    ;    .line    7; "code.c"    void Int(void) interrupt 0
        MOVWF    WSAVE
        SWAPF    STATUS,W
        CLRF    STATUS
        BCF    STATUS,5
        BCF    STATUS,6
        MOVWF    SSAVE
        MOVF    PCLATH,W
        MOVWF    PSAVE
        CLRF    PCLATH
        nop
        MOVF    PSAVE,W
        MOVWF    PCLATH
        CLRF    STATUS
        SWAPF    SSAVE,W
        MOVWF    STATUS
        SWAPF    WSAVE,F
        SWAPF    WSAVE,W
    END_OF_INTERRUPT
        RETFIE   

    code_init    code
    __sdcc_gsinit_startup
        pagesel _main
        goto _main
    ;--------------------------------------------------------
    ; code
    ;--------------------------------------------------------
    code_code    code
    ;***
    ;  pBlock Stats: dbName = M
    ;***
    ;entry:  _main    ;Function start
    ; 2 exit points
    ;has an exit
    ;; Starting pCode block
    _main    ;Function start
    ; 2 exit points
        nop
        RETURN   
    ; exit point of _main

    ;***
    ;  pBlock Stats: dbName = C
    ;***
    ;entry:  __sdcc_external_startup    ;Function start
    ; 2 exit points
    ;has an exit
    ;; Starting pCode block
    __sdcc_external_startup    ;Function start
    ; 2 exit points
        ;
    begin:
        bcf INTCON_bits.GIE
        btfsc INTCON_bits.GIE
        goto begin
        goto _main
        RETURN   
    ; exit point of __sdcc_external_startup

    As you can see the "STARTUP code" are the same, and my startup code is unusable
    owing the compiler inserts a "return" nemonic  on the 000004 position and the linker
    refuses to overwrite the interrupt code.

    I hope this post was not be bored to you.

    Best Regards.

    franciscojar

     
    • Raphael Neider
      Raphael Neider
      2007-07-18

      What you want can be obtained via

      #include "pic14regs.h"

      void _sdcc_gsinit_startup (void)
      {
          _asm
          bcf STATUS, 7
          btfsc STATUS, 7
          goto __sdcc_gsinit_startup
          goto _main
          _endasm;
      }

      void main(void)
      {
          _asm nop _endasm;
      }

      The leading NOP at 0x0000 is there for use by in-circuit debuggers---some require it I was told...
      Your goto 0x18 (main+1) actually goes to __sdcc_gsinit_startup, see .lst a couple of lines ABOVE _main (.lst files are not sorted according to addresses globally).

      _sdcc_external_startup is not supported for PIC14 devices. Though this might need to change: In the above approach you loose initialization of global and static variables, which would usually be done in __sdcc_gsinit_startup. As you now replaced it with your own startup code, no initialization will happen. Worse, you cannot even call the original __sdcc_gsinit_startup function, because the symbol has been redefined to your function. Providing a default __sdcc_external_startup which just consists of
      GOTO __sdcc_gsinit_startup
      would allow us to (1) override _sdcc_external_startup, thus applying own startup code, while still being able to (2) use the standard initialization routine by simply calling it/GOTO it from our _sdcc_external_startup routine.
      Again, currently there is no way to get both own startup code and initialization without copying the code from lib/pic/libsdcc/idata.c's _sdcc_gsinit_startup under a different name to the project (so that you can call it from the replaced __sdcc_gsinit_startup); this will probably change within a month...

      You should not place a semicolon after _asm but only after _endasm; though it does not hurt.
      Using ORG in inline assembler is... discouraged. If you need full control over the code, link with an assembled pure assembly file.

      Hope to got you on your way,
      Raphael

       
    • franciscojar
      franciscojar
      2007-07-19

      Raphael, thanks a lot for your fast response.

      OK, in order to do not change the _sdcc_gsinit_startup, I will change the .asm file generated by the sdcc and pointing to __sdcc_gsinit_startup instead _main

      i.e. in bin.asm:

      STARTUP code
      nop
      pagesel __sdcc_gsinit_startup
      goto __sdcc_gsinit_startup

      change to:

      STARTUP code
      begin:
      bcf INTCON,7
      btfsc INTCON,7
      goto begin
      pagesel __sdcc_gsinit_startup
      goto __sdcc_gsinit_startup

      save bin.asm

      gpasm -c bin.asm

      sdcc -mpic14 -p16f818 --lib-path /usr/share/sdcc/lib/pic bin.o

      and all right !!!

      I hope this will help to the community.

      franciscojar.