Как мне узнать во время компиляции, какой объем флэш-памяти и динамической памяти (SRAM) STM32 используется?

У меня есть ответ для флэш-памяти, но вопрос с оперативной памятью все еще ускользает от меня.

У Arduino есть отличная функция, которая отображает использование флэш-памяти и оперативной памяти прямо во время компиляции. Бывший. на изображении ниже вы можете видеть, что эта программа Arduino использует 2084 байта флэш-памяти (6%) и что глобальные и статические переменные используют 188 байтов (9%) динамической памяти или SRAM.

введите описание изображения здесь

Когда я компилирую простую программу мигания на плате разработки STM32F103RB Nucleo в IDE System Workbench, я хотел бы знать то же самое: сколько флэш-памяти и оперативной памяти используется и сколько осталось?

По завершении сборки System Workbench показывает:

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

Когда я смотрю на двоичный выходной файл «SW4STM32/Debug/STM32F103RB_Nucleo.bin», я вижу, что он составляет 2908 байт, что является суммой text+ data. Следовательно, это должно быть мое использование Flash! Поскольку у меня 128 КБ флэш-памяти, это означает, что я использую 2908/(128*1024) = 2% от общего объема флэш-памяти.

Но как узнать, сколько SRAM используют мои глобальные и статические переменные и сколько доступно для локальных переменных (как показывает Arduino)?

Я еще не знаю, что это означает, но если это поможет вам помочь мне , вот вывод 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
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         00000a1c  0800010c  0800010c  0001010c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       00000028  08000b28  08000b28  00010b28  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .init_array   00000004  08000b50  08000b50  00010b50  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .fini_array   00000004  08000b54  08000b54  00010b54  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .data         00000004  20000000  08000b58  00020000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  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
                  CONTENTS, READONLY
  9 .debug_info   00006795  00000000  00000000  0002002d  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_abbrev 000013b2  00000000  00000000  000267c2  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_loc    00000d0f  00000000  00000000  00027b74  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_aranges 000002e0  00000000  00000000  00028888  2**3
                  CONTENTS, READONLY, DEBUGGING
 13 .debug_ranges 00000378  00000000  00000000  00028b68  2**3
                  CONTENTS, READONLY, DEBUGGING
 14 .debug_macro  00001488  00000000  00000000  00028ee0  2**0
                  CONTENTS, READONLY, DEBUGGING
 15 .debug_line   00003dcc  00000000  00000000  0002a368  2**0
                  CONTENTS, READONLY, DEBUGGING
 16 .debug_str    00066766  00000000  00000000  0002e134  2**0
                  CONTENTS, READONLY, DEBUGGING
 17 .comment      0000007f  00000000  00000000  0009489a  2**0
                  CONTENTS, READONLY
 18 .debug_frame  00000610  00000000  00000000  0009491c  2**2
                  CONTENTS, READONLY, DEBUGGING

(Добавлено позже) См. также:

  1. Мой собственный ответ на мой собственный вопрос здесь: преобразовать вывод binutils из формата «sysv» ( ) в формат «berkeley» ( )sizesize --format=sysv my_executablesize --format=berkeley my_executable
Использование динамической памяти невозможно определить без моделирования всех возможных путей выполнения. Вы можете определить статическое распределение ОЗУ, но это исключает как использование стека, так и динамическое использование типа malloc().
Да, статическое распределение ОЗУ - это все, что я пытаюсь выяснить. Это то, что выводит Arduino, и хотя он не говорит вам, как выглядит ваша RAM во все моменты времени (во время выполнения), он сообщает вам, как выглядит ваше статическое распределение RAM, что по-прежнему дает вам хорошее представление о том, насколько велико ваше приложение по отношению к микроконтроллеру, на котором оно работает. Так что, несмотря на его ограничения, я понимаю, что я получаю именно это, и это то, чего я хочу. Спасибо, что прямо указали на это. Это стоит понять.

Ответы (3)

