
ESP32: Анализ использования оперативной памяти
Контроллер ESP32 имеет всего 512КБ оперативной памяти, и в сложных проектах разработчик может столкнуться с ее нехваткой. В статье рассказано о встроенных программных инструментах ESP IDF, которые позволят найти проблемные точки и оптимизировать их.
Контроллер ESP32 имеет 512 КБ памяти SRAM. Хотя этот объем может показаться относительно небольшим, при грамотном использовании он может предоставить множество возможностей для разработчика.
Исходный код приложения обычно содержит ряд файлов и библиотек, и компоновщик в своей работе извлекает из этих компонентов различные функции и переменные. Компоновщик обычно оптимизирует объекты, которые не используются (или на которые не ссылаются) в готовой прошивке. Таким образом, в зависимости от того, что вы делаете в своем приложении, вклад различных компонентов в использование памяти меняется.
В состав фреймворка ESP IDF входит утилита idf_size.py, которая позволит оценить использование памяти, чтобы вы могли идентифицировать и оптимизировать проблемные точки. Утилита связана со скриптами сборки, поэтому вы можете напрямую запускать команду make target, чтобы увидеть потребление памяти, не запоминая других команд.
Давайте посмотрим, как можно использовать эту утилиту, чтобы оценить эффективность использования памяти.
Память, выделенная под конкретные компоненты
Первое, что нужно сделать при анализе распределения памяти, это посмотреть, какое влияние каждый из используемых компонентов оказывает на окончательный образ прошивки. Это можно сделать, указав цель size-components для системы сборки. Выполнение этой команды после сборки приложения examples/wifi/power_save дает следующий результат:
$ make IDF_PATH=~/work/idf size-components
Total sizes:
DRAM .data size: 14200 bytes
DRAM .bss size: 23224 bytes
Used static DRAM: 37424 bytes ( 143312 available, 20.7% used)
Used static IRAM: 62344 bytes ( 68728 available, 47.6% used)
Flash code: 368546 bytes
Flash rodata: 65916 bytes
Total image size:~ 511006 bytes (.bin may be padded larger)
Per-archive contributions to ELF file:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
На экране видна итоговая информация об объеме, занимаемом всеми компонентами прошивки. Кроме того, в таблице предоставлена подробная информация по каждому из компонентов:
- data: это размер секции .data приложения. В этой секции размещаются предварительно инициализированные данные и константы.
- bss: это размер секции .bss. Здесь размещаются любые глобальные или статически определенные переменные и объекты, которые инициализируются нулями при загрузке.
- IRAM: это размер секции кода ( .text ), которую необходимо загрузить в IRAM. Обратите внимание, что большая часть кода может быть выполнена непосредственно из флэш-памяти (XIP), без необходимости загрузки его в IRAM. Как правило, сюда попадает код, который выполняется в контексте прерывания или непосредственно обращается к флэш-памяти для чтения/ записи.
- Flash Code: это размер секции кода ( .text ), которая размещается во флэш-памяти и выполняется непосредственно оттуда. Большая часть вашего раздела кода окажется именно в этом столбце.
- Flash rodata: здесь показаны данные, предназначенные только для чтения и используемые прошивкой (строки, статически инициализированные и неизменяемые массивы). Поскольку доступ к флэш-памяти возможен во время выполнения программы, нет необходимости загружать секцию в память.
- Total: общий используемый объем памяти для этого компонента.
Конечно, особое внимание нужно уделить размерам разделов IRAM и DRAM, так как именно объем SRAM является ограничивающим фактором (512 КБ) относительно флэш-памяти (порядка 2–8 МБ).
Поиск проблемной сущности
Допустим, вы узнали, что один из используемых вами компонентов потребляет гораздо больше памяти, чем должен. Вы можете изучить проблему глубже, чтобы определить, какая сущность в этом компоненте больше всего влияет на объем используемой памяти. Это можно сделать, используя цель size-symbols для системы сборки. Например:
$ make IDF_PATH=~/work/idf size-symbols COMPONENT=soc
Total sizes:
DRAM .data size: 14200 bytes
DRAM .bss size: 23224 bytes
Used static DRAM: 37424 bytes ( 143312 available, 20.7% used)
Used static IRAM: 62344 bytes ( 68728 available, 47.6% used)
Flash code: 368546 bytes
Flash rodata: 65916 bytes
Total image size:~ 511006 bytes (.bin may be padded larger)
Symbols within the archive: libsoc.a (Not all symbols may be reported)
Symbols from section: .dram0.data
str1.4(605) __func__$3446(23) __func__$3425(21) rtc_clk_cpu_freq_value(20)
Section total: 669
Symbols from section: .dram0.bss
s_cur_pll(4) s_cur_freq(4)
Section total: 8
Symbols from section: .iram0.text
rtc_init(1020) rtc_clk_cpu_freq_set(472) rtc_clk_bbpll_set(380) rtc_clk_cal_internal(369) .iram1(282) rtc_clk_cpu_freq_get(172) rtc_clk_32k_bootstrap(170) rtc_clk_32k_enable_internal(149) rtc_clk_wait_for_slow_cycle(129) rtc_time_get(96) rtc_clk_cpu_freq_value(96) rtc_clk_cal(78) rtc_clk_xtal_freq_get(68) rtc_clk_slow_freq_get_hz(51) rtc_clk_apb_freq_get(50) rtc_clk_32k_enable(49) rtc_clk_fast_freq_set(46) rtc_clk_slow_freq_set(43) clk_val_is_valid(32) .iram1.literal(28) rtc_clk_apb_freq_update(23) rtc_clk_slow_freq_get(16) clk_val_to_reg_val(14) reg_val_to_clk_val(8)
Section total: 3841
Symbols from section: .iram0.vectors
Section total: 0
Symbols from section: .flash.text
Section total: 0
Symbols from section: .flash.rodata
soc_memory_regions(704) soc_memory_types(320) str1.4(159) soc_reserved_regions(48) soc_reserved_region_count(4) soc_memory_region_count(4)
Section total: 1239
Для получения дополнительной информации по использованию памяти различными сущностями компонента в командной строке make был использован дополнительный параметр COMPONENT = <имя_компонента>. Например, в приведенном выше примере была запрошена информация для компонента «soc».
В результатах вывода команды виден вклад каждой сущности (функции, переменной или объекта) этого компонента в общий размер прошивки. Обратите внимание, что размер каждой функции виден в секции .iram0.text, а, например, массивы soc_memory_types и soc_memory_regions (определенные в soc_memory_layout.c как «const»), помещены во флэш-память, поскольку они предназначены только для чтения.
Результат работы команды может быть эффективно использован для точного определения того, какие части ваших компонентов вносят заметный вклад в использование оперативной памяти контроллера, что позволит вам сосредоточиться на эффективной оптимизации именно этих компонентов.
Дополнительные материалы:
- Среда для разработки IoT приложений на основе SoC ESP32
- Программные средства ESP-ADF для разработки аудиоприложений
- Программные средства ESP-MDF для разработки Mesh-сетей
Источник: https://medium.com
Производители: ESPRES
Разделы: Приемо-передатчики
Опубликовано: 25.10.2019