ESP8266架構探索-運行的起始

都2020年了,想必你們對ESP8266都很熟了,沒用過至少也據說過。因此拋開豐富有趣的各類應用,下面來講一說不多人討論的ESP8266的架構。git

架構

ESP8266集成了加強版的超低功耗Tensilica’s Xtensa L106 32-bit內核處理器。爲何說加強版呢,由於Tensilica處理器的特色,就是工程師能夠對內核IP作定製化,樂鑫購買IP後,繼續進行優化,造成了加強版。
該處理器使用RISC指令集,CPU時鐘速度最⾼可達160MHz,芯⽚內置了存儲控制器,包含ROM和SRAM。但這個ROM呢,固化一些底層代碼,用戶是修改不了的,用戶程序必須由外部Flash存儲,理論上最大可支持16MB的存儲。因此這就是爲何買ESP8266模塊時,都要看用的多大的Flash,使用SDK開發方式的話,從編譯到下載都要選擇正確的Flash。github

代碼和內存的存儲分配

熟悉計算機原理的都知道,計算機的本質就是計算,經過執行不一樣的指令,操做不一樣的數據來獲得不一樣的數據結果。指令在代碼中能夠認爲是不一樣的語句,數據就是不一樣的變量。在單片機中,通常指令存在ROM中,數據變量存在RAM中。有這兩個概念後,再看看ESP8266這款芯片。
ESP8266片上有固化的ROM,須要用戶外置Flash來存儲程序。在物理上有 64KB 的 iRAM,96KB 的 dRAM。
其中:npm

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執行起來的了。別走開,下面有彩蛋。app

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 );

這份ld文件裏,就描述了底層函數在ROM中的地址,也告訴咱們,到底提供了多少功能。
但NONOS SDK官方也已經中止更新了,在RTOS SDK中,底層函數做用也逐漸在淡化,像操做外設的都改爲了在用戶代碼裏編寫的形式。post

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

用戶代碼編譯後,會生成libuser.a文件,因此這個文件裏都是用戶代碼。新增語句就是將用戶代碼中類常量和代碼指令都放到iROM中。code

End

關於ESP8266架構和代碼如何開始運行的東西就到這裏了。彩蛋以後,固然是下集預告啦。下次可能會根據開源的 Bootloader代碼,來跟着解析一遍哦。
陣容以下,有沒有點期待呢。

rboot: https://github.com/raburton/rboot
zboot: https://github.com/zorxx/zboot
esp-bootloader: https://github.com/tuanpmt/esp-bootloader
相關文章
相關標籤/搜索