博客 / 詳情

返回

《ESP32-S3使用指南—IDF版 V1.6》第五章 工程的新建與配置

第五章 工程的新建與配置

在前面的章節中,我們已經簡要介紹了ESP32-P4的基礎知識和ESP-IDF的基本概念,並完成了VS Code IDE環境的搭建和Espressif插件的安裝。現在,基於這些前期準備,我們將在本章搭建一個ESP-IDF項目工程。之後的例程將以此基礎工程為模版進行編寫和擴展。
本章將分為如下幾個小節:
5.1 新建項目工程
5.2 工程文件架構解析
5.2 工程文件架構整理
5.5 項目工程配置

5.1 新建項目工程
在VS Code中新建ESP32工程是非常簡單的操作,接下來筆者將手把手教大家如何一步步創建ESP32項目工程。通過以下步驟,讀者可以快速上手並建立自己的ESP32開發環境。
1,打開所有命令面板
按下“Ctrl+Shift+P”快捷鍵打開所有命令面板,並在搜索欄內輸入“新項目”或者“New Project”內容,如下圖所示。

image001

圖5.1.1 搜索創建項目命令
2,配置項目工程參數
上圖回車後,我們根據需求配置項目工程名稱、項目保存路徑、選擇目標芯片、端口號等配置,如下圖所示。

image003

圖5.1.2 新建工程配置參數
3,選擇工程模板新建項目工程
配置參數填寫完成後,點擊上圖中的“Choose Template”選項,將進入選擇模版界面。在這個界面上,您會發現許多應用實例可供選擇(這些示例可以在路徑D:\Soft_APP\Espressif\frameworks\esp-idf\examples下找到)。為了新建工程,您可以採用某個應用示例作為模版,例如,若以樂鑫Blink跑馬燈實驗為模版,那麼新創建的工程將具備LED使用功能。下面筆者以sample_project為模版新建工程(因為此工程是樂鑫官方提供的基本模板,所以我們使用此模板來新建工程),如下圖所示:

image005

圖5.1.3 以sample_project為模版新建工程
點擊上圖的“Create project using template sample_project”新建工程,點擊完成後在此界面的右下角跳出以下信息,如下所示。

image007

圖5.1.4 是否使用新窗口打開工程
我們點擊“Yes”選項在新的窗口打開工程,此時系統彈出VS Code新窗口,如下圖所示。

image009

圖5.1.5 打開00_basic工程
注意:在上圖5.1.2中創建工程時選擇了“ESP32-P4 chip (via built-in USB-JTAG)”作為目標芯片,但在新建工程完成後,VS Code 左下角顯示的目標芯片仍然是 ESP32,這可能是由於當前 ESP-IDF 插件存在某些功能上的不完善或更新問題。
在上圖中,我們將目標芯片設置為esp32p4,然後點擊“ESP32-P4 chip (via built-in USB-JTAG)”下載類型,如下圖所示。

image011

image013

圖5.1.6 設置Espressif設備目標
00_BASIC工程與樂鑫官方提供的sample_project示例的內容和工程結構完全相同,讀者可以通過對比這兩個工程來更好地理解項目的基本框架和文件佈局。在接下來的小節中,作者將詳細講解00_BASIC工程中每個文件的作用,以幫助讀者更深入地瞭解其功能和在開發過程中的重要性。
注意:正點原子ESP32-P4的所有工程默認會設置自動編碼文件格式。如果VSCode的默認文件編碼為UTF-8,其他編碼格式的文件可能會顯示亂碼。為避免此問題,正點原子在每個工程的settings.json文件中添加了以下內容。

"files.autoGuessEncoding": true,

5.2 工程文件架構解析
在上小節中,我們已經成功在VS Code上新建了一個ESP-IDF工程。接下來,筆者將重點講解這個基礎工程的文件架構。該基礎工程的文件架構(即00_BASIC工程)如下圖所示。

image015

圖5.2.1 基礎工程文件架構
在ESP32工程的基礎架構中,每個文件和文件夾都有特定的作用。以下是對每個文件及文件夾的解析:
1,CMakeLists.txt(頂層CMake):
作用:頂層項目的CMakeLists.txt文件是CMake用於構建項目的主要配置文件。在此文件中,可以設置項目的全局CMake變量。該文件會導入位於IDF_PATH/tools/cmake/project.cmake的文件,由後者負責實現構建系統的其餘部分。最終,該文件將設置項目名稱並定義項目的基本信息。以下是CMakeLists.txt文件的內容。

