I am running the "CMSIS-RTOS2 Blinky (uVision Simulator)" example for Cortex-M4 in Arm Dev Studio on Windows. I am using ARM C/C++ Compiler 6.
The example runs ok. I have now added several C++ files to it. These compile and link ok, but when I increase the number of objects ( instantiated by new() ) on the heap the program either crashes or raises a bad_alloc exception.
I have tried increasing the heap allocation in the scatter file but that seems to make no difference. I am therefore wondering whether I am increasing it correctly or whether there is some startup requirement for C++ that I am unaware of.
My scatter file is:
CMSIS-RTOS2 Blinky (uVision Simulator)_Simulation\RTE\Device\ARMCM4\ARMCM4_ac6.sct
and the contents are:
#! armclang -E --target=arm-arm-none-eabi -mcpu=cortex-m4 -xc ; command above MUST be in first line (no comment above!) /* ;-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- */ /*--------------------- Flash Configuration ---------------------------------- ; <h> Flash Configuration ; <o0> Flash Base Address <0x0-0xFFFFFFFF:8> ; <o1> Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> *----------------------------------------------------------------------------*/ #define __ROM_BASE 0x00000000 #define __ROM_SIZE 0x00080000 /*--------------------- Embedded RAM Configuration --------------------------- ; <h> RAM Configuration ; <o0> RAM Base Address <0x0-0xFFFFFFFF:8> ; <o1> RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> *----------------------------------------------------------------------------*/ #define __RAM_BASE 0x20000000 #define __RAM_SIZE 0x00040000 /*--------------------- Stack / Heap Configuration --------------------------- ; <h> Stack / Heap Configuration ; <o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; <o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> *----------------------------------------------------------------------------*/ #define __STACK_SIZE 0x00000400 #define __HEAP_SIZE 0x0000A000 /* ;------------- <<< end of configuration section >>> --------------------------- */ /*---------------------------------------------------------------------------- User Stack & Heap boundary definition *----------------------------------------------------------------------------*/ #define __STACK_TOP (__RAM_BASE + __RAM_SIZE) /* starts at end of RAM */ #define __HEAP_BASE (AlignExpr(+0, 8)) /* starts after RW_RAM section, 8 byte aligned */ /*---------------------------------------------------------------------------- Scatter File Definitions definition *----------------------------------------------------------------------------*/ #define __RO_BASE __ROM_BASE #define __RO_SIZE __ROM_SIZE #define __RW_BASE __RAM_BASE #define __RW_SIZE (__RAM_SIZE - __STACK_SIZE - __HEAP_SIZE) LR_ROM __RO_BASE __RO_SIZE { ; load region size_region ER_ROM __RO_BASE __RO_SIZE { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } RW_RAM __RW_BASE __RW_SIZE { ; RW data .ANY (+RW +ZI) } #if __HEAP_SIZE > 0 ARM_LIB_HEAP __HEAP_BASE EMPTY __HEAP_SIZE { ; Reserve empty region for heap } #endif ARM_LIB_STACK __STACK_TOP EMPTY -__STACK_SIZE { ; Reserve empty region for stack } }
so the heap allocation should be 0xA000.
The linker command is:
armlink.exe --entry=Reset_Handler --scatter="C:\prototypes\CMSIS-RTOS2 Blinky (uVision Simulator)_Simulation/RTE/Device/ARMCM4/ARMCM4_ac6.sct" --info=sizes --strict -o "CMSIS-RTOS2 Blinky (uVision Simulator)_Simulation.axf" ./src/Elysion.o ./src/ElysionSectionList.o ./RTE/Device/ARMCM4/startup_ARMCM4.o ./RTE/Device/ARMCM4/system_ARMCM4.o ./RTE/Compiler/EventRecorder.o ./RTE/CMSIS/RTX_Config.o ./RTE/CMSIS/irq_armv7m.o ./RTE/CMSIS/os_systick.o ./RTE/CMSIS/rtx_delay.o ./RTE/CMSIS/rtx_evflags.o ./RTE/CMSIS/rtx_evr.o ./RTE/CMSIS/rtx_kernel.o ./RTE/CMSIS/rtx_lib.o ./RTE/CMSIS/rtx_memory.o ./RTE/CMSIS/rtx_mempool.o ./RTE/CMSIS/rtx_msgqueue.o ./RTE/CMSIS/rtx_mutex.o ./RTE/CMSIS/rtx_semaphore.o ./RTE/CMSIS/rtx_system.o ./RTE/CMSIS/rtx_thread.o ./RTE/CMSIS/rtx_timer.o ./Blinky.o ./ElysionMain.o
so, correct scatter code and, hopefully, correct startup files are used.
My C++ compiler options are:
armclang.exe --target=arm-arm-none-eabi -I"C:\prototypes\CMSIS-RTOS2 Blinky (uVision Simulator)_Simulation/src" -xc++ -fexceptions -O0 -g -DARMCM4 -D_RTE_ -mcpu=cortex-m4 -mfpu=none -mlittle-endian -Oz -g -Wall -fshort-enums -fshort-wchar -ffunction-sections -fno-rtti -MD -MP -c -o "ElysionMain.o" "../ElysionMain.cpp"
Can you please suggest what may be wrong?
Hi again David,
I note that __RAM_SIZE is defined as 0x40000 (256K), however the model has 8MB (0x800000) of RAM there. See ZBTSRAM at:https://developer.arm.com/documentation/100964/1115/Microcontroller-Prototyping-System-2/MPS2---memory-maps/MPS2---memory-map-for-models-without-the-Armv8-M-additions
Does extending this value, and then also the value of __HEAP_SIZE help? Does allocating a huge heap space help, at least for initial estimation purposes?
There is some advise on understanding how much stack you need, such as here:https://developer.arm.com/documentation/100748/0617/Writing-Optimized-Code/Stack-use-in-C-and-C--
However heap requirement is more difficult as it is dynamic, and is especially used in C++.
There are some 'classic' ways to see how much heap is used. For example, before running any init code, fill the RAM with a known value, then execute and dump out the memory to see what has changed. This can be done in Development Studio with commands such as:
memory fill 0x20000000 0x207fffff 4 0xdeadbeef dump ihex memory "before.txt" 0x20000000 0x207fffff continue dump ihex memory "after.txt" 0x20000000 0x207fffff
and then compare the memory dumps with any file comparison tool.
I'm not sure if this is a factor here,. but I note you are building without any optimization, -O0. It might be worth increasing this, as -O0 is very un-optimized.
Hi Ronan
Thanks very much for your reply. I am very grateful for your continued help with my many questions.
May I just ask one more, hopefully easy, question. How can I determine whether the Cortex-M4 is configure for big or little endian mode?Best regards
David
You are very welcome.
Endianess is reflected in bit 15 of the AIRCR register, and is set on reset by an input pin to the CPU. It cannot be changed after that.https://developer.arm.com/documentation/100166/0001/System-Control/System-control-registers
A complete description is given in the Architecture Reference Manual:https://developer.arm.com/documentation/ddi0403/latest/
It can also be observed in the register view of the debugger:
Hi again Ronan,
I am making progress but am still struggling with developing our code in ARM Dev Studio using armclang. I have set the RAM SIze, Heap and Stack to large values but I still find that the code crashes in unexpected places. It is very hard to find the reason. I am particularly seeing problems with std::cout() - some cout calls never return. Even printf() can be unreliable. I fixed one occurrence of a hang today by simply removing a std::string instance.
Do you have any suggestions why these problems may be happening please?Best regards,
Hi David,
Some general debugging assistance... do you make use of trace? You can enable this in the DTSL options pane in the debug configurations window.
If you are triggering an exception - you can use the Manage Signals in the breakpoints pane, to set breakpoints on various exceptions.
Hopefully these will help you decipher the issue.
Thanks Ronan, I will give those a try.Best regards,
Your answer led me to the fix. The trace showed that osRtxErrorStackOverflow was occurring. Increasing the thread's stack size fixed the problem. Thanks very much for your help.
Best regards