第三章 ESP32-S3基礎知識
在本章中,我們將深入探索ESP32-S3這款備受矚目的微控制器。我們將詳細闡述其定義、核心資源、功能應用,以及如何選擇適合您項目的ESP32-S3型號。通過本章的學習,您將全面了解ESP32-S3,為您的物聯網項目選擇合適的硬件平臺奠定堅實基礎。
本章分為如下幾個小節:
3.1 為什么選擇ESP32-S3
3.2初識ESP32-S3
3.3 ESP32-S3資源簡介
3.4 S3系列型號對比
3.5 ESP32-S3功能概述
3.6 ESP32-S3啟動例程
3.1 為什么選擇ESP32-S3
在研發之初,作者也對比過樂鑫官方推出的幾款MCU系列,經過它們各自的功能及應用場景來分析,最終作者選擇S系列的S3型號。
下面,作者比較一下樂鑫推出的芯片有哪些特點:
在上述表格中,我們可以看到樂鑫推出的各系列MCU在硬件方面存在一些差異。下面我將繼續分析這些差異及其對應用場景的影響。
1,在內核數量方面:S系列和ESP32系列支持單核和雙核處理器,而C系列和H系列僅支持單核處理器。這意味著S系列和ESP32系列在處理多任務和高強度計算方面具有更強的性能。對于需要高效能、多任務處理的應用場景,如復雜算法處理、大數據分析等,S系列和ESP32系列可能更合適。
2,在時鐘頻率方面,S系列和ESP32系列的時鐘頻率范圍為80~240MHz,而C系列和H系列的時鐘頻率分別為120MHz和96MHz。較高的時鐘頻率意味著更快的處理速度和更高的性能。對于需要高速處理的應用場景,如實時信號處理、高速數據采集等,S系列和ESP32系列可能更合適。
3,在引出編程IO方面,S系列和ESP32系列的引出編程IO數量較多,而C系列和H系列的引出編程IO數量較少。這表明S系列和ESP32系列在編程接口的多樣性和靈活性方面具有優勢。對于需要連接多種外設和傳感器的應用場景,S系列和ESP32系列可能更合適。
4,在神經網絡加速方面,只有S系列支持神經網絡加速功能。這意味著選擇S系列可以更好地滿足深度學習、圖像識別等應用場景的需求。對于需要加速神經網絡運算的應用場景,如智能家居控制、智能安防等,S系列可能更合適。
5,在通信協議方面,所有系列都支持2.4G Wi-Fi和藍牙(BLE),這意味著它們在無線通信方面具有良好的兼容性。
6,在存儲器方面,各系列MCU的SRAM和ROM大小有所不同。較大的存儲器可以提供更多的程序運行空間和數據存儲空間,以滿足更復雜的應用需求。對于需要處理大量數據和運行復雜程序的應用場景,如物聯網網關、智能儀表等,S系列和ESP32系列可能更合適。
綜上所述,樂鑫推出的各系列MCU在硬件方面各有特點,選擇哪個系列取決于具體的應用場景和需求。對于需要高性能、多核處理和神經網絡加速的應用場景,S系列可能是更好的選擇;而對于簡單的物聯網應用場景,C系列或H系列可能更合適。
正點原子選擇S系列的S3型號作為開發板的核心芯片,是為了讀者提供更好的學習資源和開發體驗,幫助讀者更好地掌握物聯網和嵌入式開發的相關技術。
另外,樂鑫科技還提供了一個在線選型工具(https://products.espressif.com/#/product-selector?language=zh),名為ESP Product Selector。它可以幫助用戶全面了解樂鑫產品與方案、提高產品選型和開發效率,如下圖所示。
上圖①顯示了篩選工具的選擇,左邊是產品選型,右邊是產品對比。上圖②表示產品選型的功能篩選,主要根據客戶的需求來選擇,例如工作溫度、單/雙核、是否具備天線等條件,來選擇自己心儀的芯片/模組或者開發板。上圖③表示功能篩選之后的結果選擇,例如芯片/模組或者滿足條件的開發板。最后,上圖④表示篩選的結果,如果篩選結果是芯片/模組,那么它就會顯示符合篩選的芯片型號或者模組。
3.2 初識ESP32-S3
ESP32-S3是一款由樂鑫公司開發的物聯網芯片,它具有一些非常獨特的功能和特點。下圖為芯片的功能框圖。
結合《esp32-s3_datasheet_cn.pdf》數據手冊和上圖的內容,簡單歸納5個內容。
1,架構和性能:ESP32-S3采用Xtensa? LX7 CPU,這是一個哈佛結構的雙核系統。它具有獨立的指令總線和數據總線,所有的內部存儲器、外部存儲器以及外設都分布在這兩條總線上。這種架構使得CPU可以同時讀取指令和數據,從而提高了處理速度。
2,存儲:ESP32-S3具有豐富的存儲空間。它內部有384 KB的內部ROM,512 KB的內部SRAM,以及8 KB的RTC快速存儲器和8 KB的RTC慢速存儲器。此外,它還支持最大1 GB的片外FLASH和最大1 GB的片外RAM。
3,外設:ESP32-S3具有許多外設,總計有45個模塊/外設。其中11個具有GDMA(Generic DMA)功能,可以用來進行數據塊的傳輸,減輕CPU的負擔,提高整體性能。
4,通信:ESP32-S3同時支持WIFI和藍牙功能,應用領域貫穿移動設備、可穿戴電子設備、智能家居等。在2.4GHz頻帶支持20MHz和40MHz頻寬。
5,向量指令:ESP32-S3增加了用于加速神經網絡計算和信號處理等工作的向量指令。這些向量指令可以大大提高芯片在AI方面的計算速度和效率。
ESP32-S3是一款功能強大、性能豐富的物聯網芯片,適用于各種物聯網應用場景。以上信息僅供參考,如需了解更多信息,請訪問樂鑫公司官網查詢相關資料。
3.3 ESP32-S3資源簡介
下面來看看ESP32-S3具體的內部資源,如下表所示。
由表可知,ESP32內部資源還是非常豐富的,本書將針對這些資源進行詳細的使用介紹,并提供豐富的例程,供大家參考學習,相信經過本書的學習,您會對ESP32-S3系列芯片有一個全面的了解和掌握。
關于ESP32-S3內部資源的詳細介紹,請大家參考“光盤àA 盤à7,硬件資料à2,芯片資料àesp32-s3_technical_reference_manual_cn.pdf”,該文檔即《ESP32-S3的技術手冊》,里面有 ESP32-S3詳細的資源說明和相關性能參數。
3.4 S3系列型號對比
樂鑫S3系列型號包括ESP32-S3、ESP32-S3R2、ESP32-S3R8和ESP32-S3FN8等。這些型號在硬件配置、功能和應用場景方面略有不同。不同型號的MCU都有不同的應用場景,下面我們來看一下這些型號的命名規則,如下圖所示。
從上圖可以看到,F表示內置FLASH;H/N表示FLASH溫度(H:高溫,N:常溫);x表示內置FLASH大小(MB);R表示內置PSRAM;x表示內置PSRAM大小(MB);V表示僅支持外部1.8v spi flash。為了讓讀者更清晰了解ESP32-S3命名規則,這里作者以ESP32-S3FH4R2這一款芯片為例,繪畫一副清晰的命名示意圖,如下圖所示。
根據上述兩張圖的分析,我們可以了解到樂鑫S3系列的命名規則和特點。除了S3系列的芯片之外,樂鑫還推出了S3系列的模組,它是S3系列芯片的簡易系統。
樂鑫S3系列模組是基于S3系列芯片的子系統,它已經設計好了外圍電路,簡化了開發過程,讓開發者可以更快速地使用S3系列芯片進行開發。通過使用S3系列模組,開發者可以更容易地實現特定功能,縮短開發周期,提高開發效率。
樂鑫推出了ESP32-S3-WROOM-1和ESP32-S3-WROOM-1U兩款通用型Wi-Fi+低功耗藍牙MCU模組,如下圖所示,它們搭載ESP32-S3系列芯片。除具有豐富的外設接口外,模組還擁有強大的神經網絡運算能力和信號處理能力,適用于AIoT領域的多種應用場景,例如喚醒詞檢測和語音命令識別、人臉檢測和識別、智能家居、智能家電、智能控制面板、智能揚聲器等。
從上圖可知,ESP32-S3-WROOM-1采用PCB板載天線,而ESP32-S3-WROOM-1U采用連接器連接外部天線。兩款模組均有多種芯片型號可供選擇,具體見下表所示:
根據上表,可以看出這兩款模組的主控芯片是ESP32-S3和ESP32-S3Rx,它們都屬于樂鑫的ESP32-S3系列芯片。之前作者已經詳細講解了ESP32-S3系列芯片的命令規則,可以得出這兩款通用模組都是外接Flash存儲器,并且內置有PSRAM(主控芯片ESP32-S3沒有內置PSRAM)。下面我們以ESP32-S3-WROOM-1-N16R8模組為例,來講解模組的命名規則,如下圖所示。
通過了解模組內置的主控芯片類型,開發者可以更好地理解該模組的功能和特點,并根據需要進行相應的開發和應用。正點原子ESP32-S3開發板是以ESP32-S3-WROOM-1-N16R8模組作為主控,它可以提供穩定的控制系統和高效的數據處理能力,同時引出的IO可以滿足各種應用需求。
3.5 ESP32-S3功能概述
3.5.1 系統和存儲
ESP32-S3采用哈佛結構Xtensa? LX7 CPU構成雙核系統。所有的內部存儲器、外部存儲器以及外設都分布在CPU 的總線上。
以下是ESP32-S3的主要特性:
1,地址空間:ESP32-S3 擁有豐富的地址空間,包括內部存儲器指令地址空間、內部存儲器數據地址空間、外設地址空間、外部存儲器指令虛地址空間、外部存儲器數據虛地址空間、內部DMA地址空間和外部DMA地址空間。這些地址空間為芯片的各個部分提供了獨立的存儲空間。
2,內部存儲器:ESP32-S3內部存儲器包括384 KB的內部ROM、512 KB的內部SRAM、8 KB的RTC快速存儲器和 8 KB 的 RTC 慢速存儲器。這些存儲器為芯片提供了存儲和讀取數據的能力。
3,外部存儲器:ESP32-S3支持最大1 GB的片外flash和最大1 GB 的片外 RAM。這些外部存儲器可以用來存儲大量的程序代碼和數據,以滿足復雜應用的需求。
4,外設空間:ESP32-S3總計有45個模塊/外設,這些外設為芯片提供了豐富的輸入輸出接口和特殊功能。
5,GDMA(Generic DMA):ESP32-S3具有11個具有GDMA功能的模塊/外設,這些 GDMA 外設可以用來進行數據塊的傳輸,從而減輕CPU的負擔,提高整體性能。
下圖是ESP32-S3地址空間映射結構圖,闡述了內部存儲器地址空間映射、外部存儲器地址空間映射和模塊/外設地址映射的系統結構圖,以及GDMA與各部分的聯系示意圖。
上圖中,灰色背景的地址空間不可用,紅色五角星表示對應存儲器和外設可以被協調器訪問。由于ESP32-S3系統是由兩個哈佛結構Xtensa? LX7 CPU構成,這兩個CPU能夠訪問的地址空間范圍是完全一致的。上圖中,地址0x40000000以下部分屬于數據總線的地址范圍;地址0x40000000~4FFFFFFF部分位指令總線的地址范圍,其他是數據總線與指令總線的地址范圍,即內部存儲器、外部存儲器和外設等映射的內存地址。
CPU的數據總線與指令總線都為小端序(將多字節數據的低位放在較小的地址處,高位放在較大的地址處)。CPU可以通過數據總線進行單字節、雙字節、4字節、16字節的數據訪問。CPU也可以通過指令總線進行數據訪問,但必須是4字節對齊方式;非對齊數據訪問會導致CPU工作異常。CPU的工作如下:
①? ? 通過數據總線與指令總線直接訪問內部存儲器。
②? ? 通過Cache直接訪問映射到地址空間的外部存儲器。
③? ? 通過數據總線直接訪問模塊/外設。
系統中部分內部存儲器與部分外部存儲器既可以被數據總線訪問也可以被指令總線訪問,這種情況下,CPU可以通過多個地址訪問到同一目標。
3.5.1.1 內部存儲器
圖3.5.1中的①、②、④和⑥部分組成ESP32-S3內部存儲器。
上圖①:Internal ROM(384KB)是只讀存儲器、不可編程,用來存放系統底層的固件(程序指令和一些只讀數據)。
上圖②:InternalSRAM(512 KB)是易失性存儲器,可以快速響應CPU的訪問請求,通常只需一個CPU時鐘周期。其中,SRAM的一部分可以被配置成外部存儲器訪問的緩存(Cache),但這種情況下無法被CPU訪問;另外,某些部分只可以被CPU的指令總線訪問;某些部分只可以被CPU的數據總線訪問;還有某些部分既可被CPU的指令總線訪問,也可被CPU的數據總線訪問。
上圖④和⑥:RTCMemory(16 KB)RTC 存儲器以靜態RAM(SRAM)方式實現,因此也是易失性存儲器。但是,在deep sleep模式下,存放在RTC存儲器中的數據不會丟失。其中, RTC FAST memory(8 KB)只可以被 CPU 訪問,不可以被協處理器訪問,通常用來存放一些在 Deep Sleep 模式下仍需保持的程序指令和數據。而RTC SLOW memory (8KB)既可以被CPU訪問,又可以被協處理器訪問,因此通常用來存放一些CPU和協處理器需要共享的程序指令和數據。
注意:所有的內部存儲器都接受權限管理。只有獲取到訪問內部存儲器的訪問權限,才可以執行正常的訪問操作,CPU訪問內部存儲器時才可以被響應。關于權限管理的更多信息,請參考《esp32-s3_technical_reference_manual_cn.pdf》章節 15 權限控制(PMS)。
3.5.1.2 外部存儲器
圖3.5.1中的⑦、⑧和⑨可見。CPU借助高速緩存(Cache)來訪問外部存儲器。 Cache 將根據內存管理單元(MMU)中的信息把 CPU指令總線或數據總線的地址變換為訪問片外flash與片外RAM的實地址。經過變換的實地址所組成的實地址空間最大支持1 GB 的片外flash與1 GB的片外RAM。前面我們討論知道,ESP32-S3采用雙核共享ICache 和DCache 結構,以便當CPU的指令總線和數據總線同時發起請求時,也可以迅速響應。當雙核同時訪問ICache時,系統會做以下判斷,如下圖所示。
當兩個核的指令總線同時訪問ICache/DCache時,由仲裁器決定誰先獲得訪問ICache/DCache的權限。當Cache缺失(處理器所要訪問的存儲塊不在高速緩存中的現象)時,Cache控制器會向外部存儲器發起請求,當ICache和DCache同時發起外部存儲器請求時,由仲裁器決定誰先獲得外部存儲器的使用權。
①:ICache的緩存大小可配置為16 KB或32KB,塊大小可以配置為16B或32B,當ICache緩存大小配置為32KB時禁用16B塊大小模式。
②:DCache的緩存大小可配置為32 KB或64 KB,塊大小可以配置為16B、32B 或64B,當DCache緩存大小配置為64 KB 時禁用16B 塊大小模式。
返回到圖4.5.1,外部存儲器通過高速緩存(Cache),ESP32-S3一次最多可以同時訪問32MB的指令總線地址空間和32MB的數據總線地址空間。32 MB的指令總線地址空間,通過指令緩存(ICache)以64 KB為單位映射到片外flash或片外RAM,支持 4 字節對齊的讀訪問或取指訪問,而32 MB的數據總線地址空間,是通過數據緩存(DCache)以64 KB為單位映射到片外RAM,支持單字節、雙字節、4字節、16字節的讀寫訪問。這部分地址空間也可以用作只讀數據空間,映射到片外 flash 或片外RAM。
下表列出了訪問外部存儲器時CPU的數據總線和指令總線與Cache的對應關系。
同樣,想要操作外部存儲器的讀寫,需獲取訪問權限,CPU訪問外部存儲器時才能被響應。關于權限管理的更多信息,請參考《esp32-s3_technical_reference_manual_cn.pdf》15權限控制(PMS)。
3.5.1.3 模塊/外設
圖3.5.1中的⑤就是模塊/外設地址空間地址,CPU就是通過該空間地址來訪問模塊/外設的。下表是模塊/外設地址空間的各段地址與其能訪問到的模塊/外設映射關系。
從上表可以得知,要操作外設的寄存器,首先需要知道該外設的首地址。然后,我們可以使用一些底層的編程語言,如C語言或匯編語言,來編寫程序以設置外設寄存器的值,從而控制外設的行為。例如,通過設置GPIO寄存器的值,我們可以控制某個LED燈的亮滅;同樣地,設置UART寄存器的值可以用來發送和接收數據。
與內部存儲器和外部存儲器訪問類似,CPU要想訪問某一個模塊/外設,需要先獲取該模塊/外設的訪問權限,否則訪問將不會被響應。關于權限管理的更多信息,請參考《esp32-s3_technical_reference_manual_cn.pdf》章節15權限控制(PMS)。
3.5.1.4 通用GDMA控制器
通用直接存儲訪問(GeneralDirect Memory Access, GDMA)用于在外設與存儲器之間以及存儲器與存儲器之間提供高速數據傳輸軟件可以在無需任何CPU操作的情況下通過GDMA快速搬移數據,從而降低了CPU的工作負載,提高了效率。ESP32-S3的GDMA控制器采用AHB總線架構,以字節為單位進行數據傳輸,支持軟件編程控制傳輸數據量,支持鏈表傳輸,同時支持訪問內部RAM時的INCR burst傳輸。其能夠訪問的最大內部RAM地址空間為480 KB,最大外部RAM地址空間為32 MB。該控制器包含5個接收通道和5個發送通道,每個通道都可以訪問內部和外部RAM,并且支持可配置的外設選擇。最后,GDMA控制器采用固定優先級及輪詢仲裁機制來管理通道間的傳輸。
正如前文所述,GDMA共有10個獨立的通道,其中包括5個接收通道和5個發送通道。這10個通道被支持GDMA功能的外設所共享,也就是說用戶可以將通道分配給任何支持GDMA功能的外設。這些外設包括SPI2、SPI3、UHCI0、I2S0、I2S1、LCD/CAM、AES、SHA、ADC和RMT等。根據圖3.3.1的③所示的連接關系再一次驗證了,這些外設都可以使用GDMA傳輸數據。此外,每個GDMA通道都具備訪問內部RAM或外部RAM的能力,這使得ESP32-S3在處理復雜的數據傳輸任務時具有顯著優勢。
下圖是GDMA功能模塊和GDMA通道示意圖。
從上圖可知,每一個外設都可以使用任意一條通道進行數據傳輸。然而,這些通道分為不同的類型。當使用GDMA接收數據時,可以選擇任意的RXn通道(n:0~4);相反,當使用GDMA發送數據時,則需要選擇任務的TXn通道(n:0~4)。這種通道的分類和選擇方式使得數據傳輸更加高效和靈活。
ESP32-S3中有11個外設/模塊可以和GDMA聯合工作,如下圖所示。其中的 11 根豎線依次對應這11個具有GDMA功能的外設/模塊,橫線表示GDMA的某一個通道(可以是任意一個通道),豎線與橫線的交點表示對應外設/模塊可以訪問GDMA的某一個通道。同一行上有多個交點則表示這幾個外設/模塊不可以同時開啟GDMA功能。
具有GDMA功能的模塊/外設通過GDMA可以訪問任何GDMA可以訪問到的存儲器。更多關于GDMA的信息,請參考《esp32-s3_technical_reference_manual_cn.pdf》章節 3 通用 DMA 控制器(GDMA)。
與前面小節一樣,當使用GDMA訪問任何存儲器時,都需要獲取對應的訪問權限,否則訪問將會失敗。
3.5.2 IO MUX和GPIO交換矩陣
ESP32-S3 芯片有45個物理通用輸入輸出管腳(GPIOPin)。每個管腳都可用作一個通用輸入輸出,或連接一個內部外設信號。利用GPIO交換矩陣、IO MUX(IO復用選擇器)和RTC IO MUX(RTC復用選擇器),可配置外設模塊的輸入信號來源于任何的GPIO管腳,并且外設模塊的輸出信號也可連接到任意GPIO管腳。這些模塊共同組成了芯片的輸入輸出控制。值得注意的是,這45個物理GPIO管腳的編號為0~21、26~48。這些管腳即可作為輸入有可作為輸出管腳。正如前文所述,正點原子選擇ESP32-S3-WROOM-1-N16R8模組作為主控,但由于該模組只有36個實際引腳的物理GPIO管腳。這是因為該模組的Flash和PSRAM使用了八線SPI即Octal SPI模式,這些模式共占用了12個GPIO管腳。而且,該模組還將IO35、IO36、IO37引出,所以最終的管腳數量為45-12+3,即36個GPIO管腳。
下圖是從《esp32-s3_datasheet_cn.pdf》數據手冊截取下來的,主要描述Flash和PSRAM使用八線SPI模式下的管腳。
需要注意的是,正點原子ESP32-S3開發板的原理圖并沒有使用IO35-IO37號管腳,所以不存在共用Falsh和PSRAM管腳。
下面我們來看一下這個模組的實物圖和引腳分布圖,如下圖所示。
從上圖可以得知,左邊的圖片是該模組的3D實物圖,而右邊的圖片是該模組的管腳分布圖。雖然這些管腳是無序的,但它們都可以被復用為其他功能(除個別功能外),例如SPI、串口、IIC等協議。這是ESP32相比其他MCU的優勢之一,它具有更多的可復用管腳,可以支持更多的外設和協議。
接下來,我們來看一下模組管腳默認復用管腳和管腳功能釋義,如下表所示。
上表是ESP32-S3-WROOM-1-N16R8模組的管腳定義,下面作者根據這個表格來講解GPIO交互矩陣及IO MUX復用的知識。
下圖為GPIO交換矩陣、IO MUX和RTC IO MUX將信號引入外設和引出至管腳的具體過程。
首先,作者說明一下上圖帶有顏色線條和標簽(Ⅰ、Ⅱ、Ⅲ、Ⅳ)的作用,紅色線條表示輸出方向;紫色線條代表RTC IO管腳的輸出方向;黃色線條代表RTCIO管腳輸入方向;標簽代表輸入/輸出分支的節點。
從上圖可知,ESP32-S3管腳具有預設功能,即每個IO管腳直接連接至一組特定的片上外設。在運動時,可通過IO MUX和IO矩陣配置連接管腳外設。從上表4.5.2.1可知,有些IO管腳預設了RTC和模擬功能,有些IO管腳預設了SPI、IIC等功能。
上圖右邊兩個“Pin X supplied by VDD3P3_CPU/RTC”框圖為芯片焊盤 (PAD) 的內部結構,即芯片邏輯與GPIO管腳之間的電氣接口。ESP32-S3的45個GPIO管腳均采用此結構,如下圖所示。
上圖中的IE表示輸入使能;OE表示輸出使能;WPU表示內部弱上拉;WPD表示內部弱下拉,它們實現了芯片封裝內晶片與GPIO管腳之間的物理連接。
一、“Pin X supplied by VDD3P3_CPU”芯片焊盤輸入流程(圖4.5.1.5.3中的綠色線條)
從上圖3.5.2.3可知,輸入信號通過兩條通道(Ⅳ處)到達輸入信號終端。第一條通道(①)無需經過GPIO SYNC模塊的同步處理,而是通過IO_MUX_n_REGIO寄存器(該寄存器的IO_MUX_MCU_SEL位作用為信號選擇IO MUX功能,為0選擇Function 0,為1選擇Function 1(GPIO),Function功能請看《esp32-s3_technical_reference_manual_cn.pdf》章節6.12 IO MUX管腳功能列表)配置進入GPIO交換矩陣,然后輸入信號進入旁路GPIO交換矩陣(GPIO_SIMy_IN_SET)。另一方面,另一條通道經過GPIO SYNC模塊的同步處理,然后將信號時鐘同步APB總線時鐘,隨后進入GPIO交換矩陣。在這個交換矩陣中,通道的開通是由寄存器GPIO_FUNCy_IN_SEL_CFG_REG進行配置的。這個寄存器的描述如下。
從上圖可知,GPIO_FUNCy_IN_SEL(其中y為GPIO的管腳號)是外設輸入信號控制位。如果GPIO_FUNCy_IN_SEL的值為0x38,則輸入信號被視為高電平;如果GPIO_FUNCy_IN_SEL的值為0x3C,則輸入信號被視為低電平。GPIO_FUNCy_IN_INV_SEL(其中y為GPIO的管腳號)是反轉輸入值的控制位。如果輸入是高電平,經過反轉操作后變為低電平;否則,保持高電平。GPIO_SIMy_IN_SET(其中y為GPIO的管腳號)是旁路GPIO交換矩陣,它的作用是提高高頻數字信號的特性。如果GPIO_SIMy_IN_SET的值為1,則選擇GPIO交換矩陣作為輸入;否則,選擇IOMUX作為輸入,最終信號到達輸入信號終端。
二、“Pin X supplied by VDD3P3_CPU”芯片焊盤輸出流程(圖4.5.1.5.3中的紅色線條)
從上圖3.5.2.3可知,輸出信號也是分為兩個通道傳輸(Ⅰ處),如果輸出信號是普通的GPIO輸出,則該信號經過GPIO矩陣,再由該矩陣輸出到IO MUX,再到輸出管腳,這個流程由GPIO_FUNCy_OUT_SEL_CFG_REG寄存器配置,如下所示:
從上圖可知,GPIO_FUNCx_OUT_SEL(其中x為GPIO的管腳號)是外設輸出信號控制位。當GPIO0管腳輸出信號時,該值為0。GPIO_FUNCx_OUT _INV_SEL(其中x為GPIO的管腳號)是反轉輸出值的控制位。如果輸出是高電平,經過反轉操作后變為低電平;否則,保持高電平。然后通過IO_MUX_n_REGIO寄存器(該寄存器的IO_MUX_MCU_SEL位的作用是信號選擇IO MUX功能,為0選擇Function 0,為1選擇Function 1(GPIO)。有關Function的詳細信息,請參閱《esp32-s3_technical_reference_manual_cn.pdf》第6.12節中的IO MUX管腳功能列表)配置,信號最終到達輸出管腳。
另一條通道是復用功能輸出的通道。該通道由輸出信號的起始端到IO MUX復用電路,然后IO_MUX_n_REGIO寄存器的IO_MUX_MCU_SEL位不為1(GPIO模式),為復用功能,最后經過Ⅱ處輸出到輸出端(GPIO和RTC IO)。
三、“Pin X supplied by VDD3P3_RTC”芯片焊盤輸入流程(圖4.5.1.5.3中的黃色線條)
根據表3.5.2.1和圖3.5.2.3所示,ESP32-S3中有22個GPIO管腳具有低功耗(RTC)性能和模擬功能,由RTC子系統控制。這些功能不使用 IO MUX 和GPIO交換矩陣,而是使用RTC IO MUX將22個RTC輸入輸出信號引入RTC子系統。當這些管腳被配置為RTC GPIO管腳,作為輸出管腳時仍然能夠在芯片處于Deep-sleep模式下保持輸出電平值或者作為輸入管腳使用時可以將芯片從Deep-sleep中喚醒。
如果它們被用作普通輸入,則輸入流程與“Pin X supplied by VDD3P3_CPU”的輸入流程相同。如果它們作為RTC復用功能,則輸入信號會進入RTCIO MUX復用電路,并最終到達RTCGPIO矩陣。
3.5.3 復位與時鐘
3.5.3.1 ESP32-S3復位等級
ESP32-S3提供四種級別的復位方式,分別是CPU復位、內核復位、系統復位和芯片復位。除芯片復位外其它復位方式不影響片上內存存儲的數據。下圖展示了整個芯片系統的結構以及四種復位等級。
CPU復位:只復位CPUx內核,這里的CPUx代表CPU0和CPU1.復位釋放后,程序將從CPUxReset Vector開始執行。
內核復位:復位除了RTC以外的數字系統,包括CPU0、CPU1、外設、WiFi、Bluetooth? LE及數字GPIO。
系統復位:復位包括RTC在內的整個數字系統。
芯片復位:復位整個芯片。
上述任意復位源產生時,CPU0和CPU1均將立刻復位。復位釋放后,CPU0和CPU1可分別通過讀取寄存器RTC_CNTL_RESET_CAUSE_PROCPU和RTC_CNTL_RESET_CAUSE_APPCPU獲取復位源。這兩個寄存器記錄的復位源除了復位級別為CPU復位的復位源分別對應自身的CPUx以外,其余的復位源保持一致。下表列出了從上述兩個寄存器中可能讀出的復位源。
上表描述了不同的復位對應的復位源,在ESP32-S3上電復位時,它的復位源為芯片復位,如下信息所示:
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xb (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3810,len:0x17c0
load:0x403c9700,len:0xd7c
load:0x403cc700,len:0x300c
entry 0x403c992c
從上述內容可以看到,rst為0x01(復位編碼),根據上表的對應關系,可得芯片上電時的復位源為芯片復位。
3.5.3.2 系統時鐘
ESP32-S3的時鐘主要來源于振蕩器(oscillator,OSC)、 RC振蕩電路和PLL時鐘生成電路。上述時鐘源產生的時鐘經時鐘分頻器或時鐘選擇器等時鐘模塊的處理,使得大部分功能模塊可以根據不同功耗和性能需求來獲取及選擇對應頻率的工作時鐘。下圖為ESP32-S3系統時鐘結構。
從上圖可知,ESP32-S3時鐘頻率,可劃分為:
(1),高性能時鐘,主要為CPU和數字外設提供工作時鐘。
①:PLL_CLK:320MHz或者480MHz內部PLL時鐘
②:XTAL_CLK:40MHz外部晶振時鐘
(2),低功耗時鐘,主要為RTC模塊以及部分處于低功耗模式的外設提供工作時鐘。
? ?? ? ①:XTAL32K_CLK:32kHz外部晶振時鐘
? ?? ? ②:RC_FAST_CLK:內置快速RC振蕩器時鐘,頻率可調節(通常為17.5MHz)
③:RC_FAST_DIV_CLK:內置快速RC振蕩器分頻時鐘(RC_FAST_CLK/256)
④:RC_SLOW_CLK:內置慢速RC振蕩器,頻率可調節(通常為136 kHz)
從上圖紅色線條所示,CPU_CLK代表CPU的主時鐘。在CPU最高效的工作模式下,主頻可以達到240MHz。主頻頻率是由寄存器SYSTEM_SOC_CLK_SEL(SEL_0:選擇SOC時鐘源)、SYSTEM_PLL_FREQ_SEL(SEL_2:選擇 PLL 時鐘頻率)和SYSTEM_CPUPERIOD_SEL(SEL_3:選擇 CPU 時鐘頻率)共同確定的,具體如下表所示。
從上表可以得知,如果用戶想要將ESP32-S3的主頻設置為240MHz,那么我們應該選擇PLL_CLK作為輸入源,然后通過二分頻得到240MHz的時鐘頻率。
外設、WiFi、BLUE、RTC等時鐘配置及選擇源,請讀者參考《esp32-s3_technical_reference_manual_cn.pdf》技術手冊章節7 復位和時鐘。
3.5.4 芯片Boot控制
在上電復位、 RTC看門狗復位、欠壓復位、模擬超級看門狗(analog superwatchdog)復位、晶振時鐘毛刺檢測復位過程中,硬件將采樣 Strapping 管腳電平存儲到鎖存器中,并一直保持到芯片掉電或關閉。GPIO0、GPIO3、GPIO45和GPIO46鎖存的狀態可以通過軟件從寄存器GPIO_STRAPPING中讀取。GPIO0、GPIO45和GPIO46默認連接內部上拉/下拉。如果這些管腳沒有外部連接或者連接的外部線路處于高阻抗狀態,內部弱上拉/下拉將決定這幾個管腳輸入電平的默認值,如下表所示。
GPIO0、GPIO45和GPIO46在芯片復位時連接芯片內部的弱上拉/下拉電阻。如果strapping管腳沒有外部連接或者連接的外部線路處于高阻抗狀態,這些電阻將決定strappin管腳的默認值。所有strapping管腳都有鎖存器。系統復位時,鎖存器采樣并存儲相應strapping管腳的值,一直保持到芯片掉電或關閉。鎖存器的狀態無法用其他方式更改。因此,strapping管腳的值在芯片工作時一直可讀取,并可在芯片復位后作為普通IO管腳使用。
①芯片啟動模式控制
復位釋放后,GPIO0和GPIO46共同決定啟動模式。詳見下表。
正常情況下,ESP32啟動模式為“SPI BOOT”,當我們按下開發板的BOOT按鍵時才能進入“Download Boot”模式啟動。
② VDD_SPI 電壓控制
ESP32-S3系列芯片所需的VDD_SPI電壓請參考《esp32-s3_datasheet_cn.pdf》數據手冊的1.2型號對比表格,如下圖所示。
這個表格下定義了每個芯片型號VDD_SPI電壓。由于正點原子ESP32S3開發板的模組選擇的是ESP32-S3-WROOM-1-N16R8,而它的主控芯片為ESP32R8,所以根據上圖的內容,我們會發現ESP32R8芯片的VDD_SPI電壓為3.3V。接著我們來看一下GPIO45號管腳的定義,如下圖所示。
從上圖可以看到,電壓有兩種控制方式,具體取決于EFUSE_VDD_SPI_FORCE的值。如果這個值為0,那么VDD_SPI電壓取決于GPIO45的電平值。如果GPIO45的電平值為0,VDD_SPI電壓為3.3V;否則為1.8V。相反,如果EFUSE_VDD_SPI_FORCE 為 1,VDD_SPI電壓取決于 eFuse(表示 flash 電壓調節器是否短接至VDD_RTC_IO)。如果eFuse為0,VDD_SPI電壓值為1.8V;否則為 3.3V。
③ ROM日記打印控制
系統啟動過程中, ROM代碼日志可打印至UART和USB串口/JTAG控制器。我們可通過配置寄存器和eFuse可分別關閉UART和USB串口/JTAG控制器的ROM代碼日志打印功能。詳細信息請參考《ESP32-S3技術參考手冊》 ->章節芯片Boot控制。
④ JTAG 信號源控制
在系統啟動早期階段,GPIO3可用于控制JTAG信號源。該管腳沒有內部上下拉電阻,strapping的值必須由不處于高阻抗狀態的外部電路控制。如圖所示,GPIO3與EFUSE_DIS_PAD_JTAG、EFUSE_DIS_USB_JTAG和EFUSE_STRAP_JTAG_SEL共同控制 JTAG 信號源。
注意:ESP32-S3系統中有一塊4-Kbit的eFuse,其中存儲著參數內容。相關內容請看《esp32-s3_technical_reference_manual_cn.pdf》技術參考手冊-> 章節 eFuse 控制器。
3.5.5 中斷矩陣
ESP32-S3的中斷矩陣將任意外部中斷源單獨分配到雙核CPU的任意外部中斷上,以便在外部設備中斷信號產生后,能夠及時通知CPU0或CPU1進行處理。外部中斷源必須經過中斷矩陣分配至CPU0/CPU1外部中斷,主要是因為ESP32-S3具有99個外部中斷源,但每個CPU只有32個中斷。通過使用中斷矩陣,可以根據應用需求將一個外部中斷源映射到多個CPU0中斷或CPU1中斷。實際上,CPU0和CPU1的外部中斷只有26個,剩下的6個中斷均為內部中斷。
下圖是雙核中斷矩陣結構。
這種設計使得ESP32S3能夠適應不同的應用需求,提供更大的靈活性和控制力。在硬件配置上,用戶需要確保中斷矩陣的正確配置,以便能夠正確地接收和處理外部中斷。同時,用戶也需要通過編程方式,根據實際需求對中斷矩陣進行適當的配置和操作。
當某個外部中斷源滿足觸發條件時(例如GPIO引腳信號狀態發生變化),該中斷信號將被送入中斷矩陣進行處理。中斷矩陣將根據中斷信號的特性,將其映射到一個特定的CPU外部中斷上。當CPU接收到這個外部中斷信號時,會執行與該中斷相關聯的ISR函數。
總的來說,ESP32S3的中斷矩陣是一種高效的中斷處理機制,它能夠將多個外部中斷源映射到兩個CPU的外部中斷上進行處理,并能夠查詢外部中斷源當前的中斷狀態。
3.6 ESP32-S3啟動流程
本文將會介紹ESP32-S3從上電到運行app_main函數中間所經歷的步驟(即啟動流程)。從宏觀上,該啟動流程可分為如下3個步驟。
①:一級引導程序,它被固化在ESP32-S3內部的ROM中,它會從flash的0x00處地址加載二級引導程序至RAM中。
②:二級引導程序從flash中加載分區表和主程序鏡像至內存中,主程序中包含了RAM段和通過flash高速緩存映射的只讀段。
③:應用程序啟動階段運行,這時第二個CPU和freeRTOS的調度器啟動,最后進入app_main函數執行用戶代碼。
下面作者根據IDF庫相關的代碼來講解這三個引導流程,如下:
一、一級引導程序
該部分程序是直接存儲在ESP32-S3內部ROM中,所以普通開發者無法直接查看,它主要是做一些前期的準備工作(復位向量代碼),然后從flash 0x00偏移地址中讀取二級引導程序文件頭中的配置信息,并使用這些信息來加載剩余的二級引導程序。
二、二級引導程序
該程序是可以查看且可被修改,在搭建ESP-IDF環境完成后,可在esp-idf\components\bootloader/subproject/main/路徑下找到bootloader_start.c文件,此文件就是二級引導程序啟動處。首先我們克隆ESP-IDF庫,克隆過程如下所示。
克隆完成后,使用VSCode打開ESP-IDF庫,接著找到bootloader_start.c,如下圖所示。
在這個文件下,找到call_start_cpu0函數,此函數是bootloader程序,如下是bootloader程序的部分代碼。
/*
ROM引導加載程序完成從閃存加載第二階段引導加載程序之后到達這里
*/
void__attribute__((noreturn)) call_start_cpu0(void)
{
? ? if (bootloader_before_init) {
? ?? ? bootloader_before_init();
? ? }
/* 1. 硬件初始化:清楚bss段、開啟cache、復位mmc等操作
bootloader_support/src/esp32s3/bootloader_esp32s3.c */
? ? if (bootloader_init() != ESP_OK) {
? ?? ? bootloader_reset();
? ? }
? ? if (bootloader_after_init) {
? ?? ? bootloader_after_init();
? ? }
? ? /* 2. 選擇啟動分區的數量:加載分區表,選擇boot分區 */
? ?bootloader_state_t bs = {0};
? ? int boot_index =select_partition_number(&bs);
? ? if (boot_index == INVALID_INDEX){
? ?? ? bootloader_reset();
? ? }
/* 3. 加載應用程序映像并啟動
bootloader_support/src/esp32s3/bootloader_utility.c */
? ?bootloader_utility_load_boot_image(&bs, boot_index);
}
ESP-IDF使用二級引導程序可以增加FLASH分區的靈活性(使用分區表),并且方便實現FLASH加密,安全引導和空中升級(OTA)等功能。主要的作用是從flash的0x8000處加載分區表(請看在線ESP32-IDF編程指南分區表章節)。根據分區表運行應用程序。
三、三級引導程序
應用程序的入口是在esp-idf/components/esp_system/port/路徑下的cpu_star.c文件,在此文件下找到call_start_cpu0函數(端口層初始化函數)。這個函數由二級引導加載程序執行,并且從不返回。因此你看不到是哪個函數調用了它,它是從匯編的最底層直接調用的。
這個函數會初始化基本的C運行環境(“CRT”),并對SOC的內部硬件進行了初始配置。執行call_start_cpu0函數完成之后,在components\esp_system\startup.c文件下調用start_cpu0(在110行中,弱關聯start_cpu0_default函數)系統層初始化函數,如下start_cpu0_default函數的部分代碼。
static voidstart_cpu0_default(void)
{
? ?ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
? ? /* 獲取CPU時鐘 */
? ? int cpu_freq = esp_clk_cpu_freq();
? ?ESP_EARLY_LOGI(TAG, "cpu freq: %d Hz", cpu_freq);
? ? /* 初始化核心組件和服務 */
? ?do_core_init();
? ? /* 執行構造函數 */
? ?do_global_ctors();
? ? /* 執行其他組件的init函數 */
? ?do_secondary_init();
? ? /* 開啟APP程序 */
? ?esp_startup_start_app();
? ? while (1);
}
到了這里,就完成了二級程序引導,并調用esp_startup_start_app函數進入三級引導程序,該函數的源碼如下:
/* components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c*/
/* 開啟APP程序 */
voidesp_startup_start_app(void)
{? ?/* 省略部分代碼 */
? ? /* 新建main任務函數 */
? ?esp_startup_start_app_common();
? ? /* 開啟FreeRTOS任務調度 */
? ?vTaskStartScheduler();
}
/* components/freertos/FreeRTOS-Kernel/portable/port_common.c*/
/* 新建main任務函數 */
voidesp_startup_start_app_common(void)
{
? ? /* 省略部分代碼 */
? ? /* 創建main任務 */
? ?portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???ESP_TASK_MAIN_STACK, NULL,
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);
? ?assert(res == pdTRUE);
? ? (void)res;
}
/* main任務函數 */
static void main_task(void* args)
{? ?/* 省略部分代碼 */
? ? /* 執行app_main函數 */
? ?app_main();
? ?vTaskDelete(NULL);
}
從上述源碼可知,首先在esp_startup_start_app_common函數調用FreeRTOS API創建main任務,然后開啟freeRTOS任務調度器,最后在main任務下調用app_main函數(此函數在創建工程時,在main.c下定義的)。