# 以下模板代碼必須按此順序出現在項目的CMakeLists.txt文件中,以確保CMake正常工作
cmake_minimum_required(VERSION 3.16)  # 指定所需的最低CMake版本

include($ENV{IDF_PATH}/tools/cmake/project.cmake)  # 包含ESP-IDF供的項目構建文件

project(00_basic)  # 定義項目名稱為00_basic

2,README.md:
作用:這是一個常見的文檔文件,通常用於提供項目的介紹和基本使用説明。開發者可以在此處寫明項目的描述、運行步驟、依賴關係等信息,方便他人快速瞭解該項目。
3,main文件夾:
作用:“main”目錄是一個特殊的組件,專門用於包含項目的源代碼。它是CMake的默認名稱,且 CMake 變量COMPONENT_DIRS默認包含此組件。你可以根據需要修改此變量以適應項目結構。如果項目中源文件較多,建議將源文件組織成多個組件,而不是將所有文件都放在“main”目錄中。這種做法有助於提升代碼的可維護性和可讀性。
注意:“main”目錄會自動添加到構建系統中。其他組件也會作為其依賴項一併添加,這樣可以免去用户處理依賴關係的麻煩,並提供即時可用的構建功能。簡單來説,在“main”文件夾中定義的應用文件可以直接調用其他組件(如PPA、LVGL等API),而無需在main/CMakeLists.txt文件中聲明它們的依賴關係。
1)main/CMakeLists.txt:
作用:定義 main 文件夾內代碼的構建規則,特別是與主程序相關的文件編譯和鏈接細節。這個文件用於告訴 CMake 如何處理 main.c 等源文件,並將其編譯到最終的可執行程序中。以下是main/CMakeLists.txt文件的內容。

idf_component_register(SRCS "main.c"    # 指定組件的源文件列表,當前包含 main.c
                    INCLUDE_DIRS ".")   # 定義頭文件的包含目錄,"." 表示當前目錄

如果我們在main文件夾下新建APP文件夾來保存自己編寫的應用程序源文件,那麼CMakeLists.txt文件的內容的內容可以這樣編寫:

idf_component_register(
    SRC_DIRS                # 指定源文件的目錄列表
        "."                 # 當前目錄
        "APP"               # "APP" 目錄,包含其他源文件
    INCLUDE_DIRS            # 指定頭文件的包含目錄列表
        "."                 # 當前目錄
        "APP"               # "APP" 目錄,包含相關頭文件
)

2)main/main.c:
作用:項目的主源文件,包含實際的應用程序代碼。在這個文件中,通常會定義程序的入口函數(app_main()),並編寫項目的核心邏輯和實現。
4,sdkconfig
作用:“sdkconfig”是項目的配置文件,在執行idf.py menuconfig時創建或更新。該文件保存了項目中所有組件(包括ESP-IDF本身)的配置信息。根據項目需求,sdkconfig文件可以選擇是否添加到源碼管理系統中。

5.2 工程文件架構整理
在講解正點原子ESP32工程架構之前,我們先了解一下樂鑫ESP32的工程架構。樂鑫ESP32的工程架構為整個開發流程奠定了基礎,是理解如何進行開發和調試的關鍵。

image018image019

圖5.2.1 樂鑫官方的ESP32項目工程架構
從上圖可以清楚地看到,除了components文件夾外,該工程架構與我們在5.2小節中創建的基本架構一致。components文件夾主要用於存放第三方組件,無論是支持ESP Component Registry的組件,還是未支持的組件,或是開發者自定義的驅動庫,都可以放在該文件夾中。然而,隨着項目規模的擴大,採用標準的樂鑫 ESP32 工程架構可能會導致架構變得複雜,難以維護。為了解決這一問題,正點原子提出了不同的組織方式:開發者編寫的驅動文件被整理到components文件夾下的BSP(板級支持包)子文件夾中;而ESP Component Registry支持的組件(如裸機移植)或其他第三方組件則被整理到components文件夾下的Middlewares子文件夾中。這種做法使硬件相關的驅動文件得到更好的管理,增強了工程的模塊化和層次結構。
此外,我們簡化了CMakeLists.txt文件的管理。通過僅保留一個主CMakeLists.txt文件來加載多個驅動庫,減少了繁瑣的配置步驟,從而提高了工程的整潔性和可維護性。這種優化方式不僅減輕了開發者的管理負擔,還提高了項目的開發效率和擴展性。
下圖為正點原子ESP32工程文件架構。

