[SOLVED] Boot Different Partition from Application
-
- Posts: 76
- Joined: Tue May 29, 2018 8:00 pm
[SOLVED] Boot Different Partition from Application
In my product, we have modified 2nd Stage Bootloader to always boot Factory. Then, the Factory image will wait a few seconds for a reset signal over network, then looks at otadata to decide which image to boot (or to stay in factory). --- The reason for this is, we want a way to recover from a bad firmware remotely --- this product does not have any user-accessible GPIOs.
I intend to use esp_ota_get_boot_partition() and then esp_image_verify(), but the missing piece is, I don't know an ESP API to boot a specified OTA image from application context.
I'm looking for something similar to the booloader_support functions bootloader_utility_load_boot_image() or load_image() which can be called from the full application.
I could try to pull pieces of bootloader_support into my application to get those functions working, but I expect to run into trouble given FreeRTOS running and other configuration that ESP-IDF performs.
Please advise.
I intend to use esp_ota_get_boot_partition() and then esp_image_verify(), but the missing piece is, I don't know an ESP API to boot a specified OTA image from application context.
I'm looking for something similar to the booloader_support functions bootloader_utility_load_boot_image() or load_image() which can be called from the full application.
I could try to pull pieces of bootloader_support into my application to get those functions working, but I expect to run into trouble given FreeRTOS running and other configuration that ESP-IDF performs.
Please advise.
Last edited by chrismerck on Wed Oct 24, 2018 4:01 pm, edited 1 time in total.
Re: Boot Different Partition from Application
Code: Select all
esp_ota_set_boot_partition
Re: Boot Different Partition from Application
Storing a pointer to the desired partition in RTC memory and rebooting to let the bootloader load that partition is probably going to be the easiest way.
Indeed loading new application from a running application may be complex, as you need to make sure that the code that does the loading, stack, and any .data/.bss that the loading code needs do not overlap with the application being loaded. In bootloader this is achieved by using a special linker script. It places the .text section of the code needed to do the loading operation into the space normally used by APP CPU instruction cache. In your factory application this is probably going to be harder to achieve...
Indeed loading new application from a running application may be complex, as you need to make sure that the code that does the loading, stack, and any .data/.bss that the loading code needs do not overlap with the application being loaded. In bootloader this is achieved by using a special linker script. It places the .text section of the code needed to do the loading operation into the space normally used by APP CPU instruction cache. In your factory application this is probably going to be harder to achieve...
Re: Boot Different Partition from Application
But, If we set firmware location partitiona into partition tables then can't it be easily manage using get boot firmware partition and set boot firmware partition APIs?ESP_igrr wrote:Storing a pointer to the desired partition in RTC memory and rebooting to let the bootloader load that partition is probably going to be the easiest way.
Indeed loading new application from a running application may be complex, as you need to make sure that the code that does the loading, stack, and any .data/.bss that the loading code needs do not overlap with the application being loaded. In bootloader this is achieved by using a special linker script. It places the .text section of the code needed to do the loading operation into the space normally used by APP CPU instruction cache. In your factory application this is probably going to be harder to achieve...
I think most of application developer are using OTA component to do that type of portion.
Regards,
Ritesh Prajapati
Ritesh Prajapati
-
- Posts: 76
- Joined: Tue May 29, 2018 8:00 pm
Re: Boot Different Partition from Application
Thanks! We will give that a try. Should be easy to accomplish with one if-statement in a customized bootloader.ESP_igrr wrote:Storing a pointer to the desired partition in RTC memory and rebooting to let the bootloader load that partition is probably going to be the easiest way.
-
- Posts: 76
- Joined: Tue May 29, 2018 8:00 pm
Re: Boot Different Partition from Application
Here's the solution we ended up using:
1. create a header file called xesp_rtc_defs.h which is shared between a custom bootloader component and our app. I've pasted the whole contents at the end of this post.
2. Use deepsleep instead of reboot from app, to preserve RTC mem.
3. When we want to use the OTA data partition, our app does XESP_RTC_ARM_REC(XESP_RTC_REC_USE_OTA) before deepsleep.
4. Bootloader checks XESP_RTC_IS_ARMED(XESP_RTC_REC_USE_OTA). If false, then it overrides boot_index, setting to -1 to cause factory to be forced.
5. Crucially, bootloader does XESP_RTC_SPEND_REC(XESP_RTC_REC_USE_OTA) before booting app, so that the USE_OTA signal is only obeyed once.
---
Header:
1. create a header file called xesp_rtc_defs.h which is shared between a custom bootloader component and our app. I've pasted the whole contents at the end of this post.
2. Use deepsleep instead of reboot from app, to preserve RTC mem.
3. When we want to use the OTA data partition, our app does XESP_RTC_ARM_REC(XESP_RTC_REC_USE_OTA) before deepsleep.
4. Bootloader checks XESP_RTC_IS_ARMED(XESP_RTC_REC_USE_OTA). If false, then it overrides boot_index, setting to -1 to cause factory to be forced.
5. Crucially, bootloader does XESP_RTC_SPEND_REC(XESP_RTC_REC_USE_OTA) before booting app, so that the USE_OTA signal is only obeyed once.
---
Header:
Code: Select all
#pragma once
#include <stdint.h>
#include <inttypes.h>
/********
* RTC Slow Memory Allocation
********/
/*
* We use RTC slow memory, one 32-bit word at a time,
* starting at the end of the 8kB region,
* because if we ever want to run a ULP program,
* it will need to be in the beginning of this region.
*/
/** signal to bootloader to obey otadata partition */
#define XESP_RTC_REC_USE_OTA 0x50001FFC
/********
* RTC Slow Memory Constants
********/
/** load this value into a record to arm it */
#define XESP_RTC_REC_CONST_ARMED 0x1BADBABE
/** set this value in a record after it has been spent */
#define XESP_RTC_REC_CONST_SPENT 0x2BADBABE
/********
* Macros
********/
#define XESP_RTC_READ_REC(rec) (*((uint32_t*)(rec)))
#define XESP_RTC_IS_ARMED(rec) (XESP_RTC_READ_REC(rec) == XESP_RTC_REC_CONST_ARMED)
#define XESP_RTC_ARM_REC(rec) (*((uint32_t*)(rec))=XESP_RTC_REC_CONST_ARMED)
#define XESP_RTC_SPEND_REC(rec) (*((uint32_t*)(rec))=XESP_RTC_REC_CONST_SPENT)
Re: [SOLVED] Boot Different Partition from Application
Hi
I'm thinking about using a similar approach to define from which partition the device should boot.
Those two defines are arbitrary values you decided to use ?
#define XESP_RTC_REC_CONST_ARMED 0x1BADBABE
#define XESP_RTC_REC_CONST_SPENT 0x2BADBABE
Would it be possible to share the code that handles those booting approach from your custom bootloader (I guess you override the espressif bootloader), as well as the code from your factory app and main app ?
Thanks
Jerome
I'm thinking about using a similar approach to define from which partition the device should boot.
Those two defines are arbitrary values you decided to use ?
#define XESP_RTC_REC_CONST_ARMED 0x1BADBABE
#define XESP_RTC_REC_CONST_SPENT 0x2BADBABE
Would it be possible to share the code that handles those booting approach from your custom bootloader (I guess you override the espressif bootloader), as well as the code from your factory app and main app ?
Thanks
Jerome
-
- Posts: 76
- Joined: Tue May 29, 2018 8:00 pm
Re: [SOLVED] Boot Different Partition from Application
Hi Jerome,
So I'm late, but better late than never?
Values to avoid are 0x0, 0xFFFFFFFF, 0xCCCCCCCC, and 0x55555555, since those may be default conditions.
The 1/2BADBABE is chosen because it is immediately recognizable on a terminal as pseudo-english.
Yes, we override the bootloader component.
We modify bootloader_start.c to read from RTC and then manipulate `boot_index` variable to -1 if we want to force booting from factory image, rather than OTA.
So I'm late, but better late than never?
Yes, they are essentially arbitrary.Those two defines are arbitrary values you decided to use ?
Values to avoid are 0x0, 0xFFFFFFFF, 0xCCCCCCCC, and 0x55555555, since those may be default conditions.
The 1/2BADBABE is chosen because it is immediately recognizable on a terminal as pseudo-english.
It's a closed-source project, but I can share some pointers.the code that handles those booting approach from your custom bootloader
Yes, we override the bootloader component.
We modify bootloader_start.c to read from RTC and then manipulate `boot_index` variable to -1 if we want to force booting from factory image, rather than OTA.
the code from your factory app
Code: Select all
void Osal_Reboot()
{
SysUser("Rebooting NOW!");
Osal_Sleep_Ms(100);
/* Leave the RTC slow memory powered during deep sleep.
Without this, we get corruption and a bootloop */
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
/* We do not use esp_restart() because that would cause RTC mem to be init */
/* WARNING: ESP-IDF docs warn that we should shutdown WiFi + BLE prior to
calling esp_deep_sleep. However, we are not doing that... */
esp_deep_sleep(1000 /* 1 ms */);
/* never reaches here */
while (1); /* just in case */
}
Re: [SOLVED] Boot Different Partition from Application
Hello Team,
We have faced one critical issue in which we are using only esp_ota_get_boot_partition to make sure from where application is started and updating OTA image into another location.
it is working fine into happy case where there won;t be any issue into any of partition.
But if any bootable partition has issue and image is not able to boot at that time application firmware is started from another location but bootable partition is still set as older location. Due to that when we are going to update firmware through OTA at that time firmware is going to flash into same location where application is running.
So, I have one alternative solution to use esp_ota_get_running_partition partition to make sure from where application firmware is running and set OTA Firmware Update partition accordingly. We are checking like due to that my problem will be resolved or not.
I will post reply over here once it will be validated and tested from my end.
We have faced one critical issue in which we are using only esp_ota_get_boot_partition to make sure from where application is started and updating OTA image into another location.
it is working fine into happy case where there won;t be any issue into any of partition.
But if any bootable partition has issue and image is not able to boot at that time application firmware is started from another location but bootable partition is still set as older location. Due to that when we are going to update firmware through OTA at that time firmware is going to flash into same location where application is running.
So, I have one alternative solution to use esp_ota_get_running_partition partition to make sure from where application firmware is running and set OTA Firmware Update partition accordingly. We are checking like due to that my problem will be resolved or not.
I will post reply over here once it will be validated and tested from my end.
Regards,
Ritesh Prajapati
Ritesh Prajapati
Re: [SOLVED] Boot Different Partition from Application
Hello All,
We have used esp_ota_get_running_partition instead of esp_ota_get_boot_partition to make sure from where application is started and updating OTA image into another location
So, We are able to update firmware into respective partition if application is started from default boot partition or OTA_0 partition irrespective of boot partition.
We have used esp_ota_get_running_partition instead of esp_ota_get_boot_partition to make sure from where application is started and updating OTA image into another location
So, We are able to update firmware into respective partition if application is started from default boot partition or OTA_0 partition irrespective of boot partition.
Regards,
Ritesh Prajapati
Ritesh Prajapati
Who is online
Users browsing this forum: No registered users and 55 guests