Вся необходимая вам информация содержится в выводе size(ака arm-none-eabi-size):

   text    data     bss     dec     hex filename
   2896      12    1588    4496    1190 STM32F103RB_Nucleo.elf
  • text— это размер всего кода в вашем приложении.

  • dataразмер инициализированных глобальных переменных. Он учитывается как во флэш-памяти, так и в ОЗУ, поскольку во время запуска копируется из флэш-памяти в ОЗУ.

  • bssэто размер глобальных переменных, которые инициализируются нулем (или не инициализируются и, следовательно, по умолчанию равны нулю). Они хранятся только в оперативной памяти.

  • decи hexпредставляют собой сумму text + data + bssв десятичном и шестнадцатеричном формате. Это значение на самом деле мало что значит для микроконтроллера, поэтому его следует игнорировать. (В средах, где программа должна быть загружена в память перед запуском, это будет общий объем памяти, занимаемой программой.)

Чтобы рассчитать использование оперативной памяти вашей программой, сложите столбцы dataи bssвместе.
SRAM = data + bss

Чтобы рассчитать использование FLASH вашей программой, добавьте textи data.
FLASH = text + data

Итак, несмотря на то, что вы сказали это, decи hexэто размер моего файла ELF, мой файл ELF на самом деле составляет 616876 байт. Есть идеи, почему?
Кроме того, для тех, кто, возможно, упустил из виду этот факт (включая меня изначально), команда для просмотра этих значений размера находится прямо в выводе System Workbench:arm-none-eabi-size STM32F103RB_Nucleo.elf
Ой, я думал, что это размер файла, но на самом деле это просто сумма разделов text/data/bss. Его все равно следует игнорировать. :)
@duskwuff на самом деле не очень точно. Многие uC STM32 имеют более одной оперативной памяти (большинство F3, многие F4, все F4 и H7). Это не принимается во внимание. Еще проблема - стек, он его не учитывает.
@GabrielStaples - эльф содержит гораздо больше системных, символических и т. д. конфигураций. Если вы включите высокий уровень отладочной информации, ваш файл .elf может иметь длину много МБ :).
Я просматриваю Руководство пользователя компоновщика GNU , написанное Стивом Чемберленом и Яном Лансом Тейлором, а также просматриваю .ld-файл моего скрипта компоновщика. стр. 42 (pdf стр. 48) руководства ( скриншот здесь ) показывает «четыре выходных раздела», а именно, .text, .rodata, .data., и .bss. Показана dataвыше arm-none-eabi-sizeсумма того, что есть .rodataи .dataв скрипте компоновщика?
Мой вопрос выше остается в силе: где .rodataво всем этом?
Кроме того, что касается вашего утверждения: (In environments where a program must be loaded into memory before running, it would be the total memory footprint of the program.).... вы имеете в виду, как на обычном компьютере, верно? Я сейчас пытаюсь посмотреть эти значения для программы на обычном компьютере, а не на микроконтроллере. Итак, size name_of_executableкажется, ответ. Пример: size a.out.
Я разместил вопрос здесь: stackoverflow.com/q/64073080/4561887 .
Я только что добавил подробный анализ в свои новые ответы здесь: electronics.stackexchange.com/a/523439/26234 и здесь: stackoverflow.com/a/64080798/4561887 .

Если вам нужен быстрый bash-скрипт Linux для автоматического расчета использования Flash и SRAM, см. мой другой ответ здесь .

TLDR

Перейти прямо вниз к «Резюме» внизу.

Подробности:

@duskwuff -inactive- ответил на суть моего вопроса в своем / его ответе здесь , но я хотел бы добавить некоторые дополнительные сведения, а также ответить на свои дополнительные вопросы, которые я написал в комментариях под его ответом.

Во-первых, ключом к изучению этой информации был раздел «Основные концепции скриптов компоновщика» руководства GNU Linker , полностью включенный в мой раздел «Ссылки» ниже. Обратитесь к нему внизу этого ответа, ниже.

Для более подробного изучения некоторых аспектов этого ответа обратитесь также к другому моему ответу на связанный вопрос, который я задал в Stack Overflow здесь .

Оказывается, информация from objdump -h STM32F103RB_Nucleo.elfсодержит те же, более конкретные подразделы вывода, что и команда arm-none-eabi-size -x --format=sysv "STM32F103RB_Nucleo.elf", которая показывает sizeвывод в sysvформате, а не в berkeleyформате по умолчанию.

Вот снова вывод в формате berkeley из команды size( arm-none-eabi-sizeдля STM32 mcus):

arm-none-eabi-size "STM32F103RB_Nucleo.elf"
   text    data     bss     dec     hex filename
   2896      12    1588    4496    1190 STM32F103RB_Nucleo.elf

