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.

CCEv3.1 .label directive doesn't work

Other Parts Discussed in Thread: MSP430F2274

I have a function which copies a code section from flash to RAM, then executes it from RAM.  It uses the .label assembly directive to find out the flash address of the code section so it can copy it to RAM.  However, the .label directive returns the RUN address of the code (which is in RAM) instead of the LOAD address (which is in flash).  So I have no way to find the starting address of the code section in flash to be transferred.

I have set up the LOAD and RUN addresses of the code section in the linker command file.  Everything is per the user manuals.  This same code worked fine in CCEv1.0 but doesn't work with CCEv3.1..

Has anybody else run into this problem?  Or is there another technique to copy code from flash to RAM?  Thanks!

  • Hi,

     

    have you thought about placing the function(s) in an named segment in flash? By doing so you know the (start)address where the linker places the code.

     

    Placing functions in named segments is described in the MSP-FET430 Flash Emulation Tool (FET)

    (for Use With Code Composer Essentials for MSP430 Version 3.1) Users Guide  - C.3.3 Function Placement Into Named Segments (http://focus.ti.com/lit/ug/slau157i/slau157i.pdf).

     

    Maybe this thread is also useful http://e2e.ti.com/forums/t/4649.aspx .

     

    Rgds

    Gookbuster

  • Thanks for your suggestions.  I have already done what you suggested, including the #pragma CODE_SECTION.  But there is another complication in this case.  I want to store a function in flash which is executed in RAM.  So the linker has to link it for execution in RAM and load it into flash.  This is accomplished with a Union statement in the linker command file:

    UNION run = RAM
    {
    .serload: load = FLASH
    .bss
    }

     


    This assigns both a RUN address (200 in this case) with a LOAD address (somewhere in flash) to the section called .serload.  The #pragma CODE_SECTION actually returns the RUN address (200) in this case, and not the flash address:

     

     

     

    #pragma

     

     

    In order to get the flash LOAD address, I need to use the .label directive:

    CODE_SECTION(serload_work, ".serload"); //allocate space for serload_work in the section named .serload

     

     

     

     

     

     

     

    asm

     

     

    (" .sect \".serload\""); //assemble subsequent code into the .serload section
    asm(" .label serloadflash_start");//Load-Time Address Label

    This should return the flash LOAD address in serloadflash_start, which it does in CCEv1.0.  But in CCEv3.1 it returns the RAM RUN address (200).  So I have no way to determine the flash start sddress so I can copy the function from flash to RAM.  I think it is a CCE bug.  I'm looking for a workaround, but haven't found one yet.

  • Please review the following.  It is small test case to illustrate how to use the CCE v3.1 tools to accomplish what you are asking.

    Edit lnk_msp430f2274.cmd in SECTIONS area.

        .mysect    : load = FLASH, run = RAM, LOAD_START(_mysect_load_start),
                     RUN_START(_mysect_run_start), SIZE(_mysect_size)

     

    Sample main.c file.

    #include <msp430.h>

    extern int _mysect_load_start ;
    extern int _mysect_run_start ;
    extern int _mysect_size ;

    #pragma CODE_SECTION(myfunc, ".mysect") ;
    int myfunc(int i)
    {
        return (i+i) ;
    }


    void main(void)
    {
        int i, result;
        int saddr, raddr, size ;
        saddr = (int)(&_mysect_load_start) ;
        raddr = (int)(&_mysect_run_start) ;
        size = (int)(&_mysect_size) ;
        for (i=0; i<size; i++)
        {
          *(int *)(raddr + i) = *(int *)(saddr + i) ;
        }
        result = myfunc(2) ;
        while (1) ;
    }

  • Hello Brandon,

     

    Thank you for the suggestion.  I tried your suggested approach instead of using the .label directive which isn't working.  However, the LOAD_START operator does not seem to return the correct address either.

     

    In the linker command file, I put:

    UNION run = RAM

    {

    .serload: load = FLASH

    .bss

    }

    LOAD_START (slflash_start_ptr) /*used in serload to copy from flash to RAM*/

    LOAD_END (slflash_end_ptr) 

    RUN_START (slram_start_ptr)

     

    In the serload.c module I put:

    #pragma CODE_SECTION(serload_work, ".serload");      //allocate space for serload_work in the section named .serload

     

    extern UINT16 slflash_start_ptr;

    extern UINT16 slflash_end_ptr;

    extern UINT16 slram_start_ptr;

     

    void Serload_Go()

    {

    register unsigned char *srcptr;

    register unsigned char *destptr;

    destptr = (unsigned char *)slram_start_ptr; //relocate code to start of RAM;

    srcptr = (unsigned char*)slflash_start_ptr;

    while (srcptr <= (unsigned char *)slflash_end_ptr)

          *destptr++ = *srcptr++;

    serload_work(); //off we go to execute code in RAM

    }

     

    After compiling and linking, the map file says:

    0000091e slflash_end_ptr

    00000200 slflash_start_ptr   //THIS IS INCORRECT, IT SHOULD BE A FLASH ADDRESS NOT A RAM ADDRESS

    00000200 slram_start_ptr

     

    The linker correctly assigned the RAM start address, but incorrectly assigned the flash start and end addresses.  It assigned the RUN addresses, not the LOAD address.  This appears to be related to the .link directive failure I reported previously.

     

    Also note that the UNION statement was needed, and that when I tried serload:load = FLASH, run = RAM, it was not adequate to define a section and I got a linker error.

     

    Thank you.

    Rob Richmond

     

  • I have added the complete CCE project to my profile at the following location.

    Let me know if you can replicate the results.  I will look at what implications there are with using the UNION structure.

  • Brandon,

    I copied and pasted from your sample project into my project, but I got different results than you did.  I could not get the flash LOAD address.  This is the same as I am seeing with my code.  The section you defined was shown as uninitialized in the memory map.  Also, the main() function did not show up in the memory map.

    I can't see why it wouldn't work.  My project is big and has many modules.  Maybe that is a factor?  It worked fine with CCEv1.0, but not with CCCv3.1.  I still have not found a way to get the correct flash LOAD address, it keeps giving me the RUN address instead.

    Thanks.

    Rob Richmond

  • Have you tried putting the example in a smaller example on its own to verify you get the same results I did?  The resultant map file is below.

    SECTION ALLOCATION MAP

     output                                  attributes/
    section   page    origin      length       input sections
    --------  ----  ----------  ----------   ----------------
    .pinit     0    00008000    00000000     UNINITIALIZED

    .bss       0    0000020c    0000000b     UNINITIALIZED
                      0000020c    00000004     rts430.lib : _lock.obj (.bss)
                      00000210    00000004                : exit.obj (.bss)
                      00000214    00000003     main.obj (.bss)

    .stack     0    000005b0    00000050     UNINITIALIZED
                      000005b0    00000002     rts430.lib : boot.obj (.stack)
                      000005b2    0000004e     --HOLE--

    .mysect    0    00008000    0000000c     RUN ADDR = 00000200
                      00008000    0000000c     main.obj (.mysect:myfunc)

    .text      0    0000800c    00000120    
                      0000800c    0000004a     main.obj (.text:main)
                      00008056    00000040     rts430.lib : autoinit.obj (.text:_auto_init)
                      00008096    0000002a                : exit.obj (.text:exit)
                      000080c0    00000022                : args_main.obj (.text:_args_main)
                      000080e2    0000001e                : boot.obj (.text:_c_int00)
                      00008100    00000012                : memcpy.obj (.text:memcpy)
                      00008112    00000010                : epilog.obj (.text)
                      00008122    00000004                : pre_init.obj (.text:_system_pre_init)
                      00008126    00000004                : exit.obj (.text:abort)
                      0000812a    00000002                : _lock.obj (.text:_nop)

    .cinit     0    0000812c    0000001c    
                      0000812c    0000000c     rts430.lib : _lock.obj (.cinit)
                      00008138    0000000c                : exit.obj (.cinit)
                      00008144    00000004     --HOLE-- [fill = 0]

    .reset     0    0000fffe    00000002    
                      0000fffe    00000002     rts430.lib : boot.obj (.reset)

     

    00008000   _mysect_load_start
    00000200   _mysect_run_start
    0000000c   _mysect_size

  • Rob,

    I just found a known defect logged in our database concerning the use of .label directive. The defect is that a symbol specified with .label directive within assembly source file gets linked to run address instead of load address, which is exactly the behavior you initially reported. This bug exists in CCE v3 and 3.1 and should be fixed in the next release CCS v4. However, the LOAD_START/LOAD_END linker command file operaters should still work, and would be the suggested workaround for defining symbols with load time addresses.

**Attention** This is a public forum