How do I find out at compile time how much of an STM32's Flash memory and dynamic memory (SRAM) is used up?

I have the answer for Flash memory, but the RAM question still eludes me.

Arduino has this super nice feature which displays flash and RAM usage right at compile time. Ex. in the image below you can see that this Arduino program uses 2084 bytes of flash (6%) and that global and static variables use 188 bytes (9%) of dynamic memory, or SRAM.

When I compile a simple blink program on an STM32F103RB Nucleo dev board in the System Workbench IDE I'd like to know the same thing: how much Flash and RAM is used, and how much is remaining?

When building completes, System Workbench shows:

Generating binary and Printing size information:
arm-none-eabi-objcopy -O binary "STM32F103RB_Nucleo.elf" "STM32F103RB_Nucleo.bin"
arm-none-eabi-size "STM32F103RB_Nucleo.elf"
text    data     bss     dec     hex filename
2896      12    1588    4496    1190 STM32F103RB_Nucleo.elf


When I look at the binary output file, "SW4STM32/Debug/STM32F103RB_Nucleo.bin", I see it is 2908 bytes, which is the sum of text + data. Therefore, that must be my Flash usage! Since I have 128KB of Flash, that means I am using 2908/(128*1024) = 2% of the total Flash space.

But how do I figure out how much SRAM my global and static variables are using, and how much is available for local variables (like Arduino shows)?

I don't have a clue what any of this stuff means yet, but if this is helpful to help you help me, here is the output from objdump -h STM32F103RB_Nucleo.elf:

\$ objdump -h STM32F103RB_Nucleo.elf

STM32F103RB_Nucleo.elf:     file format elf32-little

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
0 .isr_vector   0000010c  08000000  08000000  00010000  2**0
1 .text         00000a1c  0800010c  0800010c  0001010c  2**2
2 .rodata       00000028  08000b28  08000b28  00010b28  2**0
3 .init_array   00000004  08000b50  08000b50  00010b50  2**2
4 .fini_array   00000004  08000b54  08000b54  00010b54  2**2
5 .data         00000004  20000000  08000b58  00020000  2**2
6 .bss          00000030  20000004  08000b5c  00020004  2**2
ALLOC
7 ._user_heap_stack 00000604  20000034  08000b5c  00020034  2**0
ALLOC
8 .ARM.attributes 00000029  00000000  00000000  00020004  2**0
9 .debug_info   00006795  00000000  00000000  0002002d  2**0
10 .debug_abbrev 000013b2  00000000  00000000  000267c2  2**0
11 .debug_loc    00000d0f  00000000  00000000  00027b74  2**0
12 .debug_aranges 000002e0  00000000  00000000  00028888  2**3
13 .debug_ranges 00000378  00000000  00000000  00028b68  2**3
14 .debug_macro  00001488  00000000  00000000  00028ee0  2**0
15 .debug_line   00003dcc  00000000  00000000  0002a368  2**0
16 .debug_str    00066766  00000000  00000000  0002e134  2**0
17 .comment      0000007f  00000000  00000000  0009489a  2**0
18 .debug_frame  00000610  00000000  00000000  0009491c  2**2

• Dynamic memory usage cannot be determined without simulating every possible path of execution. You can determine static RAM allocations, but that excludes both stack usage and malloc() type dynamic usage. – Chris Stratton Mar 22 '18 at 1:06
• Yeah, static RAM allocations is all I'm trying to figure out. That's what Arduino is outputting too, and although it doesn't tell you what your RAM looks like at all of the points in time (in run-time), it does tell you what your static RAM allocation looks like, which still gives you a good feel for how big your application is relative to the microcontroller it is running on. So despite its limitations I understand that's what I'm getting, and that's what I want. Thanks for explicitly pointing this out though. It's worth understanding. – Gabriel Staples Mar 22 '18 at 1:11

The information you need is all in the output from size (aka arm-none-eabi-size):

   text    data     bss     dec     hex filename
2896      12    1588    4496    1190 STM32F103RB_Nucleo.elf

• text is the size of all code in your application.

• data is the size of initialized global variables. It counts against both flash memory and RAM, as it's copied from flash to RAM during startup.

• bss is the size of global variables which are initialized to zero (or are uninitialized, and hence default to zero). They're stored in RAM only.

• dec and hex are the sum of text + data + bss in decimal and hexadecimal. This value doesn't really mean much on a microcontroller, so it should be ignored. (In environments where a program must be loaded into memory before running, it would be the total memory footprint of the program.)

To calculate the RAM usage of your program, add the data and bss columns together.

To calculate the FLASH usage of your program, add text and data.

• So, despite the fact you said that dec and hex are the size of my ELF file, my ELF file is actually 616876 bytes. Any idea why? – Gabriel Staples Mar 22 '18 at 0:00
• Also, for those who may have overlooked this fact (myself included initially), the command to see these size values is right in the System Workbench output: arm-none-eabi-size STM32F103RB_Nucleo.elf – Gabriel Staples Mar 22 '18 at 0:02
• Oops, I thought it was the size of the file, but it's actually just the sum of the text/data/bss sections. It should still be ignored. :) – duskwuff Mar 22 '18 at 0:06
• @duskwuff it is actually not very accurate. Many STM32 uC have more than one RAM (most of F3, many F4, all F4 & H7). It does not take it into the consideration. Another problem - the stack, it does not take it into the account. – P__J__ Mar 22 '18 at 9:52
• @GabrielStaples - elf contains much more system, symbolic etc configuration. If you enable high level of the debugging information your .elf file may be many MB long :). – P__J__ Mar 22 '18 at 9:54