ESP32启动流程(超级详细!!!)

一、概念介绍
1.1什么是单片机的启动流程

单片机的启动流程指的是单片机从上电或复位后到开始执行用户代码的一系列初始化步骤。不同的单片机的启动流程有其特定的细节,但大多数单片机的启动流程都遵循一个通用的模式。
通用启动流程:

  1. 上电或复位:当单片机接通电源或被复位时,启动流程开始。复位可以是软件触发的,也可以是通过复位引脚进行的硬件复位。
  2. 执行内置启动代码:单片机首先执行存储在内部 ROM 中的固件,这通常是由单片机制造商预先编程的。这段代码不可更改,称为启动加载程序或自举加载程序(Bootloader)。
  3. 硬件初始化:启动加载程序进行硬件初始化,包括设置时钟(例如晶振或内部RC振荡器)、配置电源管理、初始化内存控制器等。
  4. 检查启动模式:单片机可能会检查某些引脚或配置寄存器来确定启动模式,比如是否进入编程模式、正常启动还是其他特殊模式。
  5. 加载用户程序:在正常启动模式下,启动加载程序会从预设的内存位置(通常是内置或外部的非易失性存储器,如 Flash)加载用户程序的初始代码到 RAM 中。
  6. 跳转到主程序:一旦用户程序被加载,控制权被交给用户程序的入口点,通常是 main() 函数。在这一点上,用户程序开始执行。
  7. 用户程序执行:用户程序会根据设计执行初始化代码,比如设定外设、初始化变量、设置中断服务例程等,然后进入主循环或开始任务调度(如果使用了操作系统)。

二、ESP32启动流程概述
ESP32-DevKitC开发板:

ESP32-DevKitC引脚图:

 ESP32功能框图

宏观上,该启动流程可以分为如下 3 个步骤:

2.1 一级引导程序 (First Stage Bootloader)

  • 存储位置:一级引导程序被烧录在 ESP32 的内部只读存储器(ROM)中,所以它是不可更改的。
  • 主要职责:初始化硬件,比如配置时钟系统、电源管理和内存。

详解:
ESP32上电复位后的启动流程

1.首先是PRO CPU 激活:(ESP32 是一款双核的微控制器,分为 PRO CPU(通常为主 CPU)和 APP CPU)
在复位之后,PRO CPU 首先被激活,开始执行位于 ESP32 芯片掩膜 ROM 中的复位向量代码(复位向量代码是指在微控制器或其他类型的处理器中,在复位事件发生后首先执行的一段代码)
这个地址是 0x40000400,不可修改。
APP CPU 在这个阶段仍处于复位状态,不参与初始化过程。

2.执行复位向量代码:
复位向量代码首先会检查 GPIO_STRAP_REG 寄存器的值,该寄存器记录了复位时不同引脚的状态,用于确定 ESP32 的工作模式。

3.工作模式判定:
从深度睡眠模式复位:
系统检查 RTC_CNTL_STORE6_REG 和 RTC_CNTL_STORE7_REG 寄存器的值。
如果 RTC_CNTL_STORE6_REG 的值非零,并且 RTC_CNTL_STORE7_REG 的 CRC 校验有效,则跳转到 RTC_CNTL_STORE6_REG 指定的地址执行代码。

如果校验无效或 RTC_CNTL_STORE6_REG 为零,或者指定地址的代码执行完毕返回,则执行上电复位相关操作。

点击ESP32启动流程(超级详细!!!) - 古月居 可查看全文

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用ESP32底层库来编写OTA程序的代码: ```C #include <WiFi.h> #include <WiFiClient.h> #include <WiFiUdp.h> #include <ESPmDNS.h> #include <Update.h> const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; const char* ota_hostname = "ESP32-OTA"; // OTA主机名 void setup() { Serial.begin(115200); Serial.println("Booting..."); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } // 设置OTA主机名 if (MDNS.begin(ota_hostname)) { Serial.println("MDNS responder started"); } else { Serial.println("Error setting up MDNS responder"); } // 初始化OTA ArduinoOTA.onStart([]() { Serial.println("OTA Start"); }); ArduinoOTA.onEnd([]() { Serial.println("\nOTA End"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("OTA Error[%u]: ", error); if (error == OTA_AUTH_ERROR) { Serial.println("Auth Failed"); } else if (error == OTA_BEGIN_ERROR) { Serial.println("Begin Failed"); } else if (error == OTA_CONNECT_ERROR) { Serial.println("Connect Failed"); } else if (error == OTA_RECEIVE_ERROR) { Serial.println("Receive Failed"); } else if (error == OTA_END_ERROR) { Serial.println("End Failed"); } }); ArduinoOTA.begin(); Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } void loop() { ArduinoOTA.handle(); } ``` 这段程序使用了ESP32底层库来进行OTA升级,与之前的版本相比,主要有以下几点不同: 1. 引入了`ESPmDNS.h`库,用于设置OTA主机名; 2. 初始化OTA时,使用了lambda表达式来定义OTA开始、结束、进度和错误回调函数; 3. 在`setup()`函数中,先设置OTA主机名,再初始化OTA。 需要注意的是,使用ESP32底层库编写程序需要手动管理WiFi连接和OTA升级的过程,因此代码相对于高层库来说需要更多的细节处理。例如,在`setup()`函数中,需要手动设置OTA主机名和初始化OTA,并在`loop()`函数中处理OTA升级。 至此,以上就是使用ESP32底层库来编写OTA程序的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值