3 # This is a wrapper for the elf-size-report.awk script which prints a detailed report
4 # of memory segment allocations and usage in a given ELF file, based on gcc 'size' output.
5 # This script sets up memory segment information needed by the awk script.
6 # If more than one .elf file is given, then a comparison (delta memory use) report is
7 # also performed using elf-size-compare.awk.
8 # Currently supports some STMicro & Atmel ARM MCUs. May not work with all placement strategies.
11 # [VAR=value] ./elf-memory-report.sh [options] [file.elf] [file2.elf] [...]
13 # Where VAR is any of the CAPITALIZED variables below. More than one can be specified,
14 # and any VAR can also be set in the environment.
15 # SIZE : gcc binutils 'size' command to use, default is "arm-none-eabi-size".
17 # Specifies MCU model on which to base default segment location/size parameters. Also see "--mcu=" option.
18 # MEM_START_<segment> & MEM_SIZE_<segment> : (read code below for defaults)
19 # Allows specifying additional/custom segment information, eg. MEM_SIZE_FLASH=768
21 # Options can be one or more of the following:
23 # Set MCU type. Same as setting the MCU env. variable, and overrides it.
25 # Some linker scripts duplicate .data in the output (eg: .data and .data_run).
26 # Set this option to skip .data from being counted in RAM a 2nd time
27 # (it is always shown as being in Flash).
29 # When specifying multiple elf files, only show the final comparison report.
31 # Opposite and exclusive of previous option, that is, do NOT show comparison report (only size reports).
33 # If an elf file is not specified on the command line, this script will prompt for one.
36 # MCU="STM32F439xI" MEM_SIZE_SDRAM2=8192 ./elf-memory-report.sh path/to/firmware.elf
37 # ./elf-memory-report.sh --mcu ATSAM3S4C --compare-only firmware_new.elf firmware_old.elf
38 # set -k && ./elf-memory-report.sh MCU=STM32F427VG --skip-data firmware.elf
39 # (the -k switch allows variable assignment anywhere on the command line)
40 # c:\cygwin\bin\bash -kc './elf-memory-report.sh --mcu ATSAM3S8C "c:\windows\path\with spaces\firmware.elf"'
42 # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
43 # Copyright (c)2016 Maxim Paperno
44 # Copyright (c)2017 OpenTX
47 # -- gcc binutils 'size' command to use
48 : ${SIZE:="arm-none-eabi-size"}
50 # -- MCU type, if defined will set certain memory defaults
51 # e.g. STM32F205xE or ATSAM3S4C
59 --mcu=*) MCU
="${i#*=}"; shift;;
60 --skip-data) skip_data
=1; shift;;
61 --compare-only) compare
=1; shift;;
62 --no-compare) compare
=0; shift;;
66 # -- make sure gawk is installed
68 if gawk
--version >/dev
/null
2>&1; then
69 [[ "$OSTYPE" == "darwin"* ]] && AWKCMD
="gawk -nf"
71 echo "GAWK is required, exiting."
75 # -- defaults which may change based on MCU
76 default_flash_addr
=0x08000000
77 default_flash_sz
=1024 # KB
82 # -- Set defaults based on MCU type
83 if [[ $MCU != "unknown" ]] ; then
84 mcu_brand
=${MCU:0:2} # ST or AT
85 if [[ $mcu_brand == "ST" && ${#MCU} -ge 7 ]] ; then
87 stm_series
=${MCU:6:1} # 4
88 stm_ser_ex
=${MCU:7:1} # 2
89 stm_flash
=${MCU:10:1} # G
93 "I") default_flash_sz
=2048;;
94 "G") default_flash_sz
=1024;;
95 "E") default_flash_sz
=512;;
96 "C") default_flash_sz
=256;;
98 if (( $stm_series == 4 )) ; then
100 if (( $stm_ser_ex >= 2 )) ; then
104 elif [[ $mcu_brand == "AT" && ${#MCU} -ge 9 ]] ; then
106 atm_series
=${MCU:5:4} # 3S4C
107 default_flash_addr
=0x00400000
109 "3S8C") default_flash_sz
=512; default_ram1_sz
=64;;
110 "3S4C") default_flash_sz
=256; default_ram1_sz
=48;;
111 "3S2C") default_flash_sz
=128; default_ram1_sz
=32;;
114 echo "MCU type unrecognized, exiting."
119 # -- target memory locations in hex
120 : ${MEM_START_FLASH:=$default_flash_addr}
121 : ${MEM_START_CCRAM:=0x10000000}
122 : ${MEM_START_SRAM1:=0x20000000}
123 : ${MEM_START_SRAM2:=0x2001c000}
124 : ${MEM_START_SRAM3:=0x20020000}
125 : ${MEM_START_PSRAM1:=0x60000000}
126 : ${MEM_START_SDRAM1:=0xC0000000}
127 : ${MEM_START_SDRAM2:=0xD0000000}
129 # -- target memory sizes in KB
130 : ${MEM_SIZE_FLASH:=$default_flash_sz}
131 : ${MEM_SIZE_CCRAM:=$default_ccm_sz}
132 : ${MEM_SIZE_SRAM1:=$default_ram1_sz}
133 : ${MEM_SIZE_SRAM2:=$default_ram2_sz}
134 : ${MEM_SIZE_SRAM3:=$default_ram3_sz}
135 : ${MEM_SIZE_PSRAM1:=0}
136 : ${MEM_SIZE_SDRAM1:=0}
137 : ${MEM_SIZE_SDRAM2:=0}
139 # -- prompt for elf file if not on command line
140 if [[ -z "$@" ]] ; then
141 read -p "Elf file(s): " ELF_FILES
146 # -- Set arrays for awk script. The segments should be in increasing address order.
147 names
=("Flash" "CCRAM" "SRAM1" "SRAM2" "SRAM3" "PSRAM1" "SDRAM1" "SDRAM2")
148 addrs
=(${MEM_START_FLASH} ${MEM_START_CCRAM} ${MEM_START_SRAM1} ${MEM_START_SRAM2} ${MEM_START_SRAM3} \
149 ${MEM_START_PSRAM1} ${MEM_START_SDRAM1} ${MEM_START_SDRAM2})
150 sizes
=(${MEM_SIZE_FLASH} ${MEM_SIZE_CCRAM} ${MEM_SIZE_SRAM1} ${MEM_SIZE_SRAM2} ${MEM_SIZE_SRAM3} \
151 ${MEM_SIZE_PSRAM1} ${MEM_SIZE_SDRAM1} ${MEM_SIZE_SDRAM2})
153 base_dir
="$(dirname "$BASH_SOURCE")"
154 base_dir
="${base_dir%%[[:space:]]}" # sometimes we get trailing \n
156 # -- run the ARM size command for each elf file and send output to awk script
160 if [[ ! -f "$elf" ]] ; then
161 echo "ELF file \"$elf\" not found."
164 #${SIZE} -A -x ${elf}
165 escelf
="${elf//\\//}"
166 output
=`${SIZE} -A -x ${elf} | ${AWKCMD} "${base_dir}/elf-size-report.awk" \
169 -v skip_data=${skip_data} \
170 -v names="${names[*]}" \
171 -v addrs="${addrs[*]}" \
172 -v sizes="${sizes[*]}"`
173 if (( compare
!= 1 )) ; then
178 all_output
+="${output}\n"
180 # -- if more than one elf file was given, also run a comparison report
181 if (( file_cnt
> 1 && compare
)) ; then
182 echo "$all_output" |
${AWKCMD} "${base_dir}/elf-size-compare.awk"