Обратите внимание, что arm-none-eabi-size "STM32F103RB_Nucleo.elf"это эквивалентно arm-none-eabi-size --format=berkeley "STM32F103RB_Nucleo.elf", поскольку --format=berkeleyиспользуется по умолчанию.

В objdump -h STM32F103RB_Nucleo.elfвыводе, который я разместил в своем вопросе, найдена вся информация, необходимая для ответа на мой вопрос, только в гораздо более подробном формате.

Как поясняется в руководстве компоновщика GNU (см. ниже), VMA означает «Адрес виртуальной памяти», а LMA означает «Адрес загрузки памяти». Адреса VMA — это место, где находятся данные во время выполнения (которые могут находиться в энергозависимой SRAM, поскольку некоторые данные копируются из флэш-памяти в SRAM при загрузке), а LMA — это место, где находятся данные, когда устройство выключено, и также до загрузки при загрузке (поэтому он должен находиться только в энергонезависимой флэш-памяти ). Некоторые данные будут скопированы из флэш-памяти (адрес LMA) в SRAM (адрес VMA) при загрузке.

Для этого микроконтроллера STM32 флэш-память начинается с адреса 0x08000000, а SRAM — с адреса 0x20000000. Таким образом, любые выходные разделы на objdump -hвыходе, которые имеют VMA (адрес времени выполнения) 0, поэтому не используются (даже на микроконтроллере) и могут быть немедленно отброшены. Это исключает вторую половину вывода objdump -h, большую часть которой составляет отладочная информация, от .ARM.attributesраздела вывода до .debug_frameраздела вывода включительно, оставляя нам только эти разделы вывода sysv, которые нас интересуют :

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .isr_vector   0000010c  08000000  08000000  00010000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         00000a1c  0800010c  0800010c  0001010c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       00000028  08000b28  08000b28  00010b28  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .init_array   00000004  08000b50  08000b50  00010b50  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .fini_array   00000004  08000b54  08000b54  00010b54  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .data         00000004  20000000  08000b58  00020000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  6 .bss          00000030  20000004  08000b5c  00020004  2**2
                  ALLOC
  7 ._user_heap_stack 00000604  20000034  08000b5c  00020034  2**0
                  ALLOC

Как видите , любой раздел READONLY, помеченный , хранится только во Flash-памяти по 0x08000000адресам -уровня и имеет один и тот же адрес LMA и VMA. Это имеет смысл, так как нет необходимости копировать его в SRAM, если он доступен только для чтения. Отмеченные разделы READONLYсоставляют textраздел в формате Беркли. Они включают:

.isr_vector
.text
.rodata

Итак, мы знаем, что:

.isr_vector + .text + .rodata = text

Это можно проверить, просуммировав их шестнадцатеричные размеры:

10c + a1c + 28 = b50

0xb50 — это десятичное число 2896, что соответствует выходному размеру textраздела по Беркли! И, опять же, как показывают 0x08000000адреса уровня LMA и VMA, это означает, что все эти разделы находятся только во флэш-памяти !

Вот мое описание этих разделов:

РАЗДЕЛЫ SYSV, СОСТАВЛЯЮЩИЕ textРАЗДЕЛ BERKELEY И ТОЛЬКО ВО ФЛЭШ-ПАМЯТИ:

  1. .isr_vector= таблица векторов ISR (подпрограмма обслуживания прерываний). Он просто указывает на все функции обратного вызова ISR для всех возможных прерываний, которые может обработать микроконтроллер.
  2. .text= логика программы; то есть: фактический код.
  3. .rodata= данные только для чтения; то есть: constи constexprстатические и глобальные переменные, которые доступны только для чтения.

Далее мы видим, что NON- READONLYразделы, которые также являются ALLOCи LOADразделами, включают в себя:

.init_array
.fini_array
.data

Итак, мы знаем, что они составляют dataсекцию беркли:

.init_array + .fini_array + .data = data

Это можно проверить, просуммировав их шестнадцатеричные размеры:

4 + 4 + 4 = c

0xc — это десятичное число 12, что соответствует выходному размеру dataраздела по Беркли.

