Bootloader: retained memory can now be kept after reboot when custom data enabled

User's custom data are not taken into account during the CRC calculation anymore.
Which means taht the retained mem structure is not systematically erased
on each reboot anymore.
This commit is contained in:
Omar Chebib 2022-08-26 19:40:06 +08:00
parent 3d1c15cd94
commit 62ad5c2258
10 changed files with 86 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
@ -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());
}
NOINLINE_ATTR void bootloader_common_reset_rtc_retain_mem(void)

View File

@ -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)

View File

@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "test_main.c"
INCLUDE_DIRS ".")

View File

@ -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();
}

View File

@ -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)

View File

@ -0,0 +1,3 @@
CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0x10
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC=y
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE=0x200