Skip to content

Commit

Permalink
Merge branch 'bugfix/rtc_retain_mem_always_erased' into 'master'
Browse files Browse the repository at this point in the history
Bootloader: retained memory can now be kept after reboot when custom data enabled

See merge request espressif/esp-idf!19809
  • Loading branch information
o-marshmallow committed Sep 1, 2022
2 parents 7b2c491 + 26c4550 commit 779d880
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 3 deletions.
1 change: 0 additions & 1 deletion components/bootloader/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,6 @@ menu "Bootloader config"

config BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE
hex "Size in bytes for custom purposes"
range 0 0x10
default 0
depends on BOOTLOADER_CUSTOM_RESERVE_RTC
help
Expand Down
7 changes: 7 additions & 0 deletions components/bootloader_support/.build-test-rules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps

components/bootloader_support/test_apps/rtc_custom_section:
disable:
- if: IDF_TARGET == "esp32c2"
temporary: false
reason: esp32c2 does not have RTC memory
6 changes: 6 additions & 0 deletions components/bootloader_support/include/esp_image_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,14 @@ typedef struct {
uint32_t crc; /*!< Check sum crc32 */
} rtc_retain_mem_t;


_Static_assert(offsetof(rtc_retain_mem_t, crc) == sizeof(rtc_retain_mem_t) - sizeof(uint32_t), "CRC field must be the last field of rtc_retain_mem_t structure");

#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
_Static_assert(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
/* The custom field must be the penultimate field */
_Static_assert(offsetof(rtc_retain_mem_t, custom) == sizeof(rtc_retain_mem_t) - sizeof(uint32_t) - CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE,
"custom field in rtc_retain_mem_t structure must be the field before the CRC one");
#endif

#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
Expand Down
17 changes: 15 additions & 2 deletions components/bootloader_support/src/bootloader_common_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,

#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t))

_Static_assert(RTC_RETAIN_MEM_ADDR >= SOC_RTC_DRAM_LOW, "rtc_retain_mem_t structure size is bigger than the RTC memory size. Consider reducing RTC reserved memory size.");

rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR;

#ifndef BOOTLOADER_BUILD
Expand All @@ -128,14 +130,25 @@ rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR
SOC_RESERVE_MEMORY_REGION(RTC_RETAIN_MEM_ADDR, RTC_RETAIN_MEM_ADDR + sizeof(rtc_retain_mem_t), rtc_retain_mem);
#endif

static uint32_t rtc_retain_mem_size(void) {
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
/* A custom memory has been reserved by the user, do not consider this memory into CRC calculation as it may change without
* the have the user updating the CRC. Return the offset of the custom field, which is equivalent to size of the structure
* minus the size of everything after (including) `custom` */
return offsetof(rtc_retain_mem_t, custom);
#else
return sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc);
#endif
}

static bool check_rtc_retain_mem(void)
{
return esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc)) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX;
return esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, rtc_retain_mem_size()) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX;
}

static void update_rtc_retain_mem_crc(void)
{
rtc_retain_mem->crc = esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc));
rtc_retain_mem->crc = esp_rom_crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, rtc_retain_mem_size());
}

void bootloader_common_reset_rtc_retain_mem(void)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(test_rtc_custom_section)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "test_main.c"
INCLUDE_DIRS ".")
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "bootloader_common.h"
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define TEST_MAGIC_VALUE 0x42987561

extern rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void);

void app_main(void) {
rtc_retain_mem_t* mem = bootloader_common_get_rtc_retain_mem();
uint32_t* _rtc_vars = (uint32_t*) mem->custom;

if (_rtc_vars[0] != TEST_MAGIC_VALUE) {
/* On the first boot, set the data inside the array */
_rtc_vars[0] = TEST_MAGIC_VALUE;
} else {
/* Second boot, the data was saved saved, success */
printf("SUCCESS: data were saved across reboot\n");
vTaskDelay(10000 / portTICK_PERIOD_MS);
}

esp_restart();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0

import pytest
from pytest_embedded import Dut


@pytest.mark.generic
@pytest.mark.esp32
@pytest.mark.esp32c3
@pytest.mark.esp32s2
@pytest.mark.esp32s3
def test_rtc_reserved_memory(dut: Dut) -> None:
dut.expect_exact('SUCCESS: data were saved across reboot', timeout=10)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0x10
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC=y
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE=0x200

0 comments on commit 779d880

Please sign in to comment.