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.

MSPM0L1305: Changed Flash memory origin to 0x2000 in linker, requires .intvec to have palign(8), why?

Part Number: MSPM0L1305
Other Parts Discussed in Thread: UNIFLASH,

Hi,

I've got a test application that I want to start at 0x2000 in Flash instead of the default 0x0000 (I have a bootloader that runs at 0x0000 and then jumps to application code).  I took the provided linker file from a TI example, and changed the Flash origin from 0x0000000 to 0x00002000, and changed " .intvecs: > 0x00000000" to  ".intvecs: > 0x00002000".

When I was testing via the debugger in Code Composer Studio (not Theia), everything worked fine (I load the application first, then load the bootloader second without erasing Flash memory, that way I can debug).   Later, I enabled the option to export a binary file, which uses the tiarmhex.exe utility to create the .bin out of the .out file.  Loading this application binary in address 0x2000 using Uniflash (and loading bootloader binary to 0x0000) does not work!

So loading the firmware using the .out file (which is what CCS debugger does) worked fine, but loading the generated .bin did not work.  I loaded the firmware on a device using the .out file, then used Uniflash to read the Flash contents back onto a file (I'm calling it the "exported binary").  When I compare this exported binary with the tiarmhex.exe-generated binary, I see that the only difference is that it appears that the .text section starts at 0x20e8 in the exported image (on an 8-byte boundary), whereas on the generated binary, it starts at 0x20e4.  (.text is the section after .intvecs)  This results in all of the function calls being offset by one 32-bit instruction, or two 16-bit thumb instructions.

Looking at the CCS-generated .map file, it says .text starts at 000020e8, as expected.  Also, in the linker (.cmd) file, I have ".text   : palign(8) {} > FLASH".  The TIArmClang Documentation states that palign(n) tells the linker to place a section's starting AND ending address boundary at n-bytes.  So it appears that there is a bug or inaccuracy here, since tiarmhex.exe is not really starting .text on an 8-byte boundary once I change Flash and .intvecs origin from 0x0000 to 0x2000.

I can cause tiarmhex.exe to output a correct binary (where .text starts at 000020e8 and everything works) by changing ".intvecs: > 0x00002000" to ".intvecs: palign(8)  > 0x00002000".  However, the documentation seems to imply this should be unnecessary.  This leads me to these questions:

  1. Why is palign(8) required in the .intvecs section, when I have Flash origin set to 0x2000, when it was not present or necessary when Flash origin was set to 0x0000?  In other words, why isn't palign(8) in the section AFTER .intvecs sufficient?  Is this a bug or expected behavior?
  2. Am I okay going forward with the linker that I now have? 
  3. Why are all of these sections 8-byte aligned, instead of, say 4-bytes (32 bits)?  It is a 32 bit processor after all.  I'm trying to improve my limited knowledge here.

Regards,

Charlie


/*****************************************************************************

  Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/ 

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions 
  are met:

   Redistributions of source code must retain the above copyright 
   notice, this list of conditions and the following disclaimer.

   Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the 
   documentation and/or other materials provided with the   
   distribution.

   Neither the name of Texas Instruments Incorporated nor the names of
   its contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*****************************************************************************/
-uinterruptVectors
--stack_size=256

MEMORY
{
FLASH (RX) : origin = 0x00002000, length = 0x0000DFF8
SRAM (RWX) : origin = 0x20000000, length = 0x00001000
}

SECTIONS
{
    .intvecs: palign(8)  > 0x00002000 //next section won't actually start at 8-byte boundary unless palign(8) is here.
    .text   : palign(8) {} > FLASH
    .const  : palign(8) {} > FLASH
    .cinit  : palign(8) {} > FLASH
    .pinit  : palign(8) {} > FLASH
    .rodata : palign(8) {} > FLASH
    .ARM.exidx    :  palign(8)  {} > FLASH
    .init_array   :  palign(8)  {} > FLASH
    .binit        : palign(8) {} > FLASH
    .TI.ramfunc      : load = FLASH, palign(8), run=SRAM, table(BINIT)

    .vtable :   > SRAM
    .args   :   > SRAM
    .data   :   > SRAM
    .bss    :   > SRAM
    .sysmem :   > SRAM
    .stack  :   > SRAM (HIGH)
}

  • That depends on our flash operation, the mspm0 flash will write 8 bytes at a time write so we recommend to align the image files to be  8 bytes aligned.

  • Gary,

    Okay, that answers my third question, thank you.  What about questions 1 and 2?

    Thanks
    Charlie

  • I think it is the same answer that we need to write 8 bytes at a time, so we keep all memory used to 8 bytes aligned that will include the interrupt table.

  • Gary,

    Let me rephrase question 1.  The interrupt table was already 8 bytes aligned, without the need to add palign (since 0x2000 is divisible by 8).  The problem was the .text section was not aligned, even though I have always had ".text   : palign(8) {} > FLASH".  The TI documentation says that palign(n) forces a section to start and end on an n-byte boundary, so the palign(8) in line 46 should always force .text to start at an 8 byte boundary.  The .text section was 8-byte-aligned previously when FLASH origin and .intvecs origin were at 0x0000, so I believe it should have continued to be 8-byte-aligned when I changed it to 0x2000.

    Adding palign(8) to line 45 causes .text to be 8-byte-aligned again, but that seems more like a workaround or hack and runs contrary to what the documentation implies should happen.  Again, from the documentation, I expect the palign(8) in line 46 to always be sufficient to force .text to start at 8-byte boundary, no need to add it to line 45 simply because I changed .intvecs and FLASH origin from 0x0000 to 0x2000.

    Edit: As I mentioned before, this apparent "bug" only shows up when I invoke tiarmhex.exe with the --binary option to generate a binary.  The map file appears to be correct the entire time, which seems to indicate a bug (or undocumented difference, if you prefer) in how tiarmhex.exe interprets the linker file.

    Charlie

  • which uses the tiarmhex.exe utility to create the .bin out of the .out file

    CCS support to generate the bin file directly, why do you need to this tool?

    whereas on the generated binary, it starts at 0x20e4

    0x20e4 is not 8 bytes aligned, I think there should be some thing wrong the to generate the bin file by the tiarmhex.exe. So I recommend to use the CCS internal tool to generate the bin file.

  • CCS support to generate the bin file directly, why do you need to this tool?

    So I recommend to use the CCS internal tool to generate the bin file.

    What do you mean by "internal tool"?  In CCS, I go to the project properties, then select Build > Arm Hex Utility -> Output Format Options -> Output Format -> select --binary.  When I use this setting,  CCS simply calls tiarmhex.exe with this option.  I have a separate script that calls tiarmhex.exe with the exact same options CCS uses.  I do this because CCS only gives me the option of choosing one format, but I want multiple to be generated automatically (intel and binary).  I am using the exact same command options as CCS does with the binary setting, which has exactly the same result.

    Let me know if this is the "internal tool" you are talking about, or if you are talking about something else.  I came across some issues with the --intel (hex) option too, but that is a topic probably for a later thread.

    Thanks,

    Charlie

  • Have you try to generate TI_TXT format file that will be easy to see the address and data? Could you help to provide the project that can reproduce this issue? I want to reproduce this issue on myside first.

  • Gary,

    Apologies for the delay, I have been working on reproducing and fixing this issue on my end.  I've identified the change we made in our code that is different from a default project.  We have a few bytes of data that we specifically want stored after the .intvecs section.  The data was in a struct that was not a multiple of 8 bytes.  I found an alternate solution to modifying the .cmd linker file was to add an empty uint32_t variable to the end of our struct so that the data is padded to a multiple of 8 bytes.

    Again this issue only appears if FLASH origin is changed to 0x2000 and only when generating a .bin file.  I still would have thought that the palign(8) keyword in the .text section of the .cmd file would prevent this.  Anyways, I have tested the alternate solution above and we are going to proceed with that solution.

    Regards,

    Charlie