image021image022

圖5.2.2 正點原子ESP32工程結構
從上圖可以清楚地看到,正點原子將所有開發者編寫的程序驅動(如LED、KEY、LCD 等)統一放置在BSP文件夾下,而Middlewares文件夾則用於存放第三方組件。這些組件包括 ESP Component Registry 支持的組件、自定義的第三方組件,以及其他開發者編寫的組件。每個組件都包含一個CMakeLists.txt文件,用於將該組件添加到構建系統中。
為了高效管理BSP文件夾下的程序驅動,我們引入了一個統一的CMakeLists.txt文件。它的優勢在於,創建新的驅動文件時,不再需要像樂鑫ESP32工程那樣為每個驅動單獨創建CMakeLists.txt文件。相反,只需一個CMakeLists.txt文件即可完成所有驅動庫的管理,從而簡化了開發流程,提升了效率。
接下來,我們將詳細介紹 BSP 文件夾下的 CMakeLists.txt 文件的具體實現,代碼如下:

①	源文件路徑,指本目錄下的所有代碼驅動
set(src_dirs
            KEY
            LCD
            LED
            SDMMC)
②	頭文件路徑,指本目錄下的所有代碼驅動
set(include_dirs
            KEY
            LCD
            LED
            SDMMC)
③	設置依賴庫
set(requires
            driver
            esp_lcd
            esp_common
            fatfs)
④	註冊組件到構建系統的函數
idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS 
${include_dirs} REQUIRES ${requires})
⑤	設置特定組件編譯選項的函數
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
	-ffast-math: 允許編譯器進行某些可能減少數學運算精度的優化,以提高性能。
	-O3: 這是一個優化級別選項,指示編譯器儘可能地進行高級優化以生成更高效的代碼。
	-Wno-error=format: 這將編譯器關於格式字符串不匹配的警告從錯誤降級為警告。
	-Wno-format: 這將完全禁用關於格式字符串的警告。

在開發過程中,設定項④和⑤是固定不變的。而設定項①和②則根據項目所需的驅動文件數量而變化。如果當前目錄下缺少某個特定的驅動文件(例如LED驅動文件),但在CMakeLists.txt文件中仍然指定了該文件需要編譯,那麼在系統編譯時將會遇到如下錯誤:

image023

圖5.2.3 未發現LED驅動文件
此時,需要我們添加LED驅動文件至BSP文件夾下,並且全部清除編譯工程文件才能再一次編譯工程。
③表示驅動程序需要依賴的庫,例如LCD驅動程序,它依賴的是esp_lcd等這些ESP-IDF(SDK)核心組件實現的。下圖是CMakeLists.txt未添加依賴庫的錯誤提示。

image025

圖5.2.4 未添加依賴庫的提示錯誤(LCD驅動程序未添加依賴庫)
在components文件夾下,無論是驅動還是第三方組件的CMakeLists.txt文件,都必須根據實際需求添加所需的依賴庫。如果某個驅動或組件未正確添加依賴庫,系統在編譯時可能會提示未找到某個函數或頭文件的錯誤。
注意:main組件無需添加依賴庫,這是我們之前已講解過的知識點,此處無需重複説明。如果Middlewares文件夾下的某個第三方組件調用了BSP文件夾中的驅動,那麼必須在其CMakeLists.txt文件中添加對BSP的依賴。例如,在5.2.2小節中的TEXT漢字顯示組件,它調用了ESP-IDF(SDK)核心組件的分區表API、spi_flash 組件API、fatfs 組件API 以及BSP文件夾下的驅動API。因此,CMakeLists.txt文件的編寫內容應如下:

list(APPEND srcs    fonts.c
                    text.c) #TEXT組件的源文件

idf_component_register( SRCS "${srcs}"              #指向哪些源文件
                        INCLUDE_DIRS "."            #指向當前組件根目錄的.h頭文件
                        REQUIRES    esp_partition   #依賴核心組件分區表API
                                    spi_flash       #依賴核心組件SPIFLASH API
                                    fatfs           #依賴核心組件文件系統fatfs API
                                    BSP)            #依賴驅動 API

