Multiple code locations?

  • KimmoS

    KimmoS - 2005-02-17


    How could I use to sdcc to set different objects to different locations?

    I know that I can set the code generation in certain address like:
    sdcc --code-loc 0x4000 main.c

    But it seems to me that if I want the interrupt routine to be in address 0xb600, I cant do that.

    I tryed following:
    sdcc -c -code-loc 0xb600 intrerrupt.c
    sdcc --code-loc 0x4000 main.c interrupt.rel

    But the main.ihx file shows no code for 0xb600.

    Why do I want to do such thing?
    We have ROM circuit where interrupt vectors are fixed.

    Anyone have idea how to fix this?
    I think there should be a option in sdcc for that, but couldn't find that.


    • Frieder Ferlemann


      a word in advance: be warned this is going to be somewhat lengthy:

      Summary: SDCC is not well prepared for this, but there are ways to get around this.

      SDCC currently places the code it generates into a segment called CSEG.
      You can advise the linker to put the CSEG somewhere (as you have done) but obviously you need more than one segment.

      The example given below assumes two files (main.c and interrupt2.c)

      volatile unsigned char counter;

      int main( void )
        while( counter < 42 )
        return counter;


      extern volatile unsigned char counter;

      void my_int2( void ) interrupt 2

      Now do:
      sdcc -V main.c
      sdcc -V -c interrupt2.c

      Shows you how SDCC invokes the assembler and it gives you an object file interrupt2.rel (which you cannot use in this form as all of the code is in segment CSEG).
      How to get a better one?
      You have the generated assembler file interrupt2.asm in which you can modify the CSEG above the function label "_my_int2:" to f.e. CSEG_IRQ2.

      Now you call the assembler "by hand" with the command line options you've gotten from the previous SDCC -V command, f.e.:
      "/usr/local/bin/asx8051" -plosgff "interrupt2.asm"

      The interrupt2.rel generated now has an extra segment which you can tell the linker to locate somewhere (line wrappings are done by sourceforge, not by me):

      sdcc -V -Wl "-b CSEG=0x1000" -Wl "-b CSEG_IRQ2=0x8000" main.rel interrupt2.rel

      There you are! Look at interrupt2.rst and main.rst (or to see whether the code sits where you want it to sit:

         8000                      85 _my_int2:
         8000 05 08                97         inc     _counter
         8002 32                   99         reti

      Note, the linker would give NO warning if things overlap!
      You're not entirely on your own though:
      Use the tool srecord (also available here on Sourceforge) like this:

      srec_cat main.ihx -intel -o main.hex -intel

      On overlaps it bails out with a warning like:
      srec_cat: main.ihx: 11: contradictory 00001000 value (previous = 02, this one = 08)



      PS1: Besides the solution proposed here you could write an assembly file with some .org directives and some ljmp instructions to your IRQ routines. This should be straightforward but needs an extra ljmp.

      PS2: Please (anyone) file a Feature Request if you come across an idea how to implement this more cleanly in SDCC. Maybe the compiler should automatically generate segment names of the form "CSEG_IRQnn" for interrupt functions?

    • Frieder Ferlemann

      Sorry, forgot a "-c" there:
      Now do:
      sdcc -V -c main.c

    • Maarten Brock

      Maarten Brock - 2005-02-24

      May I recommend to solve this with a new pragma to set the (code) segment name?

    • Frieder Ferlemann

      please let's continue on this thread on the sdcc-devel mailing list: