ESP8266架构探索-运行的起始¶
更新日期: 2022-08-10
- 2022-08-10 更新
Cyber & Robot 授权发布
都2020年了,想必大家对ESP8266都很熟了,没用过至少也听说过。所以抛开丰富有趣的各种应用,下面来说一说很少人讨论的ESP8266的架构。
架构¶
ESP8266集成了增强版的超低功耗Tensilica’s Xtensa L106 32-bit内核处理器。为什么说增强版呢,因为Tensilica处理器的特点,就是工程师可以对内核IP做定制化,乐鑫购买IP后,继续进行优化,形成了增强版。
该处理器使用RISC指令集,CPU时钟速度最⾼可达160MHz,芯⽚内置了存储控制器,包含ROM和SRAM。但这个ROM呢,固化一些底层代码,用户是修改不了的,用户程序必须由外部Flash存储,理论上最大可支持16MB的存储。
所以这就是为什么买ESP8266模块时,都要看用的多大的Flash,使用SDK开发方式的话,从编译到下载都要选择正确的Flash。
代码和内存的存储分配¶
熟悉计算机原理的都知道,计算机的本质就是计算,通过执行不同的指令,操作不同的数据来得到不同的数据结果。
指令在代码中可以认为是不同的语句,数据就是不同的变量。在单片机中,一般指令存在ROM中,数据变量存在RAM中。有这两个概念后,再看看ESP8266这款芯片。
ESP8266片上有固化的ROM,需要用户外置Flash来存储程序。在物理上有 64KB 的 iRAM,96KB 的 dRAM。
其中:
- iRAM:instruction RAM,用来存放指令,位于 0x40100000 开始的 64KB 空间。
- dRAM:data RAM,用来存放数据,位于 0x3FFE8000 开始的空间。
所以ESP8266一共有这么几个存储的地方:片上ROM、片上iRAM、片上dRAM,片外Flash。
存储区 | 作用 |
---|---|
片上ROM | 固化芯片底层代码,用户无法改动 |
片上iRAM | 存放指令,用于执行程序 |
片上dRAM | 存放数据 |
片外Flash | 存放用户代码、用户数据等 |
知道iRAM后,就知道我们Flash的地位并不怎样。代码并不是直接在Flash上取指令运行的,而是加载到iRAM中来运行的。
代码开始的地方¶
ESP8266中所有代码都是加载到iRAM后运行的,只是有的提前加载(IRAM段),有的用时加载(IROM段)。IROM段使用部分称为Cache,IRAM段为真iRAM。
ESP8266有个特殊的Cache概念。在计算机系统中,Cache是为了解决CPU读内存速度过慢而设置的。
Cache比内存的读取速度更快,但比寄存器读取速度慢。通常Cache只是小空间存储,用来缓存CPU读取过的内存数据。
ESP8266中的Cache使用了iRAM,iRAM共有64k,分了一半(32k)给Cache。ESP8266的底层启动后,会将对应Flash的空间映射到Cache空间。
用户代码是存在外置Flash的,那么芯片启动后,IRAM段加载到iRAM中,底层代码(前面说的固化ROM内)也会将Flash空间映射到Cache中。
因为Cache的空间远小于Flash,所以使用了特殊的映射技术可以将最大1M+1M的Flash映射到32K的cache中。而哪些代码需要加载到iRAM,哪些还是放在Cache中运行,则是在链接时,通过指定不同的段来区分。
写过代码的朋友就知道了,在NONOS SDK中,需要ICACHE_FLASH_ATTR来定义函数,以使代码不占用iRAM空间。在RTOS SDK中,使用IRAM_ATTR定义函数,将需要频繁运行,讲究效率的函数放到iRAM中。这个便是iRAM和iROM的区别引起的。
好了,到了这里,我们就知道代码编译生成二进制文件,烧录到Flash后,是怎么由ESP8266执行起来的了。别走开,下面有彩蛋。
ROM的底层¶
ROM的底层是看不见的,但是既然我们能用到,那就有它的痕迹
https://github.com/espressif/ESP8266_NONOS_SDK/blob/master/ld/eagle.rom.addr.v6.ld
PROVIDE ( ets_memcmp = 0x400018d4 );
PROVIDE ( ets_memcpy = 0x400018b4 );
PROVIDE ( ets_memmove = 0x400018c4 );
PROVIDE ( ets_memset = 0x400018a4 );
PROVIDE ( ets_post = 0x40000e24 );
PROVIDE ( ets_printf = 0x400024cc );
PROVIDE ( ets_putc = 0x40002be8 );
PROVIDE ( ets_rtc_int_register = 0x40002a40 );
但NONOS SDK官方也已经停止更新了,在RTOS SDK中,底层函数作用也逐渐在淡化,像操作外设的都改成了在用户代码里编写的形式。
NONOS SDK默认链接到iROM中¶
不知道现在还有多少人在使用NONOS SDK做开发,既然这篇文章说到了代码存放,那就说一下吧。
在NONOS SDK中,用户代码编译链接后,会默认放到iRAM中,所以需要用户手动增加ICACHE_FLASH_ATTR来修饰。但问题是iRAM空间只有32k,是非常有限的。
如果都是自己从0开始写的代码,那也没什么。但是如果是要引用别人的库,或者是自己写的代码要封装成库给其他地方使用,这时就很麻烦了,因为其他平台都不用这样定义。那么有没有解决办法呢,有。
在SDK中找到./ld/eagle.app.v6.ld文件。
在.irom0.text : ALIGN(4)
段下做如下修改即可。
.irom0.text : ALIGN(4)
{
_irom0_text_start = ABSOLUTE(.);
*libuser.a:(.literal.* .text.*) /* 增加此行 */
*libat.a:(.literal.* .text.*)
*libcrypto.a:(.literal.* .text.*)
... ...
_irom0_text_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr
End¶
关于ESP8266架构和代码如何开始运行的东西就到这里了。
彩蛋之后,当然是下集预告啦。
下次可能会根据开源的 Bootloader代码,来跟着解析一遍哦。
阵容如下,有没有点期待呢?
- rboot:https://github.com/raburton/rboot
- zboot:https://github.com/zorxx/zboot
- esp-bootloader:https://github.com/tuanpmt/esp-bootloader
本文也发布在
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~