This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linking Library module in specified location using IAR EW 5.2.9

Other Parts Discussed in Thread: MSP430F169

 

Hi all,

I have been trying to perform the following several days now and I always hit a deadend. Any kind of help will be greatly appreciated.

I have written a bootloading module that will be used for uploading new firmware to an MSP430F169. I want to link that module with my main software program but I want the bootloading module to be placed high in the flash say in address 0xF800. Every way i tried to do that hits a deadend.

1) If you try to compile the Main Software and the Bootloader as simple C files (and place all the routines of the bootloader from address 0xF800 and higher) both using the same Cstartup and DLIB the thing works ok. the main software is placed nicely in the lower flash and the bootloader is placed nicely from 0xF800 and higher. The problem with this is that DLIB routines are used by the bootloader and DLIB routines are placed in the lower flash just above the main software. Hence when bootloading takes place and the bootloader start erasing the flash, it will delete routines that he requires and hence crash the program.

2) If you try to compile the bootloading module as a separate project (module) and define that the start address of it will be at 0xF800 and all the DLIB routines used by it will be also be over 0xF800 then again this works ok. A single operational module is produced that starts at 0xF800 and works perfectly. When however i try to incoorporate that into my main program as a library module then the linker instead of placing it high at address 0xF800 it places it very low, even below the main software.

Does anyone know how can someone locate a library module at an exact location in the flash? Is it even possible?

I mean the first solution would work great if only i could relocate the DLIB routines I used at the same region with the bootloading module, but that seems impossible.

Just to let you know I am coding in C. I know that If I was coding in assembly then i could locate the bootloading module exactly where I would like it to be and it wouldn't call any library routines located elsewhere

