ESP8266: Что я могу сделать, чтобы раздел «.text» не помещался в область «iram1_0_seg»?

Каковы общие меры против области .text, не вписывающейся в «iram1_0_seg» при связывании для ESP8266 с использованием цепочки инструментов на основе xtensa GCC?

Я предполагаю, что оперативной памяти ESP8266 недостаточно для выполнения определенных функций. Однако что я могу сделать, чтобы перенести как можно больше функций во флэш-память?

Вот пример того, что возвращает компоновщик:

/home/user/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-gcc  -I/home/user/git/esp-open-sdk/sdk/include -I/home/user/git/esp-open-sdk/sdk/include/json -I/home/user/git/mart3/src/RTMain/ESP8266TargetGroup -Os -D__ESP8266__ -std=c99 -pedantic -Wall -Wpointer-arith -pipe -Wno-unused-parameter -Wno-unused-variable -Os -g -O2 -Wpointer-arith -Wundef -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH -ffunction-sections -fdata-sections  -L/home/user/.arduino15/packages/esp8266/hardware/esp8266/2.0.0/tools/sdk/lib -L/home/user/.arduino15/packages/esp8266/hardware/esp8266/2.0.0/tools/sdk/ld -Teagle.flash.512k0.ld -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--gc-sections src/code/CMakeFiles/FX6CodeObj.dir/FX6Generated/src-gen/fxfu___program1.c.obj src/code/CMakeFiles/FX6CodeObj.dir/FX6Generated/src/emptyHello/fxfu___helloart.c.obj src/code/CMakeFiles/FX6CodeObj.dir/FXStd/FXRTMain.c.obj src/code/CMakeFiles/FX6CodeObj.dir/FXStd/NamedList.c.obj  -o src/ARTApp/ARTApp.out  -Wl,--start-group src/ART/libART.a -lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig -lwps -lcrypto -laxtls -Wl,--end-group
/home/user/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: src/ARTApp/ARTApp.out section `.text' will not fit in region `iram1_0_seg'
collect2: error: ld returned 1 exit status

person dubbaluga    schedule 28.12.2015    source источник
comment
Возможно, это слишком специфично для Arduino, и вы могли бы получить более подробные ответы на arduino.stackexchange.com?   -  person Marged    schedule 29.12.2015
comment
Возможно, .arduino15 в пути набора инструментов немного вводит в заблуждение. Я использую набор инструментов, но не платформу Arduino. Однако я был бы не против, если бы вы перенесли этот вопрос на другой сайт.   -  person dubbaluga    schedule 29.12.2015
comment
Возможно, какая-то библиотека сильно использует память.   -  person Mert Gülsoy    schedule 05.01.2016


Ответы (2)


Я не знаю об Arduino, но если бы вы программировали, используя библиотеки Espressif, найденные здесь https://github.com/esp8266/esp8266-wiki/raw/master/sdk/, тогда у них есть много макросов для таких вещей.

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

void ICACHE_FLASH_ATTR user_init(){

Если вы проследите команду ICACHE..., вы найдете это определение

#define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text")))

Если вы затем посмотрите, как эспрессиф настраивает разделы памяти https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map .irom0.text помечен как флэш-память. В основном все, что связано с командой ICACHE..., загружается во флэш-память, а без нее - нет.

Опять же, не знаю, как перевести это в код Arduino, но, возможно, пришло время отказаться от библиотек Arduino, если вам не хватает места во флэш-памяти. Вы не указали, какой прорыв ESP вы используете, и мой разум может обманывать меня, но я считаю, что ESP12-e использует более новый чип, который имеет больше флэш-памяти, чем, скажем, ESP01, просто еще один вариант.

person arduic    schedule 30.12.2015

Немного поздно отвечать на вопрос, но я подумал, что другим может быть интересно возможное решение. Это то, что я сделал, чтобы выяснить ошибку переполнения iram1_0_seg в прошивке на основе ESP8266 nonos sdk. Чтобы узнать, какие функции на самом деле размещены в секции iram1_0_seg, выполните следующую команду:

$ xtensa-lx106-elf-nm -av yourprogram.elf | uniq -u | grep "^4010*"

'yourprogram.elf', конечно же, нужно заменить на имя файла elf вашей прошивки. Все функции iram1_0_seg находятся в диапазоне адресов 4010xxxx, отсюда и grep 4010. Очевидно, что эта команда может быть выполнена только после того, как elf сгенерирован. Если файл elf не может быть сгенерирован из-за ошибки переполнения iram1_0_seg, то необходимо удалить некоторый код. Или откатитесь к версии вашего кода, которая все еще подходила и не имела ошибки переполнения iram1_0_seg.

Вывод приведенной выше команды nm будет заканчиваться такой строкой:

$ 4010680c A _text_end

iram1_0_seg ограничен 0x8000 байтами на ESP8266. В приведенном выше примере у меня выделено «0x680c» байт, и поэтому места достаточно. Команда nm выведет список всех функций, выделенных в сегменте iram1_0_seg. Пожалуйста, посмотрите, какие из функций, возможно, не нужно размещать в оперативной памяти. Большинству функций может не хватать FLASH, но если вы не пометите их ICACHE_FLASH_ATTR, то функции окажутся в ОЗУ (и израсходуют 0x8000 байт).

Если вы видите функции, которые должны быть во FLASH (но их нет), которые на самом деле взяты из стандартных библиотек libc.a или libgcc.a, у вас есть хорошие шансы освободить место в сегменте iram1_0_seg. Возьмем пример memcpy, который уже есть в rom и вообще не нужен ни в одной библиотеке. Причина, по которой он все равно извлекается из libc.a, заключается в том, что библиотеки имеют приоритет над операторами PROVIDE в сценарии компоновщика. Взгляните на свой файл eagle.rom.addr.v6.ld (в папке /esp-open-sdk/sdk/ld). Там вы видите оператор PROVIDE(memcpy=..).

Это говорит вам, что memcpy доступен в ПЗУ. Итак, как использовать функцию ROM вместо версии libc.a? Самый простой способ — просто удалить memcpy из libc.a, чтобы компоновщик взял на себя функцию rom. Чтобы быть в безопасности, я предлагаю сделать копию libc.a перед этим, на случай, если что-то пойдет не так. Следующие команды необходимо выполнить в папке библиотеки (где находится libc.a), чтобы удалить memcpy:

$ cp libc.a libc2.a $ ar d libc2.a lib_a-memcpy.o

После того, как вы изменили свой Makefile, связав его с -lc2 вместо -lc, функция 'memcpy' будет взята из ПЗУ. Проверьте с помощью приведенной выше команды nm, чтобы убедиться, что она прошла успешно. memcpy больше не должен быть указан в списке 401. И, возможно, повторить с другими функциями libc.a (например, 'memcmp', 'strlen', 'strcpy', 'strcmp', ...). Вот как я уменьшил использование iram1_0_seg до 0x680c байт. Аналогичную процедуру можно проделать с функциями libgcc.a: __muldf3, __mulsf3, __umulsidi3, ...

person urutech    schedule 14.05.2020