MSPM0G3107-Q1: Filling Unused Flash with NOP

Part Number: MSPM0G3107-Q1
Other Parts Discussed in Thread: MSPM0G3107, UNIFLASH

Hello,

Environment Information

  • Compiler: GCC
  • Chip: MSPM0G3107
  • Linker Script: mxpm0g3107.lds (provided with SDK)

 

I am working on a project which uses the MSPM0G3107 and I am trying to satisfy a software requirement which states that "unused Flash should be filled with NOP instructions". 

The way I am interpreting this requirement is as follows: if the program size is 10KB but your Flash size is 32KB, then the 22KB of flash should be the NOP instruction instead of the default 0xFFFFFFFF. 

I have been trying to modify my Linker Script to achieve this, but I have hit a road block. Based on the Linker Script syntax, I should be able to use '=fillexp' to accomplish this.

image.png

This does work and the padding added to non 8 byte-aligned data is whatever I set in the fillexp. The problem is that this is only applicable to whatever section it is added to. This still leaves the 22KB being set to 0xFFFFFFFF.

The behavior makes sense to me since the commands being used applies ONLY to the defined section it is added to. So then I thought, I can define another section which is placed AFTER all of the normal Flash stuff and have it stretch (in theory) the size of the remaining flash. 

image.png

But I end up with the same behavior as before, only the 6 padded bytes after the two BYTE output commands are set to the fill pattern. Which makes sense to me.

image.png

I'm leaning towards the conclusion that there isn't a good way of filling in the empty Flash space since it looks like the fill pattern is only applicable to defined sections. But I was wondering if TI knew of a way to accomplish this.

I could also be overcomplicating the requirement and it is actually referencing the padding bytes added in between unused memory spaces. 

  • What are people's thoughts?

Thanks,

Adan

  • Hello Adan,

    It is understandable why you are hitting that roadblock; as you noted, the linker's =fillexp attribute is designed to handle padding within defined sections or between them, rather than unilaterally populating the entire remaining memory region.

    While TI documentation emphasizes that unused memory should be secured with valid instructions or specific fault-handling routines to ensure robust behavior, the linker script approach you are attempting is limited by how the GNU linker defines output sections.

    To help clarify the path forward, a question came to mind:

    • Have you considered using a post-build utility, such as objcopy with the --pad-to flag or a hex-file manipulation tool, to insert the NOP pattern into the final binary image? This is often a more reliable way to ensure the entire output file is padded after the linker has finished placing your code and data.

    Additionally, please keep in mind that the MSPM0 flash programmer typically requires images to be aligned to 8-byte boundaries. If you proceed with filling the flash, ensuring that your final image maintains this alignment is critical to preventing ECC faults or programming errors.

    Best,

    Owen

  • Owen, 

    Thank you for your response. 

    Prior to you mentioning objcop, it did not occur to me to try and use that. I took your suggestion and tried objcopy, but it did not go as planned. Let me explain. 

    Definitions

    • 0xBE00 - 16-bit Thumb-2 instruction for NOP
    • 0x00020000 - end of FLASH region.

    I used the following command to pad the unused memory region "objcopy --gap-fill 0xBE00 --pad-to 0x00020000 binary.hex". At the end of my compilation, I got the following warning "Warning: truncating gap-fill from 0x0000BF00 to 0x0". When I flashed my binary and read back the memory, all unused memory blocks were 0x0 instead of the 0xBE00. It turns out that with the following objcopy flag syntax "--gap-fill <var>", var is a 1 byte variable, so the upper MSB gets truncated and hence the warning message. So this didn't work, unfortunately. 

    I then went back to the drawing board and thought about it. It then came to me, why not attempt to pad the bytes with the Linker Script again but defining the unused memory as an actual output section of memory (same idea as my previous comment). But this time, shift the location counter (.) to the end of FLASH and hopefully the FILL command fills the in-between space. 

    I hard-coded 8 bytes of the NOP instruction and then shift the location counter to the end of FLASH with the FILL command in between. To my surprised, this worked. 

    As you can see, the two 0xBE00BE00 intructions are there, BUT after the second NOP the order of the preceeding instructions is not correct. Instead of appearing as 0xBE00BE00, it appears as 0x00BE00BE. To me, this was an endianess issue. I then looked at the The GNU Linker documentation and found the data is being written as big-endian with the FILL command (if my interpretation is correct).

    If I invert the byte order to big-endian in the FILL [example: FILL(0x00BE00BE) ], it gets written "correctly" to memory.

    But I am not too confident with this approach. 

     

    So this is where I am at with this. Unfortunately, this is my first time ever dealing with direct memory organization outside of your normal "variable memory inside the stack/heap, etc." and I am not too confident in what I am doing having any potential side affects that I am not taking into consideration. 

    My question is: is flipping the endianess of the FILL sufficient? 

    And, I am looking for some advice to handling this "Fill unused Flash with valid instructions" as I am a beginner. 

    • Is my approach sound?
    • What should I take into consideration when approaching this "problem"?
    • Anything I should look out for?
    • Other things I can try?
    • etc. 

    What I don't want is for me to write this memory and then an unexpected issue occuring down the line that constantly triggers the ECC faults, or that somehow my program gets corrupted because of X, Y, Z. Or that Hard Faults due to an invalid memory access are no longer going to trigger because of something I did. 

    Thanks,

    Adan

  • Hi Adan,

    The device memory layout is in little endian. The memory viewer in CCS and Uniflash is also showing the memory in little endian.

    If you hover over the memory in Uniflash, it should show you what is exactly at each memory address:

    I am not the most familiar with GNU linker file documentation for FILL, but it seems like it is interpreting the parameter in big endian.

    Best,

    Owen