Thanks for your help in advance.

 

  • Hi there

    To put a function is a specific memory location would require 2 things. The program pointing where the function or the library is going to be and modifying the linker file to be custom linker file (lnk430F169.xcl). I would highly recommend copying this file into your project folder. It sounds like you need to modify the linker file to specify IAR where to put the DLIB and cstartup.

    This sample code here shows a quick way to put a function in a specific memory location.

    void test(void);

    void main(void)
    {
    WDTCTL = WDTPW+WDTHOLD; // Stop WDT
    P1OUT |= ~BIT0;
    P1DIR |= BIT0;
    while(1)
    {
    test();
    }
    }
    void test(void) @ "MYCUSTOMSEG"
    {
    P1OUT ^= BIT0;
    }

    Custom linker file modification. Once this is done, you have to set IAR to point to this new linker file. Goto Project --> Options --> Linker --> Config tab --> check box "Override default" for Linker command file.

    // ---------------------------------------------------------
    // Code
    // ---------------------------------------------------------
    -Z(CODE)CSTART,ISR_CODE=1100-FFDF    //Modify this to change location of your cstartup
    -P(CODE)MYCUSTOMSEG=FB00-FFDF
    -P(CODE)CODE=1100-FB00

    Hope it helps!

  • Dear William,

    Thanks for your answer but I have already done all the things that you mention and indeeded they work out.

    By changing the linker command file .xcl you can indeeded reposition individual routines, also the Cstart code etc etc BUT...... you cannot reposition DLIB routines linked into the program. If you are linking in an object file (whether this is a library or an entire program module) then I think (maybe I am wrong) there is no way to define where the routines contained in this module will be place in flash.

    Any idea of how you can do that ?

     

    Thanks

     

  • I am trying to do essentially the same thing with the MAXQ610 - my boot block functions end up using several functions from the linked in library and I also wish to locate the library in the boot block segment I have defined.

    Have you made any progress with learning how to do this ?  Is it possible?  I have briefly tried to add the --image_input command line directive (Linker options - "Extra input") but that didn't seem to help.

    john

     

  • Here is a scheme that might work for you. Build two separate projects, one for Bootloader and the other for Application.

    For the Bootloader, modify the link command file so that Flash starts at F800. For the Application, modify the link command file so that Flash ends at F7FF. Each project has its own copy of cstart code, library routines, and interrupt/reset vectors.

    In the Application project, the interrupt/reset vectors are at F7E0 to F7FF and will not be invoked by the hardware automatically. Thus the Bootloader project has to help and fake it in order to run the Application.

  • Dear John,

    The answer that old_cow_yellow  works. I implemented it a bit different than he did and put all the interrupt vectors on the same position in the flash because my bootloader does not use any interrupts. Only the reset vector is used by the bootloader. And upon reset the microprocessor executes the bootloader.

  • Thanks for the replies !

    Refactoring all the client's code into two separate builds seemed like a painful last resort.  I kept digging and may have found a solution...IAR's XLIB tool.  I opened XLIB and ran the LIST-SEGMENTS command on my .r66 library file to see what was in there.  Basically all the modules are defaulted to a segment name of "CODE".  I then ran the RENAME-SEGMENT command on my library file and renamed CODE to the name of my segment where all the boot block (i.e. fixed) code is to reside. After rebuilding the project, it is appearing to work - i.e. I can load one build from IAR Workbench, run it with some test code, rebuild with a change to the test code, put the build on the system's SD Flash card, on power up the system reprograms itself with the code build on the SD card.  After reprogram and reboot, the test code displays the changes made.  Note - what I'm calling "test code" is just a few lines in the "application" (i.e. updateable area) to show me this is working.

    JG

  • I didn't understant how you did. I stuck at the same point with you.

    To link all bootloader related function into my CUSTOM_BOOTLOADER segment I used compiler option:

    --segment code=CUSTOM_BOOTLOADER
    
    
    All functions are now in CUSTOM_BOOTLOADER segment except some built-in library functions such as:
    ?DivMod16u
    ?ShiftLeft32_7
    ?CopyMemoryWords
    ?longjmp_r4
    ?longjmp_r5
    ?setjmp_r4
    ?setjmp_r5
    
    
    How can I tell IAR to place all these functions also into CUSTOM_BOOTLOADER segment?
    My bootloader code now try to use DivMod16u which is outside of bootloader segment and that code is already destroyed to be updated.
    
    
    Thank you.
  • BasePointer said:
    How can I tell IAR to place all these functions also into CUSTOM_BOOTLOADER segment?

    By altering the linker script. Problem is that these funciton have been compiled with the information to place them into default code segment.
    So instead of creating your special bootloader segment, simply move the position of the default code segment. Then all code will go to the new location, including any library code.

  • Hi, I have compiled one project(bootloader) as lib and included in the mail project(application).  changed the memory maps so that both projects are not overlapping. And my question is, You said  "In the Application project, the interrupt/reset vectors are at F7E0 to F7FF and will not be invoked by the hardware automatically. Thus the Bootloader project has to help and fake it in order to run the Application."  Please instruct me How to to get it done?

    Thanks,

    Rahul

     

  • My bootloader uses a double-jump mechanism. Which adds some CPU cycles but is quite simple.

    The original vector table contains entries that point to indirect jump instructions.
    e.g. 0xFFFC (the NMI vector) points to 0xFEF8, which contains a MOV &0xF7FC,PC instruction. So the BSL NMI ISR is calle don an NMI and jumps indirectly to the application NMI ISR whose address is stored on the 'moved' interrupt table at 0xF7FC.

    The reset vector (0xFFFE) of course points to the BSL entry point. And when the BSL wants to start the application, it also does an indirect jump to the application reset vector by executing a MOV &0xF7FE,PC instruction.

    An alternative way on 5x family CPUs is to copy the application interrupt vector table to the end of ram and set the SYSRIVECT bit in SYSCTL. Also, exclude this area from the ram segment in the linker script, so the stack begins below the ram interrupt vector table. However, since the interrupt vectors are now in ram, they are somewhat vulnerable. Sure, a stack underflow or an erroneous write shouldn't happen on a properly running program, but problems here may make the debugging during development more difficult to track.

**Attention** This is a public forum