ESP8266:我能做些什么来克服"部分`.text'不适合地区`iram1_0_seg'"?

时间:2015-12-28 23:45:15

标签: linker linker-scripts esp8266

什么是.text区域的一般措施不适合" iram1_0_seg"使用基于xtensa GCC的工具链链接ESP8266时?

我猜ESP8266的RAM不足以容纳某些功能。但是,如何将尽可能多的功能移动到闪存中呢?

以下是链接器返回的示例:

/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

2 个答案:

答案 0 :(得分: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")))

如果你看看espressif如何设置内存部分https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map .irom0.text被标记为闪存。基本上任何带有ICACHE ...命令的东西都会加载到闪存中,而不是没有。

再次不确定如何将其转换为Arduino代码,但如果您的闪存空间不足,可能是时候离开Arduino库了。你没有指定你正在使用哪个ESP突破,我的想法可能在玩我的技巧,但我相信ESP12-e使用更新的芯片,有更多的闪存然后说ESP01,只是另一种选择。

答案 1 :(得分:1)

回答这个问题有点晚了,但我认为其他人可能对可能的解决方案感兴趣。这是我为弄清楚基于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

在ESP8266上,iram1_0_seg限制为0x8000字节。在上面的示例中,我分配了“ 0x680c”字节,因此有足够的空间。 nm命令将列出iram1_0_seg段中分配的所有功能。请查看哪些功能可能不需要在RAM中分配。大多数功能都可以用完FLASH,但是如果不使用ICACHE_FLASH_ATTR进行标记,则这些功能最终会出现在RAM中(并占用0x8000字节)。

如果您看到应该在闪存中(但不是)的功能实际上来自标准库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,以防万一出问题。为了删除memcpy,需要在库文件夹(libc.a所在的文件夹)中执行以下命令:

$ 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,...