至此,本書籍提供的項目工程文件結構介紹完畢,請讀者認真瞭解該項目工程結構。
5.5 項目工程配置
在第二章中,我們瞭解到樂鑫ESP32-P4芯片有兩個型號:ESP32-P4NRW16和ESP32-P4NRW32,分別內置16M和32M PSRAM。使用這兩個型號的芯片設計板子時,必須掛載外部FLASH,因為內部的ROM僅用於存儲P4啓動固件,是隻讀且不可編程的,無法存儲用户程序。因此,設計板子時必須項目需求掛載外部FLASH容量以存儲用户程序,我們正點原子DNESP32P4開發板使用的是16MB的Flash,所以在項目工程中,必須在menuconfig配置為16MB Flash容量等相關配置。
在本章節中,筆者將重點講解如何讓前面創建的工程匹配我們設計的系統資源(如FLASH 大小、主頻、OS節拍等)。如果不進行這些參數配置,項目程序將無法充分發揮P4芯片的全部功能。接下來,筆者將通過00_basic項目工程,逐步介紹項目的配置,具體步驟如下。
1,打開00_basic項目工程
在VS Code中,按下“Ctrl + Shift + P”快捷鍵進入 “顯示所有命令” 頁面。在此頁面的搜索欄中輸入“SDK Configuration Editor (Menuconfig)” 並按回車鍵進入配置界面。如圖所示。

image027

圖5.5.1 menuconfig菜單(部分截圖)
關於menuconfig配置界面的具體內容,作者將在後續的章節中進行詳細講解。目前,我們的主要目標是配置項目工程與DNESP32P4開發板相匹配的資源。
2,在上圖“Search parameter”搜索框下輸入“Flash”進去flash配置界面,如下所示。

image029

圖5.5.2 配置Flash資源
上圖中的①“Flash SPI mode”支持四種不同的 SPI flash 訪問模式,它們分別為DIO、DOUT、QIO 和 QOUT。下面我們來看一下這幾種模式到底有哪些區別,這些模式的對比如下表所示。

QQ截圖20260209094856

表5.5.1 四種SPI模式的對比
從上表可以看出,QIO模式的速率最快,因此我們將基礎工程的Flash SPI模式設置為QIO。上圖中的②“Flash SPI speed” 提供了80MHz、40MHz和20MHz的配置選項。鑑於PSRAM的 SPI 速率最高可設置為80MHz,為了確保系統的最佳性能,我們同樣將Flash的SPI速率設置為80MHz。上圖的③是根據模組掛載的flash來確定的,這裏筆者選擇16MB大小,是毫無爭議的。
3,在搜索框中輸入“Partition Table”來設置分區表。分區表的主要功能是將flash劃分為多個功能各異的區域,包括存儲啓動文件、代碼區域和文件系統區域等子分區,以滿足不同的應用需求。後續章節將詳細解釋分區表的作用和配置方法。下圖是基礎工程分區表配置參數。

image031

圖5.5.3 配置分區表
上圖中,筆者選擇“Custom partition table CSV”自定義分區表,然後設置分區表的名稱為partitions-16MiB.csv。稍後我們會設置分區表各個子分區的管理大小。
4,在搜索框中輸入“PSRAM”來設置PSRAM參數,配置參數如下圖所示。

image033

圖5.5.4 設置PSRAM
在上圖中,筆者首先勾選了①“Support for external PSRAM”以表示支持掛載PSRAM。接着,取消了②選項以關閉PSRAM測試。如果不關閉PSRAM測試,系統啓動會變得非常緩慢。
如果讀者遇到屏幕閃爍或圖像漂移的問題,可以開啓上圖中的“XiP”模式。在此模式下,Flash中的固件(包括指令和數據)將在啓動時移動到PSRAM中,固件代碼將直接從PSRAM執行。這種配置可以有效解決屏幕閃爍或圖像漂移等問題。
注意:在上圖中,“PSRAM clock speed”的時鐘最高為20MHz。如果讀者希望配置到最高時鐘,可以啓用P4的實驗特性。在搜索框中輸入 “Make experimental features visible”並啓用該選項,這樣PSRAM的時鐘可設置為20MHz。一般在使用MIPI屏幕時,必須開啓此功能。因此,本書籍提供的例程通常都會啓用該選項,並同時開啓“XiP” 功能。
5,在搜索框中輸入“CPU frequency”來設置CPU的時鐘頻率,如下圖所示:

image035

圖5.5.5 配置CPU主頻
這裏,筆者將主頻設置為400MHz,也是ESP32-P4芯片最高的主頻了。
6,在搜索框中輸入“FreeRTOS” 以配置系統節拍時鐘(tick clock)的頻率。默認情況下configTICK_RATE_HZ的值為100,表示節拍時鐘的週期為10ms。因此,調用vTaskDelay(1000) 會導致延遲10秒。為了提高定時精度和方便性,建議將該值設置為1000,這樣節拍時鐘的週期就變為1ms,從而使vTaskDelay(1000) 代表延遲1秒。具體操作如圖所示