Я не знаю, что означают разделы .init_arrayили .fini_array(если вы знаете, пожалуйста, ответьте или оставьте комментарий), и я запутался в их местонахождении, поскольку их адреса LMA и VMA идентичны, что указывает на то, что они как во Flash, так и только во Flash. . Однако по адресам секции видно .data, что она занимает как Flash-память (при LMA [адрес загрузки] = 0x08000b58), так и память SRAM (при VMA [адрес времени выполнения] = 0x20000000). Это означает, что эти данные копируются из флэш-памяти в начало SRAM. Это происходит во время процедуры запуска. .dataсодержит НЕ-нулевые инициализированные (т.е. инициализированные чем-то отличным от нуля) статические и глобальные переменные. В итоге:

РАЗДЕЛЫ SYSV, СОСТАВЛЯЮЩИЕ dataРАЗДЕЛ BERKELEY, НАХОДЯЩИЕСЯ КАК ВО FLASH, ТАК И В SRAM, И КОТОРЫЕ КОПИРУЮТСЯ ИЗ FLASH В SRAM ВО ВРЕМЯ ЗАПУСКА:

  1. .data= НЕнулевые инициализированные (т.е. инициализированные чем-то отличным от нуля) статические и глобальные переменные

РАЗДЕЛЫ SYSV, СОСТАВЛЯЮЩИЕ dataРАЗДЕЛ BERKELEY И КОТОРЫЕ ЯВНО НАХОДЯТСЯ ТОЛЬКО В ФЛЭШ-ПАМЯТИ?:

  1. .init_array= неизвестно
  2. .fini_array= неизвестно

Это оставляет нам только эти разделы, отмеченные ALLOCи больше ничего не осталось:

.bss
._user_heap_stack

Итак, мы знаем, что они составляют bssраздел Беркли:

.bss + ._user_heap_stack = bss

Это можно проверить, просуммировав их шестнадцатеричные размеры:

30 + 604 = 634

0x634 — это десятичное число 1588, которое соответствует размеру беркли для раздела bss.

Это действительно интересно! , так как это показывает, что раздел беркли bssвключает не только .bssраздел вывода (статические и глобальные переменные с нулевой инициализацией), но также включает раздел вывода ._user_heap_stack, который, возможно (или, скорее, мне кажется) размер кучи мы указываем внутри программного обеспечения конфигурации STM32Cube. В любом случае это SRAM, выделенная как для стека времени выполнения (для локальных переменных), так и для кучи (для динамически выделяемой памяти). В итоге:

РАЗДЕЛЫ SYSV, СОСТАВЛЯЮЩИЕ bssРАЗДЕЛ BERKELEY И ЗАНИМАЮЩИЕ МЕСТО ТОЛЬКО В SRAM, НО НЕ FLASH:

  1. .bss= инициализированные нулем статические и глобальные переменные; эта SRAM устанавливается на все нули при запуске программы.
  2. ._user_heap_stack= (я думаю) полностью неинициализированная SRAM, которая выделена для стека времени выполнения (для локальных переменных) и кучи (для динамически выделяемой памяти).

Краткое содержание:

Вот разбивка того, какие разделы вывода sysv из objdump -h STM32F103RB_Nucleo.elfвывода (также показанные с меньшими подробностями в arm-none-eabi-size -x --format=sysv "STM32F103RB_Nucleo.elf"выводе) составляют какие разделы вывода berkeley.

