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

Close

How to put a function at specific address

2010-02-25
2013-03-12
  • I have read through the SDCC manual, but I am afraid I could not find any information regarding how to put a function at a desired location. Is there any additional manual about this, like a more detail linking documentation? What I wanted to do is similar to #pragma location=0x0800 in IAR. How to define user defined area and link it with SDCC? Thanks for your help.

     
  • BLRCalvin
    BLRCalvin
    2010-02-26

    Hi,

    You can specify the location of the function in the following way:

    consider a function func1() in src1.c (func1 should be the first function in the source file).

    compilation & assemble:
    sdcc -mmcs51 -model-small -c src1.c -codeseg src1_codeseg  ---> Defines a user defined code segment "src1_codeseg"

    Linking:
    sdcc -mmcs51 -model-small src1.rel -Wl -bsrc1_codeseg=0x0800 --> Specify the location of segment. The other functions in this segment will follow the func1(). If you do not wish this, let func1() alone be the function in src1.c

    However, remember that SDCC Linker processes the object files in the order they are specified and object file containing     main() should be the first object file during linking.

    Hope this helps.

    Best Regards,
    Raghu.

     
  • Hi Raghu,

    Thanks for the reply. Unfortunately this is not what I wanted. Let me explain what I intended to do. I am writing code for serial bootloader and I need to forward the incoming interrupt requests from the specified area to user program.

    Let say that the bootloader is placed at address 0x0000 and the user program will be placed at 0x0800 by the bootloader. When interrupts happen (let say timer T1), PC will jump by default to location 0x004B and I need to forward this interrupt request to user space which is 0x084B.

    The function would be:

    void T1_VECTOR_redirected(void) -----> (but this one is relocatable function)
    {
    __asm_begin
    ASM (ljmp 0x084B)
    __asm_end;
    }

    I tried this and it worked :

    void T1_VECTOR_redirected(void)
    {
    __asm_begin
    .area NODINO_REDIRECTED (CODE,CON,ABS)
    .org 0x004B
    ASM (ljmp 0x084B)
    __asm_end;
    }

    but I want to avoid writing it this way and find a better way to write it in C (if possible). I had already the solution in assembly but again, I prefer to avoid it. So, what do you have in mind?

    Eka

     
  • Maarten Brock
    Maarten Brock
    2010-02-28

    Eka,

    Using assembly is by far the best and easiest solution I think. I recommend to put all redirected vectors in one .asm file. But use a shorter area name as they are limited (truncated) to 8 characters.

    Maarten

     
  • Maarten,

    Correct me if I am wrong, but I got a sense that the linking priority is given to the user defined area, isn't it? Thanks for reminding me about the 8 characters truncation, eventhough I got no linking problem with long .are names.

    Other issue came up, this code is not properly linked:

    void ADC_VECTOR_redirected(void) __naked
    {
    __asm_begin
    .area NODINO_REDIRECTED (CODE,CON,ABS)
    .org 0x000B
    ASM (ljmp (USER_PROGRAM_PAGE * 0x800) + 0x0B)
    __asm_end;
    }

    void URX0_VECTOR_redirected(void) __naked
    {
    __asm_begin
    .area NODINO_REDIRECTED (CODE,CON,ABS)
    .org 0x0013
    ASM (ljmp _custom_isr_uart0_rx)
    __asm_end;
    }

    I had to add .ds 5 inbetween to correct compiling problem, since the label is always missalligned. Is it a known bug or I missed somthing from the documentation? This code may correct the missallignment issue:

    void ADC_VECTOR_redirected(void) __naked
    {
    __asm_begin
    .area NODINO_REDIRECTED (CODE,CON,ABS)
    .org 0x000B
    ASM (ljmp (USER_PROGRAM_PAGE * 0x800) + 0x0B)
    ASM (.ds 5)
    __asm_end;
    }

    void URX0_VECTOR_redirected(void) __naked
    {
    __asm_begin
    .area NODINO_REDIRECTED (CODE,CON,ABS)
    .org 0x0013
    ASM (ljmp _custom_isr_uart0_rx)
    ASM (.ds 5)
    __asm_end;
    }

    Eka

     
  • Maarten Brock
    Maarten Brock
    2010-03-01

    Eka,

    I'm not sure if multiple .org statements in the same area will work correctly. Also look at how much red tape you need for accomplishing this in C. I still recommend to go fully .asm for this.

    Maarten

     
  • Maarten,

    In fact it didn't work fine and I changed it. Now, I use a normal __interrupt for every interrupt service routine and just ignore the additional reti at the end. For now the bootloader works for CC2430 and I will try to put the fix into .asm soon in the later version.

    Please help me to understand with the licensing and give me some suggestion. I use and modify your compiler.h, also cc2430.h by Jesus C. Fraga. Both of this library is licensed under LGPL. I have written: uart.c, clock.c, flash.c (this should be considered s library I think) and bootloader.c (the application uses those library). The output should be a binary called bootloader.bin. Questions:

    1. If I want bootloader.bin can be used by anyone in their personal or commercial product, can I use GPL or should I stay with LGPL? (I prefer GPL).

    2. I prefer to put the library under GPL, this may encourage people to use SDCC instead. What is the advantage of putting library under LGPL if other compiler cannot link it?

    Thanks,

    Eka

     
  • Ups, I forgot to ask the third question. Once I modify your library (compiler.h) and Jesus's (cc2430.h), what license I can use and who is the copyright holder of the modified library?

    Sorry if I asked you too many questions, because I got confused between LGPL - GPL and the advantages in embedded system firmware.

    Thanks again,

    Eka

     
  • Maarten Brock
    Maarten Brock
    2010-03-02

    Now, I use a normal __interrupt for every interrupt service routine and just ignore the additional reti at the end.

    I don't understand. Do you mean you override the RETI with an inline assembly RET? You shouldn't. Just let the compiler generate the ISR of your application as is and move the code with -code-loc. In the bootloader you use the redirecting assembly file with all the jump instructions. It's best to keep the bootloader from using interrupts.

    You can choose either LGPL or GPL for your application. If anyone wants to enhance your application with proprietary code this can be done under LGPL but not under GPL. Then he must use GPL too.

    If anyone chooses to rebuild the library with a different compiler it's still LGPL and can be linked with proprietary code using the other compiler/linker.

    We will both be copyright holders of the modified code, each of our own part. You can choose either LGPL or GPL I think.

    Maarten

     
  • I don't understand. Do you mean you override the RETI with an inline assembly RET? You shouldn't. Just let the compiler generate the ISR of your application as is and move the code with -code-loc. In the bootloader you use the redirecting assembly file with all the jump instructions. It's best to keep the bootloader from using interrupts.

    That's exactly what I did. I told you before that I just ignore the generated RETI and put inline assembly to jump into user code, like this example:

    void isr_uart0_tx (void) __interrupt (INUM_UTX0)
    {
    __asm_begin
    ljmp (USER_PROGRAM_PAGE * 0x800) + 0x3B
    __asm_end;
    }

    Ok, if both of you are still the copyright holder, how can I let everyone that I made modification on it? and obviously to warn people that this library is a modified one although the name is the same.

    Let say I put the library and application under GPL, can anybody modify it using other (commercial) compiler and release the source code under GPL? I just want to make sure that everybody can use it with worrying about the legal issue.

    Eka

     
  • Maarten Brock
    Maarten Brock
    2010-03-03

    Ah, I see, you mean you ignore the RETI that is created by SDCC in the bootloader for isr_uart0_tx. But in your application there will be another isr that does return with a RETI. That's fine, though you get many jumps in a row. SDCC will create a jump at 0x003B to isr_uart0_tx which jumps to 0x083B which jumps to the real isr. If you use assembler for the interrupt vector table in the bootloader you can remove one jump.

    You can document your modification in the source.

    And yes anybody can use the library with any compiler in a GPL application.