arduino中定义sketch是从0x40200000-0x402FEFEF,而irom0_0_seg是从0x40201010-0x40300000。明明sketch是代码的意思为什么与irom0_0_seg会有偏差(0x1010B)?
IRAM原理结论(大写IRAM与iram区别在于:IRAM包含iram)
实际上flash中的0x1010-0x100000
位置是irom0位置,ubuntu下使用readelf -S ./test/firmware.elf
(firmware.elf是编译后的烧录文件)查看确实irom0是在40201010
也没找到小于该地址的数据。
接着我想,那么从0x40200000-0x40201010
或者flash物理地址0-0x1010
究竟有什么,使用16进制查看器,发现确实在firmware.bin
0-0x1010
存在数据。那么该部分数据是什么?
想要去使用objdump,发现无法识别,那么为什么*.bin
文件无法识别,我向看看elf是如何转换成bin文件的,在Vscode编译,发现无法看到编译命令,从网上了解到objcopy可以将代码转换为bin。尝试arm-none-eabi-objcopy.exe -O binary .pio\build\esp12e\firmware.elf ./boot.bin
还是无法识别文件。那找找该工程的编译器,在.vscode/launch.json
中发现:
"toolchainBinDir": "C:/Users/PX_Lenovo/.platformio/packages/toolchain-xtensa/bin"
好家伙,编译器不是gcc,看了下xtensa
这个是esp系列处理器的型号,那这个就简单了,将上面指示的工具链位置加入系统路径,重启vscode,在vs(实际是powershell执行的)的命令行中执行:xtensa-lx106-elf-objcopy.exe -O binary .pio\build\esp12e\firmware.elf ./app.bin
。结果发现app.bin
与firmware.bin
不一样。
试过很多办法,都没办法找到任何相关信息,可能其产生是因为编译器自动产生的,作为一个文件的头部或者索引表
。
现在想要知道该文件怎么过来的,先得知道是怎么样得命令产生了firmware.bin
文件,想着加多调试信息,所以在platformio.ini
加入:
build_flags =
.....
-DCORE_DEBUG_LEVEL=5
编译一次,发现打印了如下关键信息:
Creating BIN file ".pio\build\esp12e\firmware.bin" using "C:\Users\PX_Lenovo\.platformio\packages\framework-arduinoespressif8266\bootloaders\eboot\eboot.elf" and ".pio\build\esp12e\firmware.elf"
里面指出在firmware.bin=eboot.elf+firmware.elf
所产生得。
irom0在代码中的表现是:irom0_0_seg,.irom0.text。而它所处的falsh位置是0x0001010-0x300000这一段位置。在cpu内存映射是0x40201010-0x40300000。32K的iram(iram1_0_seg)会调入部分irom0的代码进入其中,而有32K的icache(irom0_0_seg)作为虚拟内存映射到irom0上,增加读取速度。
DRAM结论
除去.text与.irom0.text就只剩下:.bss,.rodata,data三个字段。根据官方:
DRAM 空间为 96 KB: 对于 Non-OS_SDK,前 80 KB 用来存放 .data/.bss/.rodata/heap,heap 区的大小取决于 .data/.bss/.rodata 的大小;还有 16 KB 给 ROM code 使用。 对于 RTOS_SDK,96 KB 用来存放 .data/.bss/.rodata/heap,heap 区的大小取决于 .data/.bss/.rodata 的大小。
也就是说内存剩余空间就是heap得了,这里不知道有没有stack。heap是动态大小,这样就会带来一些问题:某些空间比较申请全局变量,那么就是.data字段了或者.bss字段。这个会压缩heap大小,且编译器无法识别如下错误:
以80K为例,当全局申请了20K得变量,但是某个函数中申请了70K得buffer,这样会使得跑入该函数时导致数据错乱。
缓解RAM不足办法
优化ram
总之:尽量不要申请大得全局变量。
官方问题合集里面有RAM的结构讲解。
.bss.data.text.段讲解
readelf用法
arm-none-eabi-nm -n -t d -S --size-sort .pio\build\esp12e\firmware.elf
arm-none-eabi-objdump.exe -t .pio\build\esp12e\firmware.elf > objdump.txt
arm-none-eabi-objcopy.exe -O binary ./firmware.elf boot.bin
arm-none-eabi-objcopy.exe -O binary .pio\build\esp12e\firmware.elf ./boot.bin
xtensa-lx106-elf-objcopy.exe -O binary .pio\build\esp12e\firmware.elf ./app.bin
xtensa-lx106-elf-objdump.exe -t .pio\build\esp12e\firmware.elf > objdump.txt
xtensa-lx106-elf-objdump.exe -t .pio\build\esp12e\firmware.bin > bin.txt
xtensa-lx106-elf-objdump.exe -h -b binary -m arm boot.bin
xtensa-lx106-elf-readelf.exe -h .pio\build\esp12e\firmware.elf > elfinfo.txt