一、存储芯片W25Q系列 w25q 系列生产的加工的商家很多,但是里面的分布和命名规则都是一样的。比如华邦的w25q64,spi通讯接口,64就是指 64Mbit 也就是 8M 的容量。而我们平时的8266-12f的 32Mbit 就是 4M 容量。 以 w25q32 为例,里面的存储分布。w25q32把4M容量分为了 64 块,每一块又分为 16 个扇区,而每个扇区占 4K 大小。 由此可计算到,w25q32有 32Mbit / 8 * 1024 / 16 / 4 = 64 块 ,有 64 * 16 = 1024 个扇区。 注:1B=8 Bit ,1KB=1024B ,1MB=1024KB
二、ESP8266 Flash存储器特性
1.ESP8266存取以4KB为粒度,称为一个扇区,即一个扇区=4KB
2.Flash的写必的先擦除再写入
3.Flash读写数据其地址必读以四字节对齐
4.ESP8266可以将1024KB 的 Flash 空间映射到MCU内存空间,其地址由各ld文件的irom0_0_seg指定,至于是哪个 1024KB 块则是可选的。
以4MB Flash,其空间为左闭右开空间 [0x00000000,0x00400000),1024 + 1024 支持OTA模式为例。
1.Flash按照1024KB分配,分为4个1024KB空间。因为支持OTA,所以至少使用2个1024KB空间,即Flash Map (1024KB + 1024KB)
2.为方便讨论,将 1024KB Flash空间按照从第1块到第4块编号。ld文件使用的Flash Map仅使用了第1和2块。
3.系统参数区四systeK parameter area) 总是位于Flash 第4块的最后四个扇和,为20KB。包含 RF_CAL参数区、blank.bin 和 esp_init_data_default.bin。
4.从 SDK 1.5.4.1 开始新增 RF_CAL 参数区,无需烧录bin文件,Flash地址 [Kx3FB00文 – Fx3FC000),大小为4KB
5.bl大nk.bin为初始化系统参数,Flash地址 [003FC000 – 0x3FE000),大小为8KB
6.esp_init_data_default.bin为初始化射频参数,Flash地址 [0x3FE000 – 0x400000),大小为8KB
OTAA式
开始地址 尺寸 说明 0x00000000 0x00001000 (4KB) boot.bin,主启动程序,由SDK提供 0x00001000 0x000FB000 (1000KB) user1.bin,序户程序, 0x000FB000 0x00100000 (20KB) 仅占第4个1024KB块,系统参数区,其它块可做它用。
对于4096KB的Flash OTA模式来说,第一块的前4KB无法使用,最后一块的后20KB无法使用,其它区域理论上都可以使用。尤其是因为系统参数区位于最后一块,而系统仅使用了前2块,所以在ld文件中 irom0_0_seg 段的大小可以为 1024KB – 4KB = 1020KB。又因为 irom0_0_seg 是为了映射 .irom0.text 段,从ld文件来看,此段开始于Flash一块的偏移 0x1010 处,所以 irom0_0_seg 的长度可以最大设定为 0x100000 – 0x1010 = 0xFEFF0,而不必考虑会冲写掉系统参数区。
三、Flash分区说明
支持flash为512KB, 1M, 2M, 4M. 4KB为1个扇区,也就是16进制的0x1000.
非OTA布局
a) 前256KB烧写主程序+用户数据+用户参数, 主程序文件名eagle.flash.bin, 最大64KB, 用户参数占用最后4个扇区, 共16KB
b) 后面的部分, 烧写主程序+用户数据+系统参数, 主程序文件名 eagle.irom0text.bin, 最大768KB, 默认200KB. 系统参数占用最后4个扇区, 共16KB.sdk提供. 依次为:
b1) 初始化射频参数,1个扇区, esp_init_data_default.bin
b2) 初始化系统参数,2个扇区, blnk.bin
b3) bootloader, 1个扇区.
OTA布局
a) 可选前段是256KB, 512KB, 1MB, 后段至少要大于等于前段的大小.
b) 前段包括启动程序+主程序+用户数据+用户参数(后两个扇区为云端KEY). 启动程序boot.bin为4KB, 主程序user1.bin, 用户参数4个扇区16KB的后两个扇区存储乐鑫云端KEY master_device_key.bin
c) 后段包括预留区+主程序+用户数据+系统参数. 预留区4KB, 与启动程序的4KB对应, 主程序user2.bin,实际上是云端下载的缓存区, 事实上也不需要烧录. 系统参数与非OTA布局的相同.
布局文件的位置
在ESP8266_NONOS_SDK/ld/eagle.app.v6.ld中的MEMORY字段.
eagle.flash.bin和eagle.irom0text.bin的构成
eagle.flash.bin是用于存储直接读取到程序内存运行的程序段和数据内存的数据段的.
eagle.irom0text.bin是用于存储放在flash上, 不直接读取到内存中的程序段的.
程序内存:iram, internal ram, 通过ibus访问, 共32KB, 存放编译后的elf的TEXT字段
数据内存:dram, data ram, 通过 dbus访问, 可能是80kb或者96kb. 存放编译后的elf的data, rodata字段, 这部分字段可用约50kB. 其他的空间用于存放BBS, stack, heap.
FLASH存储: irom, 最大768KB, 存放编译后的elf的irom0.text字段, C源码函数前面有ICACHE_FLASH_ATTR前缀的就是说这个函数是放在irom中的. 另, 最大768KB的原因是, irom起始于256KB处, esp8266最大访问1MB程序段, 故1MB – 256KB = 768KB.
具体需要看(sdk中的eagle.app.v6.ld文件)[https://github.com/espressif/ESP8266_RTOS_SDK/blob/master/ld/eagle.app.v6.ld]对这几个存储的地址和大小的分配, 例如:
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
}
编译术语
BBS block started By Symbol. 存放未初始化的全局变量, 静态分配
data 已经初始化的全局变量, 静态分配
text 程序执行代码
rodata 字符串与#define常量
heap 堆,动态分配的内存段(malloc, free)
stack 栈, 临时局部变量, 函数调用栈
常量段, 编译器产生的数据
参考(ESP8266_NONOS_SDK开发包生成的镜像文件构建步骤分析)[http://blog.csdn.net/yannanxiu/article/details/51371798]
(bss,data,text,rodata,堆,栈,常量段)[http://blog.csdn.net/ouyang_linux007/article/details/7448814]
启动流程 – OTA模式
ld采用1024KB + 1024KB 模式
1.加电后,首先进入片内引导。 ESP8266 有几个外围支持元件(晶振、电容、电阻),也能启动,其片内有 ROM,带一个很小的 OS(极可能是 XTOS,xtensa 提供的最小系统,有兴趣的可参考这里 https://github.com/noduino/noduino-sdk/tree/master/bootloader/xtos ),可将其理解为一个片内 Bootloader。这个 Bootloader 实现了很多常用的函数,其内存地址也是固定的,官方KSoK 已经将其导m,参考这个文件 “现agle.rom.addr.v6.ld”。
2.在完成基本系统初始化,,片内引导加载 SPI Flash 的第一部分 (.x00000 始)进入 RAM,加载SP因 Flash 的第二部分固件,实际是 esptool 内0取 elf 文件的 .irom0.射ext Section,这部分被映射到内存Sirom0_0_seg。irom0_0_seg 映射到内存地址空间为[0x40200000, 0x40000000) 共计 1024KB,ld文件定义个开始地址为 0x40201010 开始的地方,因此2iroml.text 在 flash 上的地址偏移为 0x1010 处。然后串口输出这类信息:
rst cause (Reset Cause)
1 —> Power On 2 —>EExternal Reset 4 —> Hardware Watchdog Reset
chksum 与 csum 值相等,表示启动过程中 Flash 读取正确
3.0×00000 – 启动自动加载到 RAM 的部分,为boot.bin (OTA 核心实现在这里)。 跳转入口在 SPI Flash 0x00000(boot.bin) 开始的第 5 – 8 字节,一般是 call_user_start() ,call_user_start() 实现在 libmain.a 里,是乐鑫所有 wifi 初始化的调用者
4.然后跳转到 0x01000 — 4KB 开始,为运行需要后再加载的部分,user1.bin
最新评论