На изображении ниже вы можете увидеть все 3 раздела вывода berkely, обведенные разными цветами:

  1. [ЖЕЛТЫЙ] Разделы вывода в формате Беркли text(только для чтения, программная логика и константные статические и глобальные переменные) выделены желтым цветом .

     .isr_vector + .text + .rodata = text
    
    1. .isr_vector[ТОЛЬКО ДЛЯ ФЛЭШ] = таблица векторов ISR (процедура обслуживания прерываний). Он просто указывает на все функции обратного вызова ISR для всех возможных прерываний, которые может обработать микроконтроллер.
    2. .text[ТОЛЬКО ВО FLASH] = программная логика; то есть: фактический код.
    3. .rodata[ТОЛЬКО FLASH] = данные только для чтения; то есть: constи constexprстатические и глобальные переменные, которые доступны только для чтения.
  2. [СИНИЙ] Разделы вывода в формате Беркли data(ненулевые инициализированные [т.е. инициализированные значениями, отличными от нуля] статические и глобальные переменные) выделены синим цветом .

     .init_array + .fini_array + .data = data
    
    1. .init_array[ТОЛЬКО ВСПЫШКА появляется] = неизвестно.
    2. .fini_array[ТОЛЬКО ВСПЫШКА появляется] = неизвестно.
    3. .data[В ОБА FLASH И SRAM] = ненулевые инициализированные (т.е. инициализированные чем-то отличным от нуля) статические и глобальные переменные. Эти значения должны быть скопированы из флэш-памяти в SRAM при запуске, чтобы инициализировать соответствующие им статические или глобальные переменные в SRAM.
  3. [RED] Секции вывода в формате berkeley bss(статические и глобальные переменные, инициализированные нулями, а также, по-видимому, неинициализированные пространство стека и кучи) выделены красным .

     .bss + ._user_heap_stack = bss
    
    1. .bss[ТОЛЬКО SRAM] = статические и глобальные переменные с нулевой инициализацией; эта SRAM устанавливается на все нули при запуске программы.
    2. ._user_heap_stack[ТОЛЬКО SRAM] = полностью неинициализированная (я думаю) SRAM, которая выделена для стека времени выполнения (для локальных переменных) и кучи (для динамически выделяемой памяти).
  4. [GREY] Отброшенные разделы вывода sysv, которые не участвуют ни в одном из 3 разделов вывода berkeley, выделены серым цветом .

введите описание изображения здесь

Выводы памяти:

  1. Флэш-память:
    1. Использование флэш-памяти = berkeley text+ berkeley data.
      1. Флэш-память, используемая только таблицей векторов функций ISR = .isr_vector.
      2. Флэш-память, используемая только программной логикой = .text.
      3. Флэш-память, используемая статическими и глобальными переменными только для чтения = .rodata.
  2. SRAM-память:
    1. Использование SRAM из статических и глобальных переменных И выделенное для использования стека и кучи = berkeley bss+ berkeley data.
      1. SRAM используется только статическими и глобальными переменными = sysv (.bss + .data). Обратите внимание на точки ( .) перед каждым из этих имен здесь, в отличие от отсутствия точек выше.
      2. SRAM выделена специально для стека (локальные переменные) и кучи (динамическое выделение памяти) = (видимо) ._user_heap_stack.
      3. SRAM ни для чего не выделена = SRAM_total - (berkeley bss + berkeley data).

Использованная литература:

  1. Руководство GNU Linker ( ld), раздел «3.1 Основные концепции скриптов компоновщика»: https://sourceware.org/binutils/docs/ld/Basic-Script-Concepts.html#Basic-Script-Concepts :

    3.1 Основные концепции скрипта компоновщика

    Нам нужно определить некоторые основные понятия и словарный запас, чтобы описать скриптовый язык компоновщика.

    Компоновщик объединяет входные файлы в один выходной файл. Выходной файл и каждый входной файл имеют специальный формат данных, известный как формат объектного файла . Каждый файл называется объектным файлом . Выходной файл часто называют исполняемым файлом , но для наших целей мы также будем называть его объектным файлом. Каждый объектный файл имеет, среди прочего, список разделов . Иногда мы называем раздел во входном файле входным разделом ; аналогично раздел в выходном файле является выходным разделом .

    Каждый раздел в объектном файле имеет имя и размер. Большинство разделов также имеют связанный блок данных, известный как содержимое раздела . Раздел может быть помечен как загружаемый , что означает, что содержимое должно быть загружено в память при запуске выходного файла. Раздел без содержимого может быть выделяемым , что означает, что область в памяти должна быть выделена, но ничего конкретного туда не должно загружаться (в некоторых случаях эта память должна быть обнулена). Раздел, который нельзя ни загрузить, ни выделить, обычно содержит некоторую отладочную информацию.

    Каждая загружаемая или размещаемая секция вывода имеет два адреса. Первый — это VMA или адрес виртуальной памяти. Это адрес, который раздел будет иметь при запуске выходного файла. Второй — это LMA или адрес загрузки памяти. Это адрес, по которому раздел будет загружен. В большинстве случаев два адреса будут одинаковыми. Примером того, когда они могут отличаться, является случай, когда раздел данных загружается в ПЗУ, а затем копируется в ОЗУ при запуске программы (этот метод часто используется для инициализации глобальных переменных в системе на основе ПЗУ). В этом случае адрес ROM будет LMA, а адрес RAM будет VMA.

    Вы можете увидеть разделы в объектном файле, используя objdumpпрограмму с опцией '-h'.

    Каждый объектный файл также имеет список символов , известный как таблица символов . Символ может быть определен или не определен. У каждого символа есть имя, а у каждого определенного символа, среди прочего, есть адрес. Если вы скомпилируете программу на C или C++ в объектный файл, вы получите определенный символ для каждой определенной функции и глобальной или статической переменной. Каждая неопределенная функция или глобальная переменная, на которую есть ссылка во входном файле, станет неопределенным символом.

    Вы можете увидеть символы в объектном файле с помощью программы nmили с помощью objdumpпрограммы с опцией '-t'.

  2. Мой собственный ответ на мой собственный вопрос здесь: преобразовать вывод binutils из формата «sysv» ( ) в формат «berkeley» ( )sizesize --format=sysv my_executablesize --format=berkeley my_executable