image037

圖5.5.6 配置系統節拍時鐘(tick clock)的頻率
至此,保存menuconfig配置並退出。
7,配置分區表各個子分區,我們按下“Ctrl+Shift+P”快捷鍵打開命令面板,並在搜索欄內輸入“Open Partition Table Editor UI”,按以下圖配置各個分區的管理大小。

image039

圖5.5.7 設置分區表
首先,我們按下“Add New Row”選項以添加子分區條目,然後設置條目的類型、偏移和大小,最後點擊“Save”選項保存並退出。
至此,我們已完成工程配置,確保其與ESP32-P4NRW32的內部資源相匹配。現在,我們可以利用這個工程在DNESP32P4開發板上進行開發工作。接下來,我們來看一下當前的工程架構,如下圖所示。

image041

圖5.5.8 配置完的工程架構
上圖中的sdkconfig.old是之前基礎工程所使用的舊版系統配置文件,用於記錄之前的配置信息。而當前的sdkconfig則是系統最新生成的配置文件,包含了最新的設置。此外,partitions-16MiB.csv是系統配置保存後自動生成的分區表文件,供用户查看當前的分區配置情況。這些文件共同構成了ESP32開發環境的配置體系。
接下來,作者在項目工程的app_main函數中編寫了代碼,以獲取ESP32-P4NRW32的內部資源信息。這些信息包括時鐘頻率、flash大小以及PSRAM大小等。具體的代碼實現如下所示:

void app_main(void)
{
    esp_err_t ret;
    uint32_t flash_size;
    esp_chip_info_t chip_info;  /* 芯片相關信息 */

    ret = nvs_flash_init();     /* 初始化NVS */
if (ret == ESP_ERR_NVS_NO_FREE_PAGES 
|| ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ESP_ERROR_CHECK(nvs_flash_init());
    }

    /* 獲取flash大小 */
    ESP_ERROR_CHECK(esp_flash_get_size(NULL, &flash_size));
    /* 芯片信息 */
    esp_chip_info(&chip_info);

    ESP_LOGI(TAG, "| %-12s | %-10s |", "describe", "explain");
    ESP_LOGI(TAG, "|--------------|------------|");

    if (chip_info.model == CHIP_ESP32P4)
    {
        ESP_LOGI(TAG, "| %-12s | %-10s |", "model", "ESP32P4");/* 芯片型號 */                   
    }
    /* 獲取芯片的內核數量 */
ESP_LOGI(TAG, "| %-12s | %-d          |", "cores",      chip_info.cores);                       
/* 獲取芯片的內核數量 */
ESP_LOGI(TAG, "| %-12s | %-d          |", "revision",   chip_info.revision);                    
/* 獲取FLASH大小(MB) */
ESP_LOGI(TAG, "| %-12s | %-ld         |", "FLASH size", \
flash_size / (1024 * 1024));
/* 獲取PSRAM的大小(MB) */
ESP_LOGI(TAG, "| %-12s | %-2d         |", "PSRAM size", \
esp_psram_get_size() / (1024 * 1024));
    ESP_LOGI(TAG, "|--------------|------------|");

    while(1)
    {
        ESP_LOGI(TAG, "Hello-ESP32P4");
        vTaskDelay(pdMS_TO_TICKS(1000));            /* 延時1s */
    }
}

上述代碼是獲取ESP32-P4NRW32的內部資源信息,並打印到監控器上。首先我們編譯基礎工程,然後下載至開發板中,最後打開監控器查看串口打印內容,如下圖所示:

image043

圖5.5.9 打印內部資源信息
在以後的例程中,我們是以這個基礎工程來延申擴展,所以本章節的內容非常重要,望讀者好好理解。

5.6 ESP-IDF插件的下載與調試工具
ESP-IDF提供了集成的調試工具,特別是VS Code中通過插件形式,可以為開發者提供方便的調試環境。以下圖是ESP-IDF插件調試工具的一些關鍵功能和使用。

image045

