{"id":3542,"date":"2025-04-13T23:50:58","date_gmt":"2025-04-13T15:50:58","guid":{"rendered":"https:\/\/saludpcb.com\/zh\/?p=3542"},"modified":"2025-09-26T06:15:45","modified_gmt":"2025-09-25T22:15:45","slug":"esp32-bootloader-guide","status":"publish","type":"post","link":"https:\/\/saludpcb.com\/zh\/esp32-bootloader-guide\/","title":{"rendered":"\u89e3\u5bc6 ESP32 Bootloader\uff5c\u81ea\u8a02\u6d41\u7a0b\u548c\u8df3\u8f49\u908f\u8f2f\u5168\u5be6\u4f5c\uff01"},"content":{"rendered":"\n<hr class=\"wp-block-separator alignwide has-text-color has-palette-color-1-color has-alpha-channel-opacity has-palette-color-1-background-color has-background is-style-wide\"\/>\n\n\n\n<p>ESP32&nbsp;<strong>Bootloader<\/strong>\uff08\u5f15\u5c0e\u7a0b\u5e8f\uff09\u662f\u82af\u7247\u555f\u52d5\u6642\u904b\u884c\u7684\u7b2c\u4e00\u6bb5\u4ee3\u78bc\uff0c\u8ca0\u8cac\u521d\u59cb\u5316\u786c\u4ef6\u3001\u9a57\u8b49\u97cc\u9ad4\uff0c\u4e26\u6c7a\u5b9a\u5982\u4f55\u8f09\u5165\u61c9\u7528\u7a0b\u5e8f\u3002<br>\u9019\u7bc7\u6587\u7ae0\u5c07\u5e36\u4f60\u5f9e \u4e0a\u96fb\u958b\u59cb\uff0c\u4e00\u6b65\u6b65\u4e86\u89e3 Bootloader \u7684\u89d2\u8272\uff0c\u4e26\u7528\u5be6\u969b\u5c08\u6848\u793a\u7bc4\u5982\u4f55\u64b0\u5beb\u81ea\u5df1\u7684 ESP32 Bootloader\uff0c\u89c0\u5bdf\u5f9e ROM \u2192 Bootloader \u2192 App \u7684\u6574\u500b\u6d41\u7a0b\u3002<br>\u7121\u8ad6\u4f60\u662f\u958b\u767c OTA\u3001\u958b\u6a5f\u9078\u55ae\u3001\u6216\u60f3\u73a9\u9ede\u9032\u968e\u529f\u80fd\uff0c\u9019\u7bc7\u6559\u5b78\u90fd\u5c07\u662f\u4f60\u7406\u89e3\u300cESP32 \u555f\u52d5\u6a5f\u5236\u300d\u7684\u7b2c\u4e00\u6b65\u3002\u53ea\u9700\u5e7e\u5206\u9418\uff0c\u4f60\u5c07\u4e0d\u518d\u53ea\u6703\u7528 ESP32 Bootloader\uff0c\u800c\u662f\u771f\u7684\u7406\u89e3\u4e26\u80fd\u99d5\u99ad\u5b83\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/saludpcb.com\/zh\/wp-content\/uploads\/2025\/04\/Unlocking-the-ESP32-Bootloader-Full-Custom-Bootloader-Build.jpg\" alt=\"ESP32 Bootloader\" class=\"wp-image-3545\" title=\"\" srcset=\"https:\/\/saludpcb.com\/zh\/wp-content\/uploads\/2025\/04\/Unlocking-the-ESP32-Bootloader-Full-Custom-Bootloader-Build.jpg 1024w, https:\/\/saludpcb.com\/zh\/wp-content\/uploads\/2025\/04\/Unlocking-the-ESP32-Bootloader-Full-Custom-Bootloader-Build-768x768.jpg 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>\u5167\u5bb9<\/h2><nav><ul><li class=\"\"><a href=\"#\u4ec0\u9ebc\u662f-modbus\uff1f\">\u4ec0\u9ebc\u662f ESP32 Bootloader\uff1f<\/a><\/li><li class=\"\"><a href=\"#pwm-\u8207\u547c\u5438\u71c8\u539f\u7406\u5feb\u901f\u7406\u89e3\">ESP32 \u958b\u6a5f\u6d41\u7a0b\u5716<\/a><\/li><li class=\"\"><a href=\"#\u74b0\">\u958b\u767c\u74b0\u5883<\/a><\/li><li class=\"\"><a href=\"#\u5c08\u6848\u7d50\u69cb\">\u5c08\u6848\u7d50\u69cb<\/a><\/li><li class=\"\"><a href=\"#\u4f7f\u7528-esp-idf-\u64b0\u5beb\u547c\u5438\u71c8\u63a7\u5236\u7a0b\u5f0f\">\u7a0b\u5f0f\u78bc<\/a><\/li><li class=\"\"><a href=\"#\u7de8\u8b6f\u548c\u71d2\u9304\">\u7a0b\u5f0f\u78bc\u89e3\u8aaa<\/a><\/li><li class=\"\"><a href=\"#\u7de8\u8b6f\u548c\u71d2\u9304-1\">\u7de8\u8b6f\u548c\u71d2\u9304<\/a><\/li><li class=\"\"><a href=\"#\u7d50\u8ad6\">\u7d50\u8ad6<\/a><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u4ec0\u9ebc\u662f-modbus\uff1f\"><strong>\u4ec0\u9ebc\u662f ESP32<\/strong> <strong>Bootloader\uff1f<\/strong><\/h2>\n\n\n\n<p>Bootloader \u662f\u5d4c\u5165\u5f0f\u7cfb\u7d71\u555f\u52d5\u6642\u57f7\u884c\u7684&nbsp;<strong>\u4f4e\u968e\u7a0b\u5f0f<\/strong>\uff0c\u4e3b\u8981\u529f\u80fd\u5305\u62ec\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u521d\u59cb\u5316 CPU\u3001\u8a18\u61b6\u9ad4\u3001\u6642\u9418\u7b49\u786c\u4ef6<\/li>\n\n\n\n<li>\u5f9e Flash \u8f09\u5165\u61c9\u7528\u7a0b\u5f0f\uff08App\uff09<\/li>\n\n\n\n<li>\u9a57\u8b49\u97cc\u9ad4\u5b8c\u6574\u6027\uff08\u53ef\u9078\uff09<\/li>\n\n\n\n<li>\u63d0\u4f9b&nbsp;<strong>OTA\uff08\u7a7a\u4e2d\u5347\u7d1a\uff09<\/strong>&nbsp;\u652f\u63f4<\/li>\n<\/ul>\n\n\n\n<p>\u5728 ESP32 \u4e2d\uff0cBootloader \u901a\u5e38\u5b58\u653e\u5728&nbsp;<strong>Flash 0x1000 \u4f4d\u7f6e<\/strong>\uff0c\u4e26\u7531 ROM Code \u76f4\u63a5\u57f7\u884c\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pwm-\u8207\u547c\u5438\u71c8\u539f\u7406\u5feb\u901f\u7406\u89e3\">ESP32 \u958b\u6a5f\u6d41\u7a0b\u5716<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">    A[Power On \/ Reset] --&gt; B[Boot ROM (Factory Burned)]\n    B --&gt; C[Bootloader (Customizable)]\n    C --&gt; D[Load Application]\n    D --&gt; E[Run app_main()]<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Boot ROM \u662f\u6676\u7247\u5167\u5efa\u7684\uff0c\u8ca0\u8cac\u8f09\u5165 bootloader\u3002<\/li>\n\n\n\n<li>Bootloader \u662f\u4f60\u53ef\u4ee5\u7de8\u5beb\u548c\u81ea\u8a02\u7684\u968e\u6bb5\u3002<\/li>\n\n\n\n<li>\u6700\u5f8c\u624d\u6703\u8df3\u5230&nbsp;<code>main.c<\/code>&nbsp;\u4e2d\u7684&nbsp;<code>app_main()<\/code>\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u74b0\">\u958b\u767c\u74b0\u5883<\/h2>\n\n\n\n<p>\u5728\u958b\u59cb\u7de8\u7a0b\u4e4b\u524d\uff0c\u8acb\u78ba\u4fdd\u5df2\u5b8c\u6210\u4ee5\u4e0b\u6e96\u5099\u5de5\u4f5c\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/saludpcb.com\/zh\/esp32-tutorial-how-to-create-an-esp32-project-with-vscode\/\">\u5b89\u88dd ESP-IDF \u958b\u767c\u74b0\u5883<\/a> (\u81f3\u5c11\u7248\u672c v4.4 \u6216\u66f4\u9ad8)\u3002<\/li>\n\n\n\n<li><a href=\"https:\/\/saludpcb.com\/zh\/esp32-devkit-module-pinout\/\">ESP32 \u958b\u767c\u677f<\/a>\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u5c08\u6848\u7d50\u69cb\"><strong>\u5c08\u6848\u7d50\u69cb<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">esp32_boot_demo\/\n\u251c\u2500\u2500 CMakeLists.txt\n\u251c\u2500\u2500 main\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 CMakeLists.txt\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 main.c                 \/\/ User application\n\u251c\u2500\u2500 bootloader_components\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 main         \n\u2502&nbsp;&nbsp;     \u251c\u2500\u2500 CMakeLists.txt   \n\u2502&nbsp;&nbsp;     \u2514\u2500\u2500 bootloader_main.c  \/\/ Custom bootloader\n\u2514\u2500\u2500 README.md                  <\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u4f7f\u7528-esp-idf-\u64b0\u5beb\u547c\u5438\u71c8\u63a7\u5236\u7a0b\u5f0f\">\u7a0b\u5f0f\u78bc<\/h2>\n\n\n\n<p><strong>bootloader\/bootloader_main.c<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">#include &lt;stdbool.h&gt;\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"bootloader_init.h\"\n#include \"bootloader_utility.h\"\n#include \"bootloader_common.h\"\n\nstatic const char* TAG = \"boot\";\n\nstatic int select_partition_number(bootloader_state_t *bs);\n\n\/*\n * We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.\n * The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.\n * We do have a stack, so we can do the initialization in C.\n *\/\nvoid __attribute__((noreturn)) call_start_cpu0(void)\n{\n    \/\/ 1. Hardware initialization\n    if (bootloader_init() != ESP_OK) {\n        bootloader_reset();\n    }\n\n#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP\n    \/\/ If this boot is a wake up from the deep sleep then go to the short way,\n    \/\/ try to load the application which worked before deep sleep.\n    \/\/ It skips a lot of checks due to it was done before (while first boot).\n    bootloader_utility_load_boot_image_from_deep_sleep();\n    \/\/ If it is not successful try to load an application as usual.\n#endif\n\n    \/\/ 2. Select the number of boot partition\n    bootloader_state_t bs = {0};\n    int boot_index = select_partition_number(&amp;bs);\n    if (boot_index == INVALID_INDEX) {\n        bootloader_reset();\n    }\n\n    \/\/ 2.1 Print a custom message!\n    esp_rom_printf(\"[%s] %s\\n\", TAG, \"Custom Bootloader Welcome Message\");\n\n    \/\/ 3. Load the app image for booting\n    bootloader_utility_load_boot_image(&amp;bs, boot_index);\n}\n\n\/\/ Select the number of boot partition\nstatic int select_partition_number(bootloader_state_t *bs)\n{\n    \/\/ 1. Load partition table\n    if (!bootloader_utility_load_partition_table(bs)) {\n        ESP_LOGE(TAG, \"load partition table error!\");\n        return INVALID_INDEX;\n    }\n\n    \/\/ 2. Select the number of boot partition\n    return bootloader_utility_get_selected_boot_partition(bs);\n}\n\n\/\/ Return global reent struct if any newlib functions are linked to bootloader\nstruct _reent *__getreent(void)\n{\n    return _GLOBAL_REENT;\n}<\/code><\/pre>\n\n\n\n<p><strong>main\/main.c<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">#include &lt;stdio.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n\n\/\/ Entry point of the main application.\n\/\/ This is the function that runs after the bootloader hands over control.\nvoid app_main() {\n    \/\/ Print a message to indicate the app has started.\n    printf(\"=== Hello from app_main ===\\n\");\n\n    \/\/ Run an infinite loop with 1-second delay.\n    \/\/ This is a common pattern in embedded systems to keep the task alive.\n    while (1) {\n        vTaskDelay(1000 \/ portTICK_PERIOD_MS); \/\/ Delay for 1000 ms (1 second)\n    }\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6839\u76ee\u9304 CMakeLists.txt<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\"># esp32_boot_demo\/CMakeLists.txt\n\ncmake_minimum_required(VERSION 3.5)\n\ninclude($ENV{IDF_PATH}\/tools\/cmake\/project.cmake)\nproject(esp32_boot_demo)<\/code><\/pre>\n\n\n\n<p><strong><strong><code>main\/CMakeLists.txt<\/code><\/strong><\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">idf_component_register(\n    SRCS \"main.c\"\n    INCLUDE_DIRS \".\"\n)<\/code><\/pre>\n\n\n\n<p><strong><code>bootloader\/CMakeLists.txt<\/code><\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">idf_component_register(SRCS \"bootloader_main.c\"\n                    REQUIRES bootloader bootloader_support)\n\nidf_build_get_property(target IDF_TARGET)\n# Use the linker script files from the actual bootloader\nset(scripts \"${IDF_PATH}\/components\/bootloader\/subproject\/main\/ld\/${target}\/bootloader.ld\"\n            \"${IDF_PATH}\/components\/bootloader\/subproject\/main\/ld\/${target}\/bootloader.rom.ld\")\n\ntarget_linker_script(${COMPONENT_LIB} INTERFACE \"${scripts}\")<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u7de8\u8b6f\u548c\u71d2\u9304\">\u7a0b\u5f0f\u78bc\u89e3\u8aaa<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code><strong>bootloader_init()<\/strong><\/code><br>\u521d\u59cb\u5316\u786c\u9ad4\u57fa\u790e\u8a2d\u65bd\u3002<\/li>\n\n\n\n<li><code><strong>bootloader_utility_load_boot_image_from_deep_sleep()<\/strong><\/code><br>\u7528\u65bc\u6df1\u5ea6\u7761\u7720\u559a\u9192\u6642\u7684\u5feb\u901f\u555f\u52d5\uff0c\u8df3\u904e\u9a57\u8b49\u6b65\u9a5f\u4ee5\u52a0\u901f\u555f\u52d5\u3002<\/li>\n\n\n\n<li><code><strong>select_partition_number()<\/strong><\/code><br>\u89e3\u6790\u5206\u5340\u8868\u4e26\u6c7a\u5b9a\u8981\u555f\u52d5\u54ea\u500b\u5206\u5340\uff08\u4f8b\u5982&nbsp;<code>factory<\/code>&nbsp;\u6216&nbsp;<code>ota_0<\/code>\uff09\u3002<\/li>\n\n\n\n<li><code><strong>bootloader_utility_load_boot_image()<\/strong><\/code><br>\u6700\u7d42\u8f09\u5165\u61c9\u7528\u7a0b\u5f0f\u6620\u50cf\u6a94\uff0c\u4e26\u8df3\u8f49\u5230\u5176\u5165\u53e3\u5730\u5740\uff08\u901a\u5e38\u662f&nbsp;<code>0x10000<\/code>\uff09\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u7de8\u8b6f\u548c\u71d2\u9304-1\">\u7de8\u8b6f\u548c\u71d2\u9304<\/h2>\n\n\n\n<p>\u5b8c\u6210\u7a0b\u5f0f\u78bc\u5f8c\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 <a href=\"https:\/\/www.espressif.com\/en\/products\/sdks\/esp-idf\" target=\"_blank\" rel=\"noopener\">ESP-IDF<\/a> \u63d0\u4f9b\u7684\u547d\u4ee4\u9032\u884c\u7de8\u8b6f\u3001\u71d2\u9304\u548c\u76e3\u63a7\u3002<\/p>\n\n\n\n<p>\u5728 VS Code \u7684\u5de6\u4e0b\u89d2 ESP-IDF \u5de5\u5177\u5217\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9ede\u9078 <strong>Build project<\/strong><\/li>\n\n\n\n<li>\u9ede\u9078 <strong>Flash device<\/strong><\/li>\n\n\n\n<li>\u9ede\u9078 <strong>Monitor device<\/strong><\/li>\n<\/ul>\n\n\n\n<p>\u4f60\u5c31\u6703\u770b\u5230\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[boot] Custom Bootloader Welcome Message<code>=== Hello from app_main ===<\/code><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u7d50\u8ad6\">\u7d50\u8ad6<\/h2>\n\n\n\n<p>\u900f\u904e\u9019\u7bc7\u5be6\u4f5c\uff0c\u6211\u5011\u5b8c\u6574\u8d70\u4e86\u4e00\u904d ESP32 Bootloader \u7684\u555f\u52d5\u6d41\u7a0b\u3002\u5f9e\u4e0a\u96fb\u3001\u9032\u5165 Bootloader\u3001\u521d\u59cb\u5316\uff0c\u518d\u8df3\u8f49\u5230\u771f\u6b63\u7684\u61c9\u7528\u7a0b\u5f0f\u3002<br>\u4f60\u4e0d\u53ea\u662f\u770b\u61c2 ESP32 bootloader \u5728\u505a\u4ec0\u9ebc\uff0c\u66f4\u89aa\u624b\u5be6\u4f5c\u4e86\u81ea\u5df1\u7684\u6d41\u7a0b\u8207\u8df3\u8f49\u908f\u8f2f\u3002\u9019\u6a23\u7684\u80fd\u529b\uff0c\u5728 OTA \u66f4\u65b0\u3001\u5b89\u5168\u9a57\u8b49\u3001\u751a\u81f3\u591a\u7cfb\u7d71\u958b\u6a5f\u9078\u55ae\u8a2d\u8a08\u4e2d\uff0c\u90fd\u975e\u5e38\u5be6\u7528\u3002<br>\u4e86\u89e3 ESP32 bootloader\uff0c\u4e0d\u53ea\u662f\u9032\u968e\u958b\u767c\u8005\u7684\u5c08\u5229\uff0c\u800c\u662f\u6bcf\u500b ESP32 \u958b\u767c\u8005\u90fd\u8a72\u5177\u5099\u7684\u5e95\u5c64\u77e5\u8b58\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator alignwide has-text-color has-palette-color-1-color has-alpha-channel-opacity has-palette-color-1-background-color has-background is-style-wide\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>ESP32&nbsp;Bootloader\uff08\u5f15\u5c0e\u7a0b\u5e8f\uff09\u662f\u82af\u7247\u555f\u52d5\u6642\u904b\u884c\u7684\u7b2c\u4e00\u6bb5\u4ee3\u78bc\uff0c\u8ca0\u8cac\u521d\u59cb\u5316\u786c\u4ef6\u3001\u9a57\u8b49\u97cc\u9ad4\uff0c [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3545,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,53,83],"tags":[27,21,44,9,11],"class_list":["post-3542","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-module","category-esp32","category-featured","tag-c","tag-ide","tag-programming-language","tag-python","tag-tutorial"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts\/3542","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/comments?post=3542"}],"version-history":[{"count":6,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts\/3542\/revisions"}],"predecessor-version":[{"id":3550,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts\/3542\/revisions\/3550"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/media\/3545"}],"wp:attachment":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/media?parent=3542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/categories?post=3542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/tags?post=3542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}