2024-02-27 03:35 PM
I'm trying to define a region of RAM for storing debug information that can persist following a reset (DEBUG_RAM). I'd like to put variables in a section (.debug_ram) that are stored in the DEBUG_RAM memory such its usage properly displays in the Build Analyzer.
When I do this my elf and hex files are a normal size, 1.3MB and 15kB respectively. My bin files, however, are 393MB. Unfortunately the company I work for has standardized on bin files, particularly for their bootloader software.
I have attached my modified linker file (renamed STM32F765VITX_FLASH.ld.c so that it can be attached to the forum) and main.c where I locate the debug_ram_test variable in the in the .debug_ram section. When I build the build analyzer window correctly shows that 6.25% of the DEBUG_RAM region is used.
If I use a bin-to-hex utility to convert the bin file I see it's almost all data records with all of the data equal to zero, interspersed with Extended Linear Address records outside the range for the FLASH for the MCU. Here is an example:
:10FFC000000000000000000000000000000000000000000000000000000000000000000031
:10FFD000000000000000000000000000000000000000000000000000000000000000000021
:10FFE000000000000000000000000000000000000000000000000000000000000000000011
:10FFF000000000000000000000000000000000000000000000000000000000000000000001
:01000004FF0FED
:100000000000000000000000000000000000000000000000000000000000000000000000F0
:100010000000000000000000000000000000000000000000000000000000000000000000E0
:100020000000000000000000000000000000000000000000000000000000000000000000D0
:100030000000000000000000000000000000000000000000000000000000000000000000C0
I'm really hoping that I'm doing something dumb that I can fix, but I've done this on lots of projects before and probably never noticed because I only used hex files.
Solved! Go to Solution.
2024-02-27 05:56 PM
Could make DEBUG_RAM as a NOLOAD region if you don't want data initialization there.
2024-02-27 04:01 PM
hex and elf formats can hold the bytes in several chunks or segments, bin cannot. Bin contains all the values between the lowest address and the highest. There is no way to change. Keep in mind, that even if your debug info persists after a (warm) reset, the content will be lost when the power goes down. Writing zeros to inbetween addresses might even cause side effects.
If the format really cannot be changed, you may add some startup code, actively copying the debug info from a global const (read-only) variable to the target adddess (or let a secondary bin file do so).
hth
KnarfB
2024-02-27 04:16 PM
The MCU only has 2MB of Flash so a 393MB bin file doesn't make sense. If I try to load the file in STM32CubeProgrammer it says that it's too big.
If I simply remove __attribute__((section(".debug_ram"))) from debug_ram_test in main.c, the bin file reduces to 6kB. It really shouldn't have an effect on the bin size where the variable is located in RAM but it does.
Long term I do plan on looking at the RCC->CSR register to determine the cause of reset before trusting the data in the .debug_ram section. I may use a CRC as well.
For now, however, I seem to get non-sensical bin files when I build with gcc and that's the first step.
2024-02-27 05:09 PM
Large because the file tries to put data from RAM into the BIN file, ie spanning 0x08000000 thru 0x20000080 (384MB). Binaries can't be sparse. Other tools would split to multiple binaries.
Stop putting data in RAM that needs to be staged in FLASH and moved there via code in startup.s
Check .MAP file, or dump .ELF object with objcopy
2024-02-27 05:56 PM
Could make DEBUG_RAM as a NOLOAD region if you don't want data initialization there.
2024-02-27 06:07 PM
Thanks for writing me! I actually recognize your name from when I used to write here at my last job and I remember you being a really knowledgeable and helpful guy.
In my main.c I am not initializing the debug_ram_test variable so I wouldn't have expected it to store anything in FLASH that needs to be moved. In startup.s it just clears .bss and initializes .data but doesn't do anything to initialize my .debug_ram section (which is good as I want it to persistent between reboots).
I followed your advice to look at the map files, both with debug_ram_test in .debug_ram and then with debug_ram_test in .bss. Only 33 lines are different between the two, with debug_ram_test moving from .debug_ram to .bss and the other addresses shifting accordingly:
With debug_ram_test in .debug_ram:
.debug_ram 0x0000000020000000 0x8
0x0000000020000000 . = ALIGN (0x4)
*(.debug_ram)
.debug_ram 0x0000000020000000 0x8 ./Src/main.o
0x0000000020000000 debug_ram_test
0x0000000020000008 . = ALIGN (0x4)
0x0000000020000008 . = ALIGN (0x4)
.bss 0x000000002000008c 0x24
0x000000002000008c _sbss = .
0x000000002000008c __bss_start__ = _sbss
*(.bss)
.bss 0x000000002000008c 0x1c C:/ST/STM32CubeIDE_1.14.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.11.3.rel1.win32_1.1.100.202309141235/tools/bin/../lib/gcc/arm-none-eabi/11.3.1/thumb/v7e-m+dp/hard/crtbegin.o
*(.bss*)
.bss.uwTick 0x00000000200000a8 0x4 ./Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.o
0x00000000200000a8 uwTick
.bss.linker_learn
0x00000000200000ac 0x4 ./Src/main.o
0x00000000200000ac linker_learn
*(COMMON)
0x00000000200000b0 . = ALIGN (0x4)
0x00000000200000b0 _ebss = .
0x00000000200000b0 __bss_end__ = _ebss
._user_heap_stack
0x00000000200000b0 0x600
0x00000000200000b0 . = ALIGN (0x8)
[!provide] PROVIDE (end = .)
0x00000000200000b0 PROVIDE (_end = .)
0x00000000200002b0 . = (. + _Min_Heap_Size)
*fill* 0x00000000200000b0 0x200
0x00000000200006b0 . = (. + _Min_Stack_Size)
*fill* 0x00000000200002b0 0x400
0x00000000200006b0 . = ALIGN (0x8)
With debug_ram_test in .bss:
.debug_ram 0x0000000020000000 0x0
0x0000000020000000 . = ALIGN (0x4)
*(.debug_ram)
0x0000000020000000 . = ALIGN (0x4)
0x0000000020000000 . = ALIGN (0x4)
.bss 0x0000000020000090 0x2c
0x0000000020000090 _sbss = .
0x0000000020000090 __bss_start__ = _sbss
*(.bss)
.bss 0x0000000020000090 0x1c C:/ST/STM32CubeIDE_1.14.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.11.3.rel1.win32_1.1.100.202309141235/tools/bin/../lib/gcc/arm-none-eabi/11.3.1/thumb/v7e-m+dp/hard/crtbegin.o
*(.bss*)
.bss.uwTick 0x00000000200000ac 0x4 ./Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.o
0x00000000200000ac uwTick
.bss.debug_ram_test
0x00000000200000b0 0x8 ./Src/main.o
0x00000000200000b0 debug_ram_test
.bss.linker_learn
0x00000000200000b8 0x4 ./Src/main.o
0x00000000200000b8 linker_learn
*(COMMON)
0x00000000200000bc . = ALIGN (0x4)
0x00000000200000bc _ebss = .
0x00000000200000bc __bss_end__ = _ebss
._user_heap_stack
0x00000000200000bc 0x604
0x00000000200000c0 . = ALIGN (0x8)
*fill* 0x00000000200000bc 0x4
[!provide] PROVIDE (end = .)
0x00000000200000c0 PROVIDE (_end = .)
0x00000000200002c0 . = (. + _Min_Heap_Size)
*fill* 0x00000000200000c0 0x200
0x00000000200006c0 . = (. + _Min_Stack_Size)
*fill* 0x00000000200002c0 0x400
0x00000000200006c0 . = ALIGN (0x8)
I do suppose I'm surprised to see .bss start at 0x2000008c in the first map file and start at 0x20000090 in the second. I'd have expected them to both start at 0x20000080 as that's where RAM begins. I don't really see how these map file differences would cause the bin file corresponding to the first map file to be 393MB, however, and the bin file corresponding to the second map file to be 6kB.
2024-02-27 06:15 PM
NOLOAD seems to have worked!
With my debug variable in the DEBUG_RAM region I'm now getting a 6kB bin file!
Thank you so much for this!