圖5.6.1 ESP-IDF插件的下載與調試工具
(1)選擇SDK模板(豬頭圖標):通過該圖標選擇不同的SDK版本編譯工程。
(2)選擇串口號(插頭圖標):選擇連接開發板的下載串口號,VS Code會列出當前電腦連接的所有串口供選擇。串口選擇會被記錄,下次打開VS Code無需重新選擇。在開發過程中,儘量不要更換USB線或更換電腦的插口,否則串口號會發生變化。
(3)設置Espressif設備目標(芯片圖標):對應IDF命令idf.py set-target xxxx。此選項用於設置當前工程要下載到的目標芯片型號(如ESP32 S2、S3、C2、C3和P4 等)。該設置會寫入當前工程配置文件,默認情況下工程配置目標芯片為ESP32。
(4)查看當前工程位置(文件夾圖標):查看當前項目工程路徑。
(5)SDK配置編輯器(齒輪圖標):對應IDF命令 idf.py menuconfig,用於配置當前工程的系統設置。配置項非常多,建議在需要時再修改。
(6)清除全部構建文件(垃圾桶圖標):用於清除編譯生成的文件,常用於在壓縮或拷貝工程文件時減少佔用空間。如果編譯過程中出現問題,也可以嘗試清除後再重新編譯。
(7)構建項目(扳手圖標):編譯當前項目工程。此操作僅編譯功能,不包含下載固件。
(8)選擇燒錄方式(五角星圖標):可選擇UART、JTAG和DFU下載,通常選擇串口 UART 方式下載。
(9)燒錄設備(閃電圖標):將編譯好的固件下載到設備芯片中。此操作僅下載固件,不包含編譯功能。如果修改了代碼,需要先編譯再點擊下載,所做的修改才會生效。
(10)監控設備(電視機圖標):用於查看設備的串口信息輸出(UART和JTAG均可打開)。
(11)調試(小爬蟲圖標):此操作僅用於JTAG接口進行調試。
(12)構建、下載與監控(一團火圖標):最常用的功能之一,一次性完成編譯、下載和打開串口監控的所有操作。
(13)打開ESP-IDF終端(命令圖標):打開命令行窗口,定位到當前項目路徑下,可以執行ESP-IDF相關命令。
(14)工程的錯誤與警告提示(錯誤和警告圖標):顯示當前工程中出現的錯誤和警告,便於快速定位和解決問題。
從上述可以看到,ESP-IDF插件工具欄提供了集成的功能,簡化了開發、調試和下載固件的流程,使開發者可以專注於代碼邏輯的實現。通過這些功能,工程管理更加高效便捷。
下面筆者將簡單介紹ESP32-P4的兩種下載方式:UART下載 和JTAG下載。其中,UART下載僅支持固件下載,適用於基礎開發和固件更新。而JTAG下載不僅支持固件下載,還具備強大的調試功能,可以進行代碼級調試,如設置斷點、查看寄存器等,適合更復雜的開發場景。

5.6.1 串口下載方式
下面,筆者以5.1小節新建工程(00_BASIC)為例,簡單講解一下工程的下載流程,如下流程所示。
(1)使用USB線的Type-C接口連接DNESP32P4開發板的USB串口,並USB A口連接到電腦,使得電腦與開發板建立連接。
(2)在設備管理器中,查看USB串口的端口號,並在VS Code軟件左下角調試區域設置端口號(插頭圖標)。
(3)點擊“設置Espressif設備目標”(芯片圖標)選擇目標芯片,這裏筆者選擇ESP32-P4.
(4)選擇“燒錄方式”(五角星圖標),如UART或者JTAG
(5)點擊“清除構建”(垃圾桶圖標)清除工程。
(6)點擊“構建項目”(扳手圖標)編譯工程。
(7)編譯完成後,點擊“燒錄設備”(閃電圖標)下載代碼。
編譯工程成功後,工程目錄下出現build文件夾,這個文件夾是由ESP-IDF Tools生產的文件,如log、固件、map等下載和調試文件。如下圖所示:

image047

圖5.6.1.1 編譯輸出文件(部分截圖)
編譯完成後,VSCode軟件底部的“終端”窗口會輸出編譯信息,如下圖所示:

image049

