Skip to content

Commit e603f4e

Browse files
author
Konstantin Kondrashov
committed
Merge branch 'feature/bootloader_ota' into 'master'
feat(bootloader): Supports recovery bootloader Closes IDF-7780 and IDF-7779 See merge request espressif/esp-idf!31893
2 parents 7eb7108 + 3a7c1a2 commit e603f4e

37 files changed

+1023
-384
lines changed

components/app_update/test_apps/test_app_update/.build-test-rules.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@ components/app_update/test_apps:
77
- if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_XIP_SUPPORTED == 1
88
# S2 doesn't have ROM for flash
99
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and (SOC_SPIRAM_XIP_SUPPORTED == 1 and IDF_TARGET != "esp32s2")
10+
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1
1011
disable:
1112
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
1213
temporary: true
1314
reason: not supported yet # TODO: [ESP32H21] IDF-11515, [ESP32H4] IDF-12279
1415
- if: IDF_TARGET == "esp32c61" and CONFIG_NAME == "xip_psram_with_rom_impl"
1516
temporary: true
1617
reason: not supported yet # TODO: [ESP32C61] IDF-12784
18+
disable_test:
19+
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1 and IDF_TARGET == "esp32c61"
20+
temporary: true
21+
reason: lack of runners # TODO: [ESP32C61] IDF-13165
Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
idf_component_register(SRC_DIRS "."
2-
PRIV_INCLUDE_DIRS "."
3-
PRIV_REQUIRES cmock test_utils app_update bootloader_support nvs_flash driver spi_flash esp_psram
4-
WHOLE_ARCHIVE)
1+
idf_component_register(
2+
SRC_DIRS "."
3+
PRIV_INCLUDE_DIRS "."
4+
PRIV_REQUIRES
5+
cmock
6+
test_utils
7+
app_update
8+
bootloader_support
9+
nvs_flash
10+
driver
11+
spi_flash
12+
esp_psram
13+
efuse
14+
WHOLE_ARCHIVE
15+
)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/*
7+
* Tests bootloader update.
8+
*/
9+
10+
#include "unity.h"
11+
#include "esp_log.h"
12+
#include "esp_efuse.h"
13+
#include "esp_flash_internal.h"
14+
#include "esp_rom_sys.h"
15+
#include "utils_update.h"
16+
#include "sdkconfig.h"
17+
18+
#define BOOT_COUNT_NAMESPACE "boot_count"
19+
20+
static __attribute__((unused)) const char *TAG = "btldr_update";
21+
22+
#if CONFIG_BOOTLOADER_RECOVERY_ENABLE
23+
24+
/* @brief Checks and prepares the partition so that the factory app is launched after that.
25+
*/
26+
static void start_test(void)
27+
{
28+
ESP_LOGI(TAG, "boot count 1 - reset");
29+
set_boot_count_in_nvs(1);
30+
erase_ota_data();
31+
ESP_LOGI(TAG, "ota_data erased");
32+
ESP_LOGI(TAG, "Bootloader offset: 0x%x", esp_rom_get_bootloader_offset());
33+
reboot_as_deep_sleep();
34+
}
35+
36+
static void test_flow1(void)
37+
{
38+
uint8_t boot_count = get_boot_count_from_nvs();
39+
boot_count++;
40+
set_boot_count_in_nvs(boot_count);
41+
ESP_LOGI(TAG, "boot count %d", boot_count);
42+
43+
ESP_LOGI(TAG, "Bootloader offset: 0x%x", esp_rom_get_bootloader_offset());
44+
45+
const esp_partition_t *primary_bootloader;
46+
TEST_ESP_OK(esp_partition_register_external(NULL, ESP_PRIMARY_BOOTLOADER_OFFSET, ESP_BOOTLOADER_SIZE, "PrimaryBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_PRIMARY, &primary_bootloader));
47+
const esp_partition_t *recovery_bootloader;
48+
TEST_ESP_OK(esp_partition_register_external(NULL, CONFIG_BOOTLOADER_RECOVERY_OFFSET, ESP_BOOTLOADER_SIZE, "RecoveryBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_RECOVERY, &recovery_bootloader));
49+
ESP_LOGI(TAG, "Bootloaders are registered");
50+
51+
// Remove write protection for the bootloader
52+
esp_flash_set_dangerous_write_protection(esp_flash_default_chip, false);
53+
switch (boot_count) {
54+
case 2:
55+
TEST_ASSERT_EQUAL_HEX32(ESP_PRIMARY_BOOTLOADER_OFFSET, esp_rom_get_bootloader_offset());
56+
57+
TEST_ESP_OK(esp_partition_erase_range(recovery_bootloader, 0, recovery_bootloader->size));
58+
ESP_LOGI(TAG, "Erase recovery bootloader");
59+
60+
TEST_ESP_OK(esp_efuse_set_recovery_bootloader_offset(CONFIG_BOOTLOADER_RECOVERY_OFFSET));
61+
62+
ESP_LOGI(TAG, "Backup, copy <%s> -> <%s>", primary_bootloader->label, recovery_bootloader->label);
63+
TEST_ESP_OK(esp_partition_copy(recovery_bootloader, 0, primary_bootloader, 0, primary_bootloader->size));
64+
65+
TEST_ESP_OK(esp_partition_erase_range(primary_bootloader, 0, primary_bootloader->size));
66+
ESP_LOGI(TAG, "Erase primary bootloader");
67+
reboot_as_deep_sleep();
68+
break;
69+
case 3:
70+
TEST_ASSERT_EQUAL_HEX32(CONFIG_BOOTLOADER_RECOVERY_OFFSET, esp_rom_get_bootloader_offset());
71+
72+
ESP_LOGI(TAG, "Return to primary bootloader...");
73+
ESP_LOGI(TAG, "Copy <%s> -> <%s>", recovery_bootloader->label, primary_bootloader->label);
74+
TEST_ESP_OK(esp_partition_copy(primary_bootloader, 0, recovery_bootloader, 0, primary_bootloader->size));
75+
76+
TEST_ESP_OK(esp_partition_erase_range(recovery_bootloader, 0, recovery_bootloader->size));
77+
ESP_LOGI(TAG, "Erase recovery bootloader");
78+
break;
79+
default:
80+
TEST_FAIL_MESSAGE("Unexpected stage");
81+
break;
82+
}
83+
}
84+
85+
TEST_CASE_MULTIPLE_STAGES("Recovery bootloader feature", "[recovery_bootloader][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1);
86+
87+
#endif // CONFIG_BOOTLOADER_RECOVERY_ENABLE

0 commit comments

Comments
 (0)