]> granicus.if.org Git - esp-idf/commitdiff
bootloader: API for the fast wakeup and custom using RTC mem
authorKonstantinKondrashov <konstantin@espressif.com>
Fri, 5 Jul 2019 10:18:58 +0000 (18:18 +0800)
committerbot <bot@espressif.com>
Wed, 21 Aug 2019 11:44:37 +0000 (11:44 +0000)
Added "Reserve RTC FAST memory for custom purposes" option.
Added a boot counter.

components/bootloader/Kconfig.projbuild
components/bootloader/subproject/main/bootloader_start.c
components/bootloader_support/include/bootloader_common.h
components/bootloader_support/include/esp_image_format.h
components/bootloader_support/include_bootloader/bootloader_utility.h
components/bootloader_support/src/bootloader_common.c
components/bootloader_support/src/bootloader_utility.c
components/esp32/ld/esp32.ld

index ba08b72385ddedcec597f054510bdd089540da38..2d4a050919429c0731c0cb1314a34718c0e8a2bf 100644 (file)
@@ -235,7 +235,7 @@ menu "Bootloader config"
 
     config BOOTLOADER_RESERVE_RTC_SIZE
         hex
-        default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
+        default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP || BOOTLOADER_CUSTOM_RESERVE_RTC
         default 0
         help
             Reserve RTC FAST memory for Skip image validation. This option in bytes.
@@ -244,6 +244,28 @@ menu "Bootloader config"
             When a wakeup occurs (from Deep sleep), the bootloader retrieves it and
             loads the application without validation.
 
+    config BOOTLOADER_CUSTOM_RESERVE_RTC
+        bool "Reserve RTC FAST memory for custom purposes"
+        default n
+        help
+            This option allows the customer to place data in the RTC FAST memory,
+            this area remains valid when rebooted, except for power loss.
+            This memory is located at a fixed address and is available
+            for both the bootloader and the application.
+            (The application and bootoloader must be compiled with the same option).
+            The RTC FAST memory has access only through PRO_CPU.
+
+    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
+            This option reserves in RTC FAST memory the area for custom purposes.
+            If you want to create your own bootloader and save more information
+            in this area of memory, you can increase it. It must be a multiple of 4 bytes.
+            This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
+
 endmenu  # Bootloader
 
 
index e9bd32d8817c33d2fbdd8618e5798461767a1afe..f93fa5694b4aea832572e83b4dd9fa8c355e22bb 100644 (file)
@@ -41,6 +41,14 @@ void __attribute__((noreturn)) call_start_cpu0(void)
         bootloader_reset();
     }
 
+#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
+    // If this boot is a wake up from the deep sleep then go to the short way,
+    // try to load the application which worked before deep sleep.
+    // It skips a lot of checks due to it was done before (while first boot).
+    bootloader_utility_load_boot_image_from_deep_sleep();
+    // If it is not successful try to load an application as usual.
+#endif
+
     // 2. Select the number of boot partition
     bootloader_state_t bs = { 0 };
     int boot_index = select_partition_number(&bs);
index 4b887f55f967961f6621e400d962ced65722af94..1058b20cc5be5e5392af2b2260318cdf9ec968b0 100644 (file)
@@ -146,6 +146,68 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
  */
 void bootloader_common_vddsdio_configure(void);
 
+#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
+/**
+ * @brief Returns partition from rtc_retain_mem
+ *
+ * Uses to get the partition of application which was worked before to go to the deep sleep.
+ * This partition was stored in rtc_retain_mem.
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ *       Make sure that this function is used only PRO_CPU.
+ *
+ * @return partition: If rtc_retain_mem is valid.
+ *        - NULL: If it is not valid.
+ */
+esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void);
+
+/**
+ * @brief Update the partition and reboot_counter in rtc_retain_mem.
+ *
+ * This function saves the partition of application for fast booting from the deep sleep.
+ * An algorithm uses this partition to avoid reading the otadata and does not validate an image.
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ *       Make sure that this function is used only PRO_CPU.
+ *
+ * @param[in] partition      App partition description. Can be NULL, in this case rtc_retain_mem.partition is not updated.
+ * @param[in] reboot_counter If true then update reboot_counter.
+ *
+ */
+void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter);
+
+/**
+ * @brief Reset entire rtc_retain_mem.
+ *
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ *       Make sure that this function is used only PRO_CPU.
+ */
+void bootloader_common_reset_rtc_retain_mem(void);
+
+/**
+ * @brief Returns reboot_counter from rtc_retain_mem
+ *
+ * The reboot_counter counts the number of reboots. Reset only when power is off.
+ * The very first launch of the application will be from 1.
+ * Overflow is not possible, it will stop at the value UINT16_MAX.
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ *       Make sure that this function is used only PRO_CPU.
+ *
+ * @return reboot_counter: 1..65535
+ *         - 0: If rtc_retain_mem is not valid.
+ */
+uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void);
+
+/**
+ * @brief Returns rtc_retain_mem
+ *
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ *       Make sure that this function is used only PRO_CPU.
+ *
+ * @return rtc_retain_mem
+ */
+rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void);
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 09d4bda3da239a9656939dbaa1e2dc17d6f70058..4e656a17b644d5200e413a6b1fb657cab8bff971 100644 (file)
@@ -51,6 +51,34 @@ typedef enum {
 #endif
 } esp_image_load_mode_t;
 