圖5.6.1.2 編譯00_BASIC工程
上圖顯示了一個 內存類型使用總結 的輸出結果,詳細列出了微控制器不同內存區域的使用情況。以下是各部分的描述:
1,Flash 存儲:
1)已使用:152832字節,佔用總Flash內存的0.23%。
2)詳細分配:
①:.text:109424字節。用來存儲用户程序,運行時,加載至RAM中執行。
②:.rodata:42904字節。存儲只讀數據,例如常量和不可修改的字符串。
③:.appdesc:256字節。存儲應用描述符信息,如程序的版本信息、編譯時間等元數據。
④:.init_array:248字節。存儲全局和靜態對象的構造函數指針。
2,DIRAM(數據指令 RAM):
1)已使用:80864字節,佔用總DIRAM的14.03%。
2)詳細分配:
①:.text:65482字節。關鍵代碼存儲在DIRAM,用於加快執行速度。
②:.data:9229字節。初始化的全局或靜態變量存儲在DIRAM中。
③:.bss:6092字節。在程序中聲明但未初始化的全局或靜態變量,運行時被初始化為0並存儲在DIRAM中,可在程序運行過程中動態更新。
3,LP RAM(低功耗 RAM):
1)已使用:128字節,佔用總LP RAM的0.39%。
2)詳細分配:
.rtc_reserved:24字節。
4,HP 核心 RAM (高性能 RAM):
1)已使用:90字節,佔用總HP核心RAM的1.1%。
2)詳細分配:
①:.data:60字節。一些高頻訪問的初始化數據變量存儲在高性能 RAM 中。
②:.text:30字節。存儲快速執行的極少量核心代碼。
總鏡像大小:227385字節(可能會在 .bin 文件中填充更多)。
編譯成功後,點擊圖5.6.1中的“設備燒錄”(閃電圖標)就可以把編譯出來的可執行文件燒錄至DNESP32P4開發板上。

5.6.2 JTAG下載與調試
本小節參考樂鑫ESP-IDF編程指南的JTAG調試章節,介紹了ESP32-P4的調試功能。
ESP32-P4內置JTAG電路,因此無需額外的芯片即可實現調試。通過將USB線連接到D+/D-引腳,開發人員可以方便地進行下載和調試。利用JTAG接口,開發者可以通過開源工具OpenOCD對ESP32-P4進行調試。OpenOCD是一款專為嵌入式系統設計的工具,支持通過JTAG或SWD接口執行調試、固件燒寫等任務。
根據樂鑫官方資料,ESP32-P4支持兩種JTAG調試方式:
1)內置JTAG調試:直接利用ESP32-P4內置的JTAG電路進行調試,無需額外硬件。
2)使用ESP-PROG調試器:ESP-PROG是一款官方調試器,集成了自動下載固件、串口通信和JTAG在線調試等功能,進一步提升了開發效率。
在VS Code中安裝OpenOCD時,環境會自動配置,開發者可以直接使用內置JTAG電路與VS Code中的OpenOCD進行調試和下載操作,從而簡化了開發流程。下面筆者帶讀者瞭解一下JTAG下載與調試流程,如下所示。
1,新建launch.json文件
在VS Code中,點擊“運行與調試”或使用快捷鍵“Ctrl + Shift + D”進入調試界面,選擇“創建launch.json”文件,然後選擇“ESP-IDF”調試器進行配置,如下圖所示。

image051

圖5.6.2.1 新建ESP-IDF調試文件
在上圖中,我們按照圖示的①②③順序操作,即可完成調試器的配置。完成這些步驟後,在生成的launch.json文件中添加所需的調試信息。具體的調試信息及配置內容,筆者將在後續章節中詳細講解。
2,添加launch.json文件調試信息
關於launch.json文件的調試信息,樂鑫官方提供了詳細的VS Code調試配置文件launch.json的指導説明,您可以參考樂鑫官網提供的調試配置頁面。在該頁面中,會詳細介紹如何根據您使用的調試器(如JTAG調試器或VS Code內置調試工具)來修改launch.json的內容。由於我們選擇使用VS Code進行調試,則選擇“Use Microsoft C/C++ Extension to Debug”的launch.json文件內容,如下代碼所示:

{
  "configurations": [
    {
      "name": "GDB",
      "type": "cppdbg",
      "request": "launch",
      "MIMode": "gdb",
      "miDebuggerPath": "${command:espIdf.getToolchainGdb}",
      "program": "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf",
      "windows": {
        "program": "${workspaceFolder}\\build\\${command:espIdf.getProjectName}.elf"
      },
      "cwd": "${workspaceFolder}",
      "setupCommands": [
              { "text": "target remote :3333" },    # 必須添加這一段
              { "text": "set remotetimeout 20" },
          ],
          "postRemoteConnectCommands": [
              { "text": "mon reset halt" },
              { "text": "maintenance flush register-cache"},
          ],
      "externalConsole": false,
      "logging": {
        "engineLogging": true
      }
    }
  ]
}

