Skip to content

Commit

Permalink
Merge pull request #2 from almir-okato/self_reflasher_v1
Browse files Browse the repository at this point in the history
Add self reflash using embedded binary example
  • Loading branch information
almir-okato authored Dec 4, 2024
2 parents 640f294 + e919fba commit e6c3d5a
Show file tree
Hide file tree
Showing 29 changed files with 850 additions and 84 deletions.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,18 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf

# default build directory name
build

# lock files
dependencies.lock

# VS Code Settings
.vscode/

# Example project files
examples/**/build/
examples/**/build_esp*_*/
examples/**/sdkconfig
examples/**/sdkconfig.old
9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
idf_component_register(SRCS "src/self_reflasher.c"
INCLUDE_DIRS "include"
REQUIRES esp_partition esp_http_client spi_flash
PRIV_REQUIRES log)
REQUIRES esp_partition
esp_http_client
spi_flash
PRIV_REQUIRES log
LDFRAGMENTS esp_self_reflasher.lf)

require_idf_targets(esp32 esp32s2 esp32s3 esp32c3 esp32c6 esp32h2)
3 changes: 0 additions & 3 deletions Kconfig
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
menu "ESP Self Reflasher"

endmenu
109 changes: 108 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,108 @@
# esp-self-reflasher
# esp-self-reflasher

`esp-self-reflasher` enables a project to do a full system reflash. As it involves risky flash operations, such as overwriting the bootloader region, that could brick the device, this needs to be use carefully.

There are two ways of operation:

- Download reflashing image;
- Embedded reflashing image.

For a example of each usage check the [examples](/examples) directory.

## Configuration constraints

It is mandatory that the following SPI Flash configuration is enabled:

- `SPI_FLASH_DANGEROUS_WRITE_ALLOWED` - "Writing to dangerous flash regions"

Otherwise the flash writing operations may not be effective depending on the destination addresses.

## WARNING

As mentioned above, the use of the `esp-self-reflasher` may involve risky flash operations that may brick the device if not correctly configured and planned beforehand by the user.

No NVS data, configuration, or other existing data in the destination flash region are transported neither kept. It is also on the user responsibility to handle it if needed.

## Download reflashing image

This mode downloads the **reflashing image** binary, thus expects a network connection and the HTTP endpoint to it.

`esp-self-reflasher` fetches from the system a valid OTA partition that does not conflict with the final destination neither the current execution partition, so the **reflashing image** can be staged into it.
After the download the reflash image can be copied to the final destination address.

Overall, the process can be described as following:

1. Firstly, the required configuration needs to be filled:
- Set a HTTP configuration (`esp_http_client_config_t`) with the target URL;
```c
esp_http_client_config_t http_config = {
.url = CONFIG_EXAMPLE_UPGRADE_URL,
.event_handler = _http_event_handler,
.buffer_size = BUFFER_SIZE, // HTTP buffer size
.buffer_size_tx = BUFFER_SIZE, // Transmission buffer size
.keep_alive_enable = true,
};
```
- Set the destination address and size (`addr_region_t`);
```c
addr_region_t example_region = {
.region_address = CONFIG_EXAMPLE_DEST_ADDRESS,
.region_size = CONFIG_EXAMPLE_DEST_MAX_SIZE,
};
```
- Set a `esp-self-reflasher` configuration (`esp_self_reflasher_config_t`) with the previous mentioned information;
```c
esp_self_reflasher_config_t self_reflasher_config = {
.http_config = &http_config,
.dest_region = example_region,
};
```
- Optionally, the target partition where the download will be placed can also be set into the `esp-self-reflasher` configuration;
2. `esp_self_reflasher_init` fetches a valid OTA partition if its not previously set, erases the partition found and sets the component handle with the configuration information;
```c
esp_self_reflasher_handle_t self_reflasher_handle = NULL;
esp_err_t err = esp_self_reflasher_init(&self_reflasher_config, &self_reflasher_handle);
```
3. `esp_self_reflasher_download_bin` initializes the HTTP client and starts the **reflashing image** download from the endpoint;
```c
err = esp_self_reflasher_download_bin(self_reflasher_handle);
```
4. `esp_self_reflasher_copy_to_region` erases the final destination flash region and copy the downloaded **reflashing image** to it;
```c
err = esp_self_reflasher_copy_to_region(self_reflasher_handle);
```

It is also possible to set and repeat the process for downloading other `reflashing images` to another destination:

5. Set a new HTTP configuration, a new destination address and a new `esp-self-reflasher` configuration (like step 1);
6. `esp_self_reflasher_upd_next_config` updates the configuration and the component handle;
```c
err = esp_self_reflasher_upd_next_config(&self_reflasher_new_config, self_reflasher_handle);
```
7. Repeat steps 3 and 4;

### Constraints

The reflash image size should fit into an existing partition.
The final destination address and size must not conflict with where the current code is executed from.

## Embedded reflashing image

In this way of operation, the target **reflashing image** is embedded to the application for direct copy to the destination (like a single shot execution), so it can pushed over any firmware update method, however as the binary load will increase the application size itself, the partition size constraints must be considered.

The example `boot_swap_embedded_example` can be checked for how to embedded the **reflashing image** binary data into the project.

The process can be described as following:

1. Required configuration needs to be filled:
- Set the source address from the embedded binary and size (`addr_region_t`), ensure that the address is an address from flash;
- Set the destination address and size (`addr_region_t`);
- Set a `esp-self-reflasher` configuration (`esp_self_reflasher_config_t`) with the previous mentioned information;
2. `esp_self_reflasher_directly_copy_to_region` erases the destination as it copies the **reflashing image** to it.
```c
err = esp_self_reflasher_directly_copy_to_region(&self_reflasher_config);
```

### Constraints

As mentioned, the binary load will increase the application size itself, so the target device's partition size must be observed.
39 changes: 39 additions & 0 deletions esp_self_reflasher.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[mapping:spi_flash_reflasher]
archive: libspi_flash.a
entries:
spi_flash_mmap (noflash)
esp_flash_api (noflash)
flash_mmap (noflash)
cache_utils (noflash)
flash_ops (noflash)
spi_flash_chip_generic (noflash)
spi_flash_chip_issi (noflash)
spi_flash_chip_mxic (noflash)
spi_flash_chip_gd (noflash)
spi_flash_chip_winbond (noflash)
spi_flash_chip_boya (noflash)
spi_flash_chip_th (noflash)
memspi_host_driver (noflash)
flash_brownout_hook (noflash)
spi_flash_wrap (noflash)

[mapping:esp_mm_reflasher]
archive: libesp_mm.a
entries:
* (noflash)

[mapping:esp_rom_reflasher]
archive: libesp_rom.a
entries:
* (noflash)

[mapping:esp_system_reflasher]
archive: libesp_system.a
entries:
esp_system:esp_restart (noflash)

[mapping:esp_self_reflasher]
archive: libesp-self-reflasher.a
entries:
* (noflash)
self_reflasher:esp_self_reflasher_get_running_partition (default)
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS ../.. $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ota_reflash)
project(boot_swap_download)
Loading

0 comments on commit e6c3d5a

Please sign in to comment.