[esp8266]官方SDK与arduino ROM或Flash布局,Vscode+platformio 如何设置
flash布局有哪些
- 乐鑫官方的SDK flash布局
- 在arduino开发上的FS(file spilt)布局
乐鑫官方储存结构(非OTA)
在esp8266上有一个spi总线的w25q32芯片(或者其他大小的),支持:512KB, 1M, 2M, 4M.
esp8266有内部储存器,但是以及用掉了,应该时烧录了乐鑫自己的板载程序,所以我们只能烧录程序在
外部的spi flash(如:w25q32)上。
对于RAM则是芯片内部有160K的RAM
一些词语解释
词语名 | 解释 |
---|---|
RMA | 160K,RAM = IRAM + DRAM |
DRAM | 起始:0x3FFE8000 96K,对于 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 的大小。 | |
IRAM | 起始:0x40100000 ,64K, instruct RAM,有时候会把它当作64K,有时候会32K,这里区分,IRAM=icache+iram |
iram | 起始:0x40100000 ,32K,被icache分去后的instruct RAM |
icache | 起始:0x40200000,32K,IRAM分出后的用作映射作用,ICACHE_FLASH_ATTR字段(section)会被加载到cache中。 |
动态内存结构
RAM
内部的RAM(160KB)被分为两部分:IRMA与DRAM,其中IRAM(64K),从其中抽取32K用作icache,其余32K任然作为iram,
icache 映射一部分falsh(wa25q32)上的内存到其中,以加速读取。
cahce映射
esp8266 支持多种 cache 映射机制,当前默认的使用的是 1MB + 1MB 的方式。
即将 spi flash 中的:
0x000000~0x0FFFFF 映射到 0x40200000~0x402FFFFF,
0x100000~0x1FFFFF 映射到 0x40200000~0x402FFFFF。
Flash结构
(图来自他人帖子,没找到原图,觉着画的很OK,随手用了,原帖主人介意来联系我删除)
falsh在bin线性上一共分布为(按flash从0x000000开始):
烧录bin档名 | flash地址 | 扇区号 | 默认长度(KB) | 最大长度(KB) | 区域说明 |
---|---|---|---|---|---|
eagle.flash.bin | 0x00000 | 0- | 64 | 64 | |
eagle.irom0text.bin | 0x10000 | 16-? | 200 | 768 | |
esp_init_data_default.bin | 0x3FE000 | 1020 | 4 | 4 | |
blank.bin | 0x3FE000 | 1022 | 4 | 4 |
falsh在逻辑上一共分布为(按flash从0x000000开始):
区域名 | flash地址 | 扇区号 | 长度(KB) | 区域说明 |
---|---|---|---|---|
系统程序 | 0x00000 | 0 | 64 | eagle.flash.bin |
系统程序 | 0x10000 | 16-? | 768 | eagle.irom0text.bin |
用户数据 | 0x? | ? | ? | ? |
系统自己校准后保存RF参数区域 | 0x3FB000 | 1019 | 1 | RF_CAL |
默认RF参数 | 0x3FC000 | 1020 | 1 | esp_init_data_default.bin |
balnk.bin | 0x3FD000 | 1021 | 1 | 图中被划去的 |
balnk.bin | 0x3FE000 | 1022 | 1 | 初始化系统参数区 |
以上与网上有些版本有些差异,但我感觉问题差异不大。
代码中的字段
MEMORY
{
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x18000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40220000, len = 0x5C000
}
参考链接
arduino储存结构
一些词语解释
词语名 | 解释 |
---|---|
RMA | 160K,RAM = IRAM + DRAM |
DRAM | 起始:0x3FFE8000 96K,对于 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 的大小。 | |
IRAM | 起始:0x40100000 ,64K, instruct RAM,有时候会把它当作64K,有时候会32K,这里区分,IRAM=icache+iram |
iram | 32K,被icache分去后的instruct RAM |
icache | 32K,IRAM分出后的用作映射作用,ICACHE_FLASH_ATTR字段(section)会被加载到cache中。 |
修改过程
- 首先了解上面的官方的SDK结构后,发现起始flash是可以修改的,然后通过arduino与官方SDK falsh布局解析发现实际上
的flash起始是被arduino重新配置过。 - 在此之前得了解arduino的falsh配置,flash(4M举例)被分为6区域:
区域 | 作用 | 内存起始 |
---|---|---|
sketch | 这块区域主要是OTA或者板载代码(就是用户程序) | 0x40200000(esp8266内存的映射) |
empty | 空白区域 | |
spifs | 文件系统区域 | |
eeprom | eeprom区域,可以使用arduino的EEPROM读写 | |
rfcal | 射频校准参数 | |
wifi | wifi配置参数,如密码等。 |
该文件配置位置在:C:\Users\PX_Lenovo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\tools\sdk\ld\eagle.flash.4m3m.ld(只是取其中一种配置方式说明,文件夹里有很多这样的配置文件)
-
那么用户视角是哪里修改,而真实的配置文件是哪个?
通过寻找发现实际上用户界面只需要勾选即可,而真正起作用的文件是:eagle.flash.4m1m.ld(取其中一个文件)。
-
发现其实arduino下的spifs实际上是文件系统而已,通过以上界面修改可以达到代码选择需要的***.ld文件,如:eagle.flash.4m3m.ld。
-
那么在VsCode+platformio上如何做到这样的修改。
-
起初发现之前在目录
C:\Users\PX_Lenovo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2
下发现很多*.py文件,猜想是否
由这些python代码来实现编译选择正确的,翻看了一些代码,确实由有相关操作,我想是否可以在python代码中加入打印,判断platformio调用这些代码
结果发现,加入代码,使用platformio编译无效。 -
我发现编译时会有一些打印,打印给了许多的网址,找到platformio手册 然后仔细在网站上
寻找了一些资料,发现**.ld文件其实就是ld(gnu 链接器),知道链接器的朋友肯定知道,其实platformio使用界面选择替代输入命令行。 -
那么我是否能在platformio中设置它选择文件
eagle.flash.4m3m.ld
,首先想到platformio.ini文件是配置环境变量文件,在网上找寻一番,还真有一点,
在该文件下加入board_build.ldscript = eagle.flash.4m3m.ld
就能实现加载该脚本。试图加入,发现无任何变化:
-
第二天,继续思考,看看能不能在vscode的终端手动添加ld命令,发现只有gcc.exe,没有ld命令。
-
注意到点击编译,终端会打印:
Executing task in folder SmallDesktopDisplay: C:\Users\PX_Lenovo\.platformio\penv\Scripts\platformio.exe run <
是否platformio插件就在这里,打开该文件,随意翻动一下,在C:\Users\PX_Lenovo\.platformio\platforms\espressif8266\boards
中发现很多json文件,那么
联想到platformio.ini中字段board = nodemcuv2
,自然而然在C:\Users\PX_Lenovo\.platformio\platforms\espressif8266\boards
打开该文件: -
赫然发现
"ldscript": "eagle.flash.4m1m.ld"
,这个应该就是寻找的文件,尝试修改该字段为:"ldscript": "eagle.flash.4m3m.ld"
,发现编译没有任何变化
,发现编译时会打印一些板子信息:
-
那么尝试修改这些信息,在nodemcuv2.json中
"name": "NodeMCU 1.0 (ESP-12E Module)"
修改为:"name": "NodeMCU 1.0 (ESP-12E Module, Hello!)"
,发现终端打印同样的信息,那么确定是该文件无疑,尝试再修改一些其他信息,打印发现也会变动。 -
突然注意到修改为
eagle.flash.4m3m.ld
其实是spi fs的大小修改了,实际上终端是不会打印出文件系统的任何信息的。那么到这里其实修改已经完成了。 -
那么实际上可能在paltformio.ini文件中加入
board_build.ldscript = eagle.flash.4m3m.ld
是生效的。
总结
在platformio中使用arduino开发esp8266,其修改板子配置只需要修改paltformio.ini:board_build.ldscript
,并且代码的区域只有sketch这块(我使用esp12s只有1044464Byte)。
其他
在开发过程中发现,80KB RAM(应该是DRAM)实际上用不了多少,我申请一个8KB的动态缓冲区已经是极限了,那么预测实际上可使用的50KB左右,大了就会无限重启
可能是某些函数会申请大内存吧,实际情况以后有需要再测试。
修改linker脚本
在platformio.ini加入:
board_build.ldscript = C:\Users\PX_Lenovo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\tools\sdk\ld\eagle.flash.4m3m.ld
文件位置:
arduino配置文件:C:\Users\PX_Lenovo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266
platformio:C:\Users\PX_Lenovo\.platformio\platforms\espressif8266\boards
参考链接
arduino与官方SDK falsh布局解析
官方arduino esp8266falsh 布局参考文档
脚本.ld使用方法