Skip to content

Ota commands in flash #6538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
91c95a5
WIP: Flash-stored OTA commands
davisonja Jan 4, 2017
e97e1e7
Basic merge and update of `boards.txt.py`, untested!!
davisonja Sep 20, 2019
9d598f2
Missed some brackets and forgot to finish a line!
davisonja Sep 20, 2019
9733d42
Tweak values and move OTA commands to the end of sketch space (which …
davisonja Sep 20, 2019
c850515
Result of running `python3 tools/boards.txt.py --allgen`
davisonja Sep 20, 2019
f3d01a2
Cleaned up some things that had leaked in from testing
davisonja Sep 20, 2019
8f1a74c
Added constant `APP_START_OFFSET` which was missed out of the transfer
davisonja Sep 21, 2019
32f1539
Add includes
davisonja Sep 24, 2019
923b2d7
CI Cleanup
davisonja Sep 25, 2019
8205f17
CI Cleanups
davisonja Sep 25, 2019
16127c2
CI Cleanups
davisonja Sep 25, 2019
ce6a824
Merge remote-tracking branch 'upstream/master' into ota_commands_in_f…
davisonja Sep 29, 2019
a931150
Regenerated the files
davisonja Sep 29, 2019
1339018
switched out the cast
davisonja Sep 29, 2019
68245ac
Adjusted values to be addresses not offsets and fixed up references
davisonja Sep 30, 2019
fa00e1e
Tweak tests
davisonja Oct 2, 2019
abe0f39
Merge remote-tracking branch 'upstream/master' into ota_commands_in_f…
davisonja Oct 2, 2019
44ce1f7
Added some conditions around the debug output of eboot, which are def…
davisonja Oct 3, 2019
217a9c5
Merge branch 'master' into ota_commands_in_flash
davisonja Oct 3, 2019
9377af5
Merge branch 'master' into ota_commands_in_flash
davisonja Oct 4, 2019
38b267f
Merge branch 'master' into ota_commands_in_flash
davisonja Oct 10, 2019
e67ebc5
Merge branch 'master' into ota_commands_in_flash
davisonja Nov 17, 2019
9e78b6d
Merge remote-tracking branch 'upstream/master' into ota_commands_in_f…
davisonja Nov 20, 2019
0692c61
:facepalm: moment as the previous merge of master was faulty.
davisonja Nov 20, 2019
3ebeb26
Merge branch 'master' into ota_commands_in_flash
davisonja Sep 10, 2020
d616d90
Merge branch 'master' into ota_commands_in_flash
davisonja Sep 10, 2020
4d64292
Merge branch 'master' into ota_commands_in_flash
davisonja Oct 16, 2020
7762f5d
Merge remote-tracking branch 'upstream/master' into ota_commands_in_f…
davisonja Dec 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bootloaders/eboot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ OBJDUMP := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-objdump

INC += -I../../tools/sdk/include -I../../tools/sdk/uzlib/src

CFLAGS += -std=gnu99
CFLAGS += -std=gnu99 -DEBOOT_ENABLE_FLASH_STORAGE

CFLAGS += -Os -fcommon -g -Wall -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals -ffunction-sections -fdata-sections -free -fipa-pta

Expand Down
47 changes: 47 additions & 0 deletions bootloaders/eboot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
eboot Bootloader
================


A simple bootloader which can copy an OTA update to main application address in flash and load the application code to IRAM.

# Contents
- [Startup sequence](#startup-sequence)


### Startup sequence ###

On startup the ESP ROM will [load and start the firmware image](#load-and-start) from flash location 0x0 - eboot.

##### eboot will #####
1. print a version string from the current firmware image
2. [attempt to read a command](#read-eboot-command)
1. execute command (if found)
2. on completion of the command, mark it complete
3. [load and start the application](#load-and-start)



### Read eboot command ###

Historically eboot commands were stored in RTC RAM. In an effort to survive a power-outage mid-update (which will claer the RTC RAM) there is now provision for storing the commands in Flash. If no valid command is found in the flash storage (or flash storage is disabled) eboot will try RTC RAM.

Commands are considered valid if the checksum is correct.

```C
typedef struct eboot_command {
uint32_t magic;
enum action_t action;
uint32_t args[29];
uint32_t crc32;
} eboot_command_t;
```


### Load and start ###

The firmware images are expected to have ELF headers indicating what location each section should be loaded into - which is relevant for the RAM locations.

Both the ESP bootloader and eboot will work through the image sections copying the contents of the appropriate ones into their address.

Finally execution jumps to the entry-point specified in the image header.

93 changes: 91 additions & 2 deletions bootloaders/eboot/eboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,69 @@ int print_version(const uint32_t flash_addr)
return 0;
}

#if defined (EBOOT_ENABLE_SERIAL_DEBUG)
int print_flags(const uint32_t flash_addr)
{
const char* __attribute__ ((aligned (4))) fmtt = "#%08x\n\0\0";
uint32_t ver, i;
uint32_t fmt[2];
eboot_flash_command_t cmd;
fmt[0] = ((uint32_t*) fmtt)[0];
fmt[1] = ((uint32_t*) fmtt)[1];
ver = commandAddress();
ets_putc('<');
ets_printf((const char*) fmt, ver);
ets_putc('\n');
for (i = 0; i < EBOOT_COMMAND_MAX_COUNT; i++) {
ets_putc('0' + i);
ets_putc(':');
readBootCommand(i, &cmd);
ets_printf((const char*) fmt, cmd.flags);
}
ets_putc('D');
ets_putc('o');
ets_putc('n');
ets_putc('e');
ets_putc('!');
ets_putc('\n');
return 0;
}
#else
#define print_flags(X) {}
#endif

int find_app_start(const uint32_t flash_addr)
{
image_header_t image_header;
uint32_t pos = flash_addr;
uint8_t count = 0;

do {
pos += APP_START_OFFSET;
if (SPIRead(pos, &image_header, sizeof(image_header))) {
return 0;
}
count += 1;
} while ((image_header.magic != 0xe9) && (count < 4));
return pos;
}

int load_app_from_flash_raw(const uint32_t flash_addr)
{
image_header_t image_header;
uint32_t pos = flash_addr + APP_START_OFFSET;
uint32_t pos = find_app_start(flash_addr);
const char* __attribute__ ((aligned (4))) fmtt = "l:%08x\n\0";
uint32_t ver, i;
uint32_t fmt[2];
fmt[0] = ((uint32_t*) fmtt)[0];
fmt[1] = ((uint32_t*) fmtt)[1];

if (SPIRead(pos, &image_header, sizeof(image_header))) {
ets_printf((const char*) fmt, pos);
if (SPIRead(pos, &image_header, sizeof(image_header))) {
return 1;
}
pos += sizeof(image_header);
ets_printf((const char*) fmt, pos);


for (uint32_t section_index = 0;
Expand All @@ -62,6 +116,15 @@ int load_app_from_flash_raw(const uint32_t flash_addr)

const uint32_t address = section_header.address;

#if defined (EBOOT_ENABLE_SERIAL_DEBUG)
ets_putc('f');
ets_printf((const char*) fmt, pos);
ets_putc('t');
ets_printf((const char*) fmt, address);
ets_putc('s');
ets_printf((const char*) fmt, section_header.size);
#endif

bool load = false;

if (address < 0x40000000) {
Expand All @@ -83,8 +146,18 @@ int load_app_from_flash_raw(const uint32_t flash_addr)
continue;
}

#if defined (EBOOT_ENABLE_SERIAL_DEBUG)
ets_putc('l');
ets_putc('o');
#endif

if (SPIRead(pos, (void*)address, section_header.size))
return 3;
#if defined (EBOOT_ENABLE_SERIAL_DEBUG)
ets_putc('a');
ets_putc('d');
ets_putc('\n');
#endif

pos += section_header.size;
}
Expand Down Expand Up @@ -123,6 +196,20 @@ int copy_raw(const uint32_t src_addr,
const uint32_t size,
const bool verify)
{
const char* __attribute__ ((aligned (4))) fmtt = ":%08x\n\0\0";
uint32_t fmt[2];
fmt[0] = ((uint32_t*) fmtt)[0];
fmt[1] = ((uint32_t*) fmtt)[1];

#if defined (EBOOT_ENABLE_SERIAL_DEBUG)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move the ifdef before the variables (otherwise this may generate a warning if DEBUG is off)

ets_putc('S');
ets_printf((const char*) fmt, src_addr);
ets_putc('D');
ets_printf((const char*) fmt, dst_addr);
ets_putc('B');
ets_printf((const char*) fmt, size);
#endif

// require regions to be aligned
if ((src_addr & 0xfff) != 0 ||
(dst_addr & 0xfff) != 0) {
Expand Down Expand Up @@ -223,6 +310,7 @@ int main()
struct eboot_command cmd;

print_version(0);
print_flags(0);

if (eboot_command_read(&cmd) == 0) {
// valid command was passed via RTC_MEM
Expand Down Expand Up @@ -264,6 +352,7 @@ int main()
ets_printf((const char *)&cp);
#endif
if (res == 0) {
eboot_command_clear();
cmd.action = ACTION_LOAD_APP;
cmd.args[0] = cmd.args[1];
}
Expand Down
Loading