参考资料:
技术规格书
技术参考书
调试openocd手册
应用程序的启动流程 - ESP32-C3 - — ESP-IDF 编程指南 latest 文档
一,芯片复位运行的流程
1,上电复位执行一级引导程序(固化在芯片ROM,无法修改)
2,一级引导程序工作:
根据芯片boot启动模式判断是否SPI,或下载启动模式
如果是spi启动模式,则从flash 0x0处加载二级引导程序到IRAM中运行。
如果是下载启动模式,则等待UART0/USB(jtag)接口
Boot启动模式
获取bootstrap 3个引脚的状态(寄存器GPIO_STRAP_REG 0x0038 ):
GPIO2 GPIO8 GPIO9(弱上拉)
1 x 1 SPI启动 (加载flash中的程序)
1 1 0 下载启动 模式(UART0 或 USB )
Note: 启动时,一般是将程序加载到IRAM运行;但是 寄存器(地址:0x42000000)= 0xaebd041d时,直接在flash运行.
eFuse存储器控制一级引导程序启动打印:
eFuse 的 EFUSE_UART_PRINT_CONTROL
=0 默认,打印
=1 GPIO8=0 上电打印 GPIO8=1 上电不打印
=2 GPIO8=1 上电打印 GPIO8=0 上电不打印
=3 不打印
3,二级引导程序: 从flash加载分区表信息,加载主程序(app_main)到RAM,并处理主程序所有数据和代码段,flash高速映射只读段(从flash运行时)。
二级引导程序路径:(build/bootloader/bootloader.bin)
二,分析启动流程相关信息
0,分析前准备工作
0.1 硬件连接
1,开发板 USB-jtag 接电脑 USB
2,开发板UART0 接 USB-TTL, 再接 电脑USB (UART0是ESP32C2调试信息默认输出接口。
0.2 打开三个终端:helloworld项目终端,openOCD终端,telnet终端。
开始分析:
获取固件信息(二级引导程序、主程序、分区表)和UART0打印的调试信息
hellowordl终端run:
get_idf (一键导入编译工具环境)
idf.py build
idf.py flash
build过程得到的信息(截取):
hello_world.bin(项目主程序) binary size 0x24a10 bytes. Smallest app partition is 0x100000 bytes. 0xdb5f0 bytes (86%) free.
espressif/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 espressif/hello_world/build/bootloader/bootloader.bin(二级引导程序)
Bootloader binary size 0x4eb0 bytes. 0x3150 bytes (39%) free.
Project build complete. To flash, run this command:
esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32c3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello_world.bin
or run 'idf.py -p (PORT) flash'
项目生产的三部分信息在flash中的分布:
1,二级引导程序的flash烧录地址是:0x0 size 0x4eb0 bytes
2,分区表flash烧录地址是: 0x8000
3,主程序的flash烧录地址是0x10000 size 0x24a10 bytes.
执行 idf.py partition-table 得到分区别信息
Partition table binary generated. Contents:
*******************************************************************************
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,24K,
phy_init,data,phy,0xf000,4K,
factory,app,factory,0x10000,1M,
*******************************************************************************
分区表的配置:在项目根目录的文件sdkconfig文件中 Partition Table部分内容。该文件是idf框架的配置文件,可以通过idf.py menuconfig查看和修改。当前使用的是预配置的 “Single factory app, no OTA” 配置。打开sdkconfig可以看到分区表的offset配置为0x8000.
CONFIG_PARTITION_TABLE_OFFSET=0x8000
有三个分区表:其中子名称为factory ,类型Type为app的分区 会被二级引导程序识别并加载到IRAM中。其他两个分区表(nvs,phy_init)存放一些数据。
关于分区表的详细描述:
分区表 - ESP32-C3 - — ESP-IDF 编程指南 latest 文档
Helloworld 终端运行:
idf.py monitor
监听UART0的信息。(必要时指定串口 -p port)
OPENOCD终端运行run:
get_idf
openocd -f board/esp32c3-builtin.cfg
返回信息:
Open On-Chip Debugger v0.10.0-esp32-20211111 (2021-11-10-21:44)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Warn : Transport "jtag" was already selected
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255
Info : clock speed 40000 kHz
Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)
Info : datacount=2 progbufsize=16
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x40101104
Info : Listening on port 3333 for gdb connections
此时OPENOCD就等待调试程序的连接。
我们先用telnet做简单调试和控制
telnet终端运行run:
telnet localhost 4444
Halt
Reset
Halt
通过openocd 使芯片从新复位运行,和暂停。
在监听UART0的终端就可以看到输出的调试信息:
芯片一级固化程序打印信息:
ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x20000348
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x17ac (数据段)
load:0x403ce000,len:0x930 (代码段)
load:0x403d0000,len:0x2d78
entry 0x403ce000(入口地址 call_start_cpu0 )
一级引导程序加载二级引导程序的数据段和代码段。把二级引导程序代码(bootloader)加载到了地址:0x403ce000(这是内部SRAM1的指令空间),数据段加载到0x3fcd6100(内部SRAM1数据空间)。
二级程序入口地址 0x403ce000= call_start_cpu0 (代码:bootloader_start.c)
参考二级引导程序的代码:
components/bootloader/subproject/main/ld/esp32c3/bootloader.ld
components/bootloader/subproject/main/bootloader_start.c
内部SRAM1可以存放指令和数据,同序访问:
指令空间384KB可读写:0x4038_0000~0x403D_FFFF,
数据空间384KB可读写:0x3FC8_0000 ~ 0x3FCD_FFFF.
二级引导程序打印信息:
I (44) boot: ESP-IDF v5.0-dev-346-g7af719e426-dirty 2nd stage bootloader
I (44) boot: compile time 10:14:41
I (44) boot: chip revision: 3
I (48) boot.esp32c3: SPI Speed : 80MHz
I (53) boot.esp32c3: SPI Mode : DIO
I (57) boot.esp32c3: SPI Flash Size : 2MB
I (62) boot: Enabling RNG early entropy source...
I (68) boot: Partition Table:
I (71) boot: ## Label Usage Type ST Offset Length
I (78) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (86) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (93) boot: 2 factory factory app 00 00 00010000 00100000
I (101) boot: End of partition table
I (105) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=06e60h ( 28256) map
I (118) esp_image: segment 1: paddr=00016e88 vaddr=3fc8a000 size=0144ch ( 5196) load
I (123) esp_image: segment 2: paddr=000182dc vaddr=40380000 size=07d3ch ( 32060) load
I (136) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=127e0h ( 75744) map
I (151) esp_image: segment 4: paddr=00032808 vaddr=40387d3c size=021c8h ( 8648) load
I (153) esp_image: segment 5: paddr=000349d8 vaddr=50000000 size=00010h ( 16) load
I (160) boot: Loaded app from partition at offset 0x10000
I (163) boot: Disabling RNG early entropy source...
I (379) cpu_start: Pro cpu up.
I (388) cpu_start: Pro cpu start user code
I (388) cpu_start: cpu freq: 160000000
I (388) cpu_start: Application information:
I (391) cpu_start: Project name: hello_world
I (396) cpu_start: App version: 1
I (400) cpu_start: Compile time: Nov 20 2021 10:14:28
I (406) cpu_start: ELF file SHA256: d04f3ff4f7c5b8a8...
I (412) cpu_start: ESP-IDF: v5.0-dev-346-g7af719e426-dirty
I (419) heap_init: Initializing. RAM available for dynamic allocation:
I (427) heap_init: At 3FC8C2B0 len 00033D50 (207 KiB): DRAM
I (433) heap_init: At 3FCC0000 len 0001F060 (124 KiB): STACK/DRAM
I (440) heap_init: At 50000010 len 00001FF0 (7 KiB): RTCRAM
I (446) spi_flash: detected chip: generic
I (451) spi_flash: flash io: dio
W (454) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (468) sleep: Configure to isolate all GPIO pins in sleep state
I (474) sleep: Enable automatic switching of GPIO sleep configuration
I (482) cpu_start: Starting scheduler.
主程序打印信息:
Hello world!=======world
This is esp32c3 chip with 1 CPU core(s), WiFi/BLE, silicon revision 3, 2MB external flash
Minimum free heap size: 329596 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds... (此处被telnet halt暂停)