.init_arrayи .fini_array-- глобальные переменные в C++ будут иметь свои конструкторы и деструкторы, запускаемые до того, как main начнет выполняться и после выхода из main соответственно. Эти два раздела содержат (указатели на) функции создания и уничтожения, которые должны вызываться библиотекой поддержки времени выполнения. В чистом стандарте ISO C такой вещи нет (вы не можете инициализировать глобальную переменную C динамическим выражением), но gcc добавляет ее в C как расширение, используя __attribute((constructor))__и __attribute__((destructor)).

Скрипт/команда для автоматического расчета использования Flash и SRAM.

В качестве расширения двух других ответов, включая мой собственный , вот однострочный скрипт Linux bash, который вы можете использовать для автоматического расчета FLASHи SRAMиспользования.

Это предполагает, что ваша команда для просмотра информации о размере Berkeley вашего файла .elf имеет формат arm-none-eabi-size "STM32F103RB_Nucleo.elf". Обновите этот путь до интересующего вас файла .elf. Если вы ищете файлы Linux .elf или обычные исполняемые файлы вместо файлов .elf STM32, используйте sizeвместо arm-none-eabi-size. Пример: size path/to/my_program.elf.

В любом случае, вот сценарий:

size_info=$(arm-none-eabi-size "STM32F103RB_Nucleo.elf" | awk NR\>1); \
text=$(echo "$size_info" | awk '{print $1}'); \
data=$(echo "$size_info" | awk '{print $2}'); \
bss=$(echo "$size_info" | awk '{print $3}'); \
flash=$(($text + $data)); \
sram=$(($bss + $data)); \
echo "FLASH used                    = $flash bytes"; \
echo "SRAM used by global variables = $sram bytes"

Предполагая, что arm-none-eabi-size "STM32F103RB_Nucleo.elf"это показывает:

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

... вот пример запуска вышеуказанного скрипта:

FLASH used                    = 2908 bytes
SRAM used by global variables = 1600 bytes

Разбивка Flash, SRAM и 3 разделов Berkely

  • Флэш и SRAM:
    • FLASH = text + data
    • SRAM = bss + data
  • 3 раздела Беркли:
    • text= данные программы + вектор ISR + родата (данные только для чтения: constстатические constexprи глобальные переменные только для чтения)
    • data= НЕнулевые инициализированные (т.е. инициализированные числом, отличным от нуля) статические и глобальные переменные, + .init_array + .fini_array
    • bss= инициализированные нулями статические и глобальные переменные + пространство стека и кучи, выделенное сценарием компоновщика

Для получения более подробной информации см. Мой другой, очень подробный ответ здесь: Как мне узнать во время компиляции, сколько флэш-памяти STM32 и динамической памяти (SRAM) израсходовано?

Использованная литература:

  1. основной ответ: Как мне узнать во время компиляции, сколько из флэш-памяти STM32 и динамической памяти (SRAM) израсходовано?
  2. мой другой ответ: как мне узнать во время компиляции, сколько из флэш-памяти STM32 и динамической памяти (SRAM) израсходовано?
  3. как добавить числа в bash: https://stackoverflow.com/questions/6348902/how-can-i-add-numbers-in-a-bash-script/6348941#6348941
  4. как использовать awkдля удаления первой строки текстового блоба: https://superuser.com/questions/284258/remove-first-line-in-bash/284270#284270
  5. общий awkпример из моих собственных заметок , чтобы напомнить мне, как его использовать:du -h | tail -n 1 | awk '{print $1}'