Skip to content

Commit

Permalink
Bootloader: retained memory can now be kept after reboot when custom …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
o-marshmallow committed Nov 24, 2022
1 parent 3d1c15c commit 62ad5c2
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());
}

NOINLINE_ATTR 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 62ad5c2

Please sign in to comment.