+typedef struct {
+    esp_partition_pos_t partition;  /*!< Partition of application which worked before goes to the deep sleep. */
+    uint16_t reboot_counter;        /*!< Reboot counter. Reset only when power is off. */
+    uint16_t reserve;               /*!< Reserve */
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+    uint8_t custom[CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE]; /*!< Reserve for custom propose */
+#endif
+    uint32_t crc;                   /*!< Check sum crc32 */
+} rtc_retain_mem_t;
+
+#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");
+#endif
+
+#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
+_Static_assert(CONFIG_BOOTLOADER_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
+#endif
+
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
+#endif
+
+#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
+_Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved RTC area must exceed size of rtc_retain_mem_t");
+#endif
+
 /**
  * @brief Verify and (optionally, in bootloader mode) load an app image.
  *
index 84d0cb48f3680220b76449cd6e977fbd25a46f92..4f31f5acbc6321ad07be017d8446598256ca2c9c 100644 (file)
@@ -54,6 +54,16 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
  */
 __attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index);
 
+#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
+/**
+ * @brief Load that application which was worked before we go to the deep sleep.
+ *
+ * Checks the reboot reason if it is the deep sleep and has a valid partition in the RTC memory
+ * then try to load the application which was worked before we go to the deep sleep.
+ *
+ */
+void bootloader_utility_load_boot_image_from_deep_sleep(void);
+#endif
 
 /**
  * @brief Software reset the ESP32
index a10fb2f2aced6856bbfd10ad917b70966f407c13..acc7644ea3288b252010bb16ba106c792252b317 100644 (file)
@@ -270,3 +270,66 @@ void bootloader_common_vddsdio_configure(void)
     }
 #endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
 }
+
+
+#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
+
+rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
+
+static bool check_rtc_retain_mem(void)
+{
+    return 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;
+}
+
+static void update_rtc_retain_mem_crc(void)
+{
+    rtc_retain_mem->crc = crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc));
+}
+
+void bootloader_common_reset_rtc_retain_mem(void)
+{
+    memset(rtc_retain_mem, 0, sizeof(rtc_retain_mem_t));
+}
+
+uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void)
+{
+    if (check_rtc_retain_mem()) {
+        return rtc_retain_mem->reboot_counter;
+    }
+    return 0;
+}
+
+esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void)
+{
+    if (check_rtc_retain_mem()) {
+        return &rtc_retain_mem->partition;
+    }
+    return NULL;
+}
+
+void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter)
+{
+    if (reboot_counter) {
+        if (!check_rtc_retain_mem()) {
+            bootloader_common_reset_rtc_retain_mem();
+        }
+        if (++rtc_retain_mem->reboot_counter == 0) {
+            // do not allow to overflow. Stop it.
+            --rtc_retain_mem->reboot_counter;
+        }
+
+    }
+
+    if (partition != NULL) {
+        rtc_retain_mem->partition.offset = partition->offset;
+        rtc_retain_mem->partition.size   = partition->size;
+    }
+
+    update_rtc_retain_mem_crc();
+}
+
+rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
+{
+    return rtc_retain_mem;
+}
+#endif
\ No newline at end of file
index 7d5f67ac7e123e04dd97b02a30bb5058500bcb98..b9d76ed9bc86e7fb37e391e958e792e099e09631 100644 (file)
@@ -417,7 +417,7 @@ static void set_actual_ota_seq(const bootloader_state_t *bs, int index)
         update_anti_rollback(&bs->ota[index]);
 #endif
     }
-#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP )
+#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
     esp_partition_pos_t partition = index_to_partition(bs, index);
     bootloader_common_update_rtc_retain_mem(&partition, true);
 #endif
index 514b9ebd820a2019a8e33011c286ecce410408eb..a52b56f90db51420ffd016ebcc094e67d5bf8871 100644 (file)
@@ -21,7 +21,9 @@
 #define CONFIG_BT_RESERVE_DRAM 0
 #endif
 
-#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
 #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
 #else
 #define ESP_BOOTLOADER_RESERVE_RTC 0