I’m getting error with the latest PlatformIO, Mbed-framework & tools. It tries to merge firmware with userfirmware quite a long time until the process fails with error:
*** [.pio/build/nrf52_dk/firmware.hex] MemoryError :
Traceback (most recent call last):
File "/home/timo/.platformio/packages/tool-scons/script/../engine/SCons/Action.py", line 1054, in execute
result = self.execfunction(target=target, source=rsources, env=env)
File "/home/timo/.platformio/packages/framework-mbed/platformio/platformio-build.py", line 274, in merge_firmwares
env.subst(target)[0]
File "/home/timo/.platformio/packages/framework-mbed/platformio/pio_mbed_adapter.py", line 127, in merge_apps
update_regions, update_res, self.notify, self.toolchain.config)
File "/home/timo/.platformio/packages/framework-mbed/tools/regions.py", line 168, in merge_region_list
merged.puts(begin, padding * pad_size)
File "/home/timo/.platformio/packages/framework-mbed/platformio/package_deps/py2/intelhex/__init__.py", line 745, in puts
self._buf[addr+i] = a[i]
MemoryError
Unfortunately I can not provide the current project. I can try to reproduce with some skeleton code later. The problem appeared after I migrated from earlier platformio and mbed versions to the latest. Unfortunately I have not the exact versions of working platformio and tools, only mbed which was 5.10.1. Here is full build log:
Processing nrf52_dk (platform: nordicnrf52; board: nrf52_dk; framework: mbed)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/nordicnrf52/nrf52_dk.html
PLATFORM: Nordic nRF52 3.5.0 > Nordic nRF52-DK
HARDWARE: NRF52832 64MHz, 64KB RAM, 512KB Flash
DEBUG: Current (jlink) On-board (cmsis-dap, jlink) External (blackmagic, stlink)
PACKAGES: toolchain-gccarmnoneeabi 1.70201.0 (7.2.1), framework-mbed 5.51203.190509 (5.12.3), tool-sreccat 1.164.0 (1.64)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 0 compatible libraries
Scanning dependencies...
No dependencies
merge_firmwares([".pio/build/nrf52_dk/firmware.hex"], [".pio/build/nrf52_dk/userfirmware.hex"])
Checking size .pio/build/nrf52_dk/firmware.elf
Memory Usage -> http://bit.ly/pio-memory-usage
DATA: [== ] 22.7% (used 14896 bytes from 65536 bytes)
PROGRAM: [== ] 21.8% (used 114120 bytes from 524288 bytes)
*** [.pio/build/nrf52_dk/firmware.hex] MemoryError :
Traceback (most recent call last):
File "/home/timo/.platformio/packages/tool-scons/script/../engine/SCons/Action.py", line 1054, in execute
result = self.execfunction(target=target, source=rsources, env=env)
File "/home/timo/.platformio/packages/framework-mbed/platformio/platformio-build.py", line 274, in merge_firmwares
env.subst(target)[0]
File "/home/timo/.platformio/packages/framework-mbed/platformio/pio_mbed_adapter.py", line 127, in merge_apps
update_regions, update_res, self.notify, self.toolchain.config)
File "/home/timo/.platformio/packages/framework-mbed/tools/regions.py", line 168, in merge_region_list
merged.puts(begin, padding * pad_size)
File "/home/timo/.platformio/packages/framework-mbed/platformio/package_deps/py2/intelhex/__init__.py", line 745, in puts
self._buf[addr+i] = a[i]
MemoryError
I’ve narrowed the problem to modified linker script (that was working perfectly with earlier versions). With unmodified linker script the build will succeed with correct merge. Blank projects and project that included ble and rtos to gain some size will still succeed but not my actual project. Here is the modified linker script from .platformio/packages/framework-mbed/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld
/*
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Linker script to configure memory regions. */
/* Default to no softdevice */
#if !defined(MBED_APP_START)
#define MBED_APP_START 0x0
#endif
#if !defined(MBED_APP_SIZE)
#define MBED_APP_SIZE 0x80000
#endif
/* If softdevice is present, set aside space for it */
#if !defined(MBED_RAM_START)
#if defined(SOFTDEVICE_PRESENT)
#define MBED_RAM_START 0x200032D0
#define MBED_RAM_SIZE 0xCD30
#else
#define MBED_RAM_START 0x20000000
#define MBED_RAM_SIZE 0x10000
#endif
#endif
#if !defined(MBED_BOOT_STACK_SIZE)
#define MBED_BOOT_STACK_SIZE 0x800
#endif
#define ENCRYPTIONKEY_MEM_SIZE 0x20
#define MANUFACTURERINFO_MEM_SIZE 0x10
#define MBED_RAM0_START MBED_RAM_START
#define MBED_RAM0_SIZE 0xDC
#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE)
#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE - ENCRYPTIONKEY_MEM_SIZE - MANUFACTURERINFO_MEM_SIZE)
#define MANUFACTURERINFO_MEM_START (MBED_RAM1_START + MBED_RAM1_SIZE)
#define ENCRYPTIONKEY_MEM_START (MANUFACTURERINFO_MEM_START + MANUFACTURERINFO_MEM_SIZE)
MEMORY
{
FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE
RAM_NVIC (rwx) : ORIGIN = MBED_RAM0_START, LENGTH = MBED_RAM0_SIZE
RAM (rwx) : ORIGIN = MBED_RAM1_START, LENGTH = MBED_RAM1_SIZE
MANUFACTURERINFO_MEM (rwx) : ORIGIN = MANUFACTURERINFO_MEM_START, LENGTH = MANUFACTURERINFO_MEM_SIZE
ENCRYPTIONKEY_MEM (rwx) : ORIGIN = ENCRYPTIONKEY_MEM_START, LENGTH = ENCRYPTIONKEY_MEM_SIZE
}
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
/* Linker script to place sections and symbol values. Should be used together
* with the other linker script that defines memory regions FLASH and RAM.
* It references the following symbols that must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines the following symbols that the code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.Vectors))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.sdh_soc_observers :
{
PROVIDE(__start_sdh_soc_observers = .);
KEEP(*(SORT(.sdh_soc_observers*)))
PROVIDE(__stop_sdh_soc_observers = .);
} > FLASH
.sdh_stack_observers :
{
PROVIDE(__start_sdh_stack_observers = .);
KEEP(*(SORT(.sdh_stack_observers*)))
PROVIDE(__stop_sdh_stack_observers = .);
} > FLASH
.sdh_req_observers :
{
PROVIDE(__start_sdh_req_observers = .);
KEEP(*(SORT(.sdh_req_observers*)))
PROVIDE(__stop_sdh_req_observers = .);
} > FLASH
.sdh_state_observers :
{
PROVIDE(__start_sdh_state_observers = .);
KEEP(*(SORT(.sdh_state_observers*)))
PROVIDE(__stop_sdh_state_observers = .);
} > FLASH
.sdh_ble_observers :
{
PROVIDE(__start_sdh_ble_observers = .);
KEEP(*(SORT(.sdh_ble_observers*)))
PROVIDE(__stop_sdh_ble_observers = .);
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(8);
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
. = ALIGN(8);
} > FLASH
__exidx_end = .;
__etext = .;
.manufacturerinfo :
{
. = ALIGN(4);
__manufacturerinfo_start__ = .;
*(.manufacturerinfo*)
__manufacturerinfo_end__ = .;
} > MANUFACTURERINFO_MEM
.encryptionkey :
{
. = ALIGN(4);
__encryptionkey_start__ = .;
*(.encryptionkey*)
__encryptionkey_end__ = .;
} > ENCRYPTIONKEY_MEM
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(8);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(8);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(8);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(8);
PROVIDE(__start_fs_data = .);
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
*(.jcr)
. = ALIGN(8);
/* All data end */
__data_end__ = .;
} > RAM
__edata = .;
.nvictable (NOLOAD) :
{
PROVIDE(__start_nvictable = .);
KEEP(*(.nvictable))
PROVIDE(__stop_nvictable = .);
} > RAM_NVIC
.noinit (NOLOAD) :
{
PROVIDE(__start_noinit = .);
KEEP(*(.noinit))
PROVIDE(__stop_noinit = .);
} > RAM
.bss :
{
. = ALIGN(8);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(8);
__bss_end__ = .;
} > RAM
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
*(.heap*);
/* Expand the heap to reach the stack boundary. */
ASSERT(. <= (ORIGIN(RAM) + LENGTH(RAM) - MBED_BOOT_STACK_SIZE), "heap region overflowed into stack");
. = ORIGIN(RAM) + LENGTH(RAM) - MBED_BOOT_STACK_SIZE;
__HeapLimit = .;
} > RAM
PROVIDE(__heap_start = ADDR(.heap));
PROVIDE(__heap_size = SIZEOF(.heap));
PROVIDE(__mbed_sbrk_start = ADDR(.heap));
PROVIDE(__mbed_krbs_start = ADDR(.heap) + SIZEOF(.heap));
/* .stack_dummy section does not contain any symbols. It is only
* used for the linker script to calculate the size of stack sections
* and assign values to stack symbols later. */
.stack (NOLOAD):
{
__StackLimit = .;
*(.stack*)
. = ORIGIN(RAM) + LENGTH(RAM);
} > RAM
/* Set the stack top to the end of RAM and move down the stack limit by
* the size of the stack_dummy section. */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - MBED_BOOT_STACK_SIZE;
PROVIDE(__stack = __StackTop);
}
I guess no new info about this? There is definitely a bug in python merge script somewhere. Merge step will consume all the memory on my machine and finally crashes. The “userfirmware.hex” file which the process tries to merge with Nordic softdevice is correct. I verified this by editing the python script to skip the merge and then merge by using Nordic’s “mergehex” tool. The resulting firmware was working correctly. I’m currently forced to use this way to build software.
Hi @traj! We are preparing mbed v5.13.2 where your issue should be fixed, stay tuned. As a workaround you can temporarily roll back to the previous version of the platform.
I finally managed to test the provided branch. Now the merge will succeed but there is some other issue. Compiled firmware does not work. Furthermore compile report shows that data and program usage took a huge increase versus builds with previous versions. Both have more than doubled and they are now above 50%.
I think so. Mbed-cli with latest mbed will give me larger hex that will not work. Could this be some configuration error? I’m using Nordic’s softdevice so there should be no mbed BLE stack present. But somehow the hex has gained huge weight. Nordic’s softdevice has been updated between versions but the change is not that much.
In the latest release they updated Nordic SDK to v15, but BLE is now based on Arm Cordio stack. And looks like this new stack has quite heavy memory footprint.
Yes I need the BLE. I just realized that my mbed_app.json config will include the Cordio stack. I found the correct extra_labels conf and will try with that.