從上述代碼可以看到,我們必須在launch.json文件中添加 { "text": "target remote :3333" } 這一行,否則可能會導致調試錯誤。完成這一步後,將配置內容完整拷貝到剛剛創建的launch.json文件中,這樣就完成了launch.json文件的全部配置。
3,JTAG下載程序流程
使用USB線的Type-C接口連接DNESP32P4開發板的USB 串口/ JTAG,並USB A口連接到電腦,使得電腦與開發板建立連接。
1)點擊“選擇燒錄方法”(五角星圖標),這裏我們選擇JTAG下載。
2)點擊“選擇要使用的端口”(插頭圖標),根據電腦識別選擇端口號。
3)點擊“清除構建”(垃圾桶圖標)擦除工程。
4)點擊“構建項目”(扳手圖標)編譯工程。
編譯成功後,點擊“燒錄設備”下載程序至開發板中,此時,VS Code提示是否運行OpenOCD,如下圖所示。

image053

圖5.6.2.2 運行OpenOCD
下載成功後,VS Code右下角提示如下信息。

image055

圖5.6.2.3 提示下載成功
4,JTAG調試流程
JTAG調試過程非常簡單。首先,將代碼下載至開發板。然後,在VS Code中點擊“運行與調試,或者使用快捷鍵“F5”啓動調試。如下圖所示,操作十分直觀,開發人員可以輕鬆進行調試。此時,系統執行到app_main函數中的第一行代碼,如下圖所示。

image057

圖5.6.2.4 調試效果
在上圖中,右上角提供了一系列用於調試代碼的選項。由於這些功能在學習MDK開發環境時已有詳細介紹,並且是開發中經常使用的工具,因此作者在此不再對這些調試選項進行過多講解。開發者可以直接使用這些熟悉的功能,進行代碼調試和問題排查。
5,JTAG調試方法
接下來,作者將簡要介紹一些在VS Code中使用JTAG調試的操作,包括如何加載變量到監視窗口,以及如何打開反彙編視圖等實用功能。
1)變量監控: 在調試時,選擇一個變量,右鍵點擊並選擇“添加到監視”。這樣,該變量就會出現在監視窗口中,方便實時查看其值的變化,如下圖所示。

image059

圖5.6.2.5 變量添加到監視器中
此時,在運行與調試界面中,監視窗口將實時顯示該變量的當前值,如下圖所示。

image061

圖5.6.2.6 監視變量和監視CPU寄存器
除了簡單的變量,您還可以監控 函數、結構體 等複合類型。只需在代碼中選擇對應的對象並添加到監視窗口中,您可以實時監控這些元素的變化。
2)調用堆棧:調用堆棧用於顯示當前程序的執行路徑,幫助開發者追蹤函數調用順序,尤其在發生異常時可以快速定位問題,如下圖所示。

image063

圖5.6.2.7 顯示當前程序的執行路徑
上圖右側“已暫停”提示表示程序暫停,下一次運行時將不會繼續執行該位置的代碼。如果顯示文件名和行號,則表明程序當前運行到該文件的指定行。
3)斷點監控:允許開發者在程序執行到特定位置時暫停程序並檢查系統狀態。斷點監控不僅可以幫助開發者定位代碼錯誤,還可以用來監控特定的變量、寄存器或硬件狀態。在 VS Code 中,設置斷點非常簡單。您只需在代碼的某一行上點擊左側的行號即可設置斷點。執行到該行時,程序會暫停。如下圖所示。

image065

圖5.6.2.8 設置斷點
在斷點監控區域可看到我們設置的當前位置和刪除斷點,如下圖所示。

image067

圖5.6.2.9 斷點監控
4)反彙編視圖:反彙編視圖顯示程序的機器碼指令,並將其轉換為彙編語言,便於開發者分析底層代碼的執行過程。通過此視圖,開發者可以查看程序的控制流、數據處理以及硬件資源的使用情況。通過下圖操作就可以打開ESP32-P4項目工程的反彙編視圖了。

image069

圖5.6.2.10 打開反彙編視圖
至此,JTAG調試方法的講解到此結束。如需瞭解更多JTAG調試的使用方法,建議查閲樂鑫官方提供的《ESP-IDF Extension for VSCode》在線文檔(https://docs.espressif.com/projects/vscode-esp-idf-extension/zh_CN/latest/index.html),獲取更詳盡的指導。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.