ESP8266:我能做些啥来克服“部分 `.text' 将不适合区域 `iram1_0_seg'”?
Posted
技术标签:
【中文标题】ESP8266:我能做些啥来克服“部分 `.text\' 将不适合区域 `iram1_0_seg\'”?【英文标题】:ESP8266: What can I do to overcome "section `.text' will not fit in region `iram1_0_seg'"?ESP8266:我能做些什么来克服“部分 `.text' 将不适合区域 `iram1_0_seg'”? 【发布时间】:2016-04-02 19:55:13 【问题描述】:使用基于 xtensa GCC 的工具链链接 ESP8266 时,针对 .text 区域不适合“iram1_0_seg”的一般措施是什么?
我猜想 ESP8266s 的 RAM 不足以容纳某些功能。但是,如何才能将尽可能多的功能移入 Flash?
这是链接器返回的示例:
/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
【问题讨论】:
也许这对 Arduino 来说太具体了,您可能会在 arduino.stackexchange.com 得到更好的答案? 也许工具链路径中的.arduino15
有点误导。我使用的是工具链,而不是 Arduino 框架。但是,如果您将此问题移至其他网站,我不介意。
可能某些库正在大量使用内存。
【参考方案1】:
我不了解 Arduino,但如果您要使用 https://github.com/esp8266/esp8266-wiki/raw/master/sdk/ 此处找到的 Espressif 库进行编程,那么他们有很多宏用于诸如此类的事情。
例如,ESP 的“main”使用以下行放入闪存中。
void ICACHE_FLASH_ATTR user_init()
如果你跟踪 ICACHE... 命令你会发现这个定义
#define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text")))
如果您随后查看 espressif 如何设置内存部分 https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map .irom0.text 被标记为闪存。基本上任何带有 ICACHE... 命令的东西都会被加载到闪存中,任何没有的东西都不是。
再次不确定如何将其转换为 Arduino 代码,但如果闪存空间不足,可能是时候离开 Arduino 库了。您没有具体说明您使用的是哪个 ESP 分线器,我的想法可能在捉弄我,但我相信 ESP12-e 使用的是更新的芯片,它比 ESP01 拥有更多的闪存,只是另一种选择。
【讨论】:
【参考方案2】:现在回答这个问题有点晚了,但我认为其他人可能对可能的解决方案感兴趣。这就是我为弄清楚基于 ESP8266 nonos sdk 的固件上的 iram1_0_seg 溢出错误所做的工作。 为了找出 iram1_0_seg 部分中实际分配了哪些函数,请运行以下命令:
$ xtensa-lx106-elf-nm -av yourprogram.elf | uniq -u | grep "^4010*"
“yourprogram.elf”当然需要替换为您的固件 elf 文件的名称。所有 iram1_0_seg 函数都在 4010xxxx 地址范围内,因此 grep 为 4010。显然,该命令只能在生成 elf 时执行。如果由于 iram1_0_seg 溢出错误导致无法生成 elf 文件,则需要删除一些代码。或者回滚到您的代码版本仍然合适并且没有 iram1_0_seg 溢出错误。
上述 nm 命令的输出将以如下一行结尾:
$ 4010680c A _text_end
iram1_0_seg 在 ESP8266 上被限制为 0x8000 字节。在上面的示例中,我分配了“0x680c”字节,因此有足够的空间。 nm 命令将列出 iram1_0_seg 段中分配的所有函数。请查看哪些功能可能不需要在 RAM 中分配。大多数函数可以用完 FLASH,但如果你不使用 ICACHE_FLASH_ATTR 标记它们,那么函数最终会进入 RAM(并用完 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 中可用。那么,如何使用 ROM 功能而不是 libc.a 版本呢?最简单的方法是简单地从 libc.a 中删除 memcpy,以便链接器获取 rom 函数。为了安全起见,我建议之前制作一个 libc.a 的副本,以防万一出现问题。需要在库文件夹(libc.a 所在的位置)中执行以下命令才能删除 memcpy:
$ cp libc.a libc2.a
$ ar d libc2.a lib_a-memcpy.o
在您将 Makefile 更改为使用 -lc2 而不是 -lc 链接后,“memcpy”功能将从 ROM 中获取。使用上面的 nm 命令检查是否成功。 memcpy 不应再列在 401 列表中。并且可能与其他 libc.a 函数重复(例如,'memcmp','strlen','strcpy','strcmp',...)。 这就是我将 iram1_0_seg 使用量降低到 0x680c 字节的方法。 类似的过程可以用 libgcc.a 函数完成:__muldf3, __mulsf3, __umulsidi3, ...
【讨论】:
【参考方案3】:您可以尝试通过在“工具”>“MMU”部分中选择另一个选项来更改内存分配方案。例如选择“16KB 缓存 + 48KB IRAM (IRAM)”而不是“32KB 缓存 + 32KB IRAM(平衡)”。
【讨论】:
以上是关于ESP8266:我能做些啥来克服“部分 `.text' 将不适合区域 `iram1_0_seg'”?的主要内容,如果未能解决你的问题,请参考以下文章
我的代码有点脏,我想不出改进它的方法,我能做些啥来获得更紧凑和更好的解决方案?