espressif / ESP8266_RTOS_SDK

Latest ESP8266 SDK based on FreeRTOS, esp-idf style.
http://bbs.espressif.com
Apache License 2.0
3.33k stars 1.56k forks source link

512K app size causes incorrect OTA running and next-update partitions (GIT8266O-511) #933

Open flameboss opened 4 years ago

flameboss commented 4 years ago

Environment

Problem Description

I will attach a simple program that simply switches boot partition to other ota partition when the user enters a u on the console.

This program works OK when I use the default OTA partitions generated by make menuconfig, in which ota_1 starts at 0x110000. However, since I need to save flash space for a user partition, on a 2MB flash, I made my custom partition table have ota_1 start at 0x90000, allowing 512K for each app.

Expected Behavior

When running in ota_1, app should output on console:

Boot partition: label ota_1, offset x90000, len x80000 Running partition: label ota_1, offset x90000, len x80000 Next update partition: label ota_0, offset x10000, len x80000

Actual Behavior

When running in ota_1, app does output on console (including boot loader messages which prove it is booting from ota_1 at 0x90000):

... I (271) boot: Loaded app from partition at offset 0x90000 ... Boot partition: label ota_1, offset x90000, len x80000 Running partition: label ota_0, offset x10000, len x80000 Next update partition: label ota_1, offset x90000, len x80000

Note: the first line is correct, but the 2nd two lines are not correct.

Steps to repropduce

  1. make a new project with the attached user_main.c and partitions.csv and sdkconfig
  2. make
  3. make flash
  4. make app2
  5. make app2-flash
  6. while app is running from ota_0 see expected output: Boot partition: label ota_0, offset x10000, len x80000 Running partition: label ota_0, offset x10000, len x80000 Next update partition: label ota_1, offset x90000, len x80000
  7. press 'u' on the console reset to boot from ota_1
  8. observe output from app running on ota_1

Code to reproduce this issue

static void print_partitions()
{   
    const esp_partition_t *p;

    p = esp_ota_get_boot_partition(); 
    printf("Boot partition: label %s, offset x%x, len x%x\n", p->label, p->address, p->size);

    p = esp_ota_get_running_partition();
    printf("Running  partition: label %s, offset x%x, len x%x\n", p->label, p->address, p->size);

    p = esp_ota_get_next_update_partition(NULL);
    printf("Next update partition: label %s, offset x%x, len x%x\n", p->label, p->address, p->size);
    next_update_partition = p;
}
# Name,   Type, SubType, Offset,   Size
# old boot loader              0x0,  0x1000
# new boot loader           0x1000,  0x4000
# Partition table           0x8000,  0x1000
nvs,       data, nvs,       0x9000,  0x4000
otadata,   data, ota,       0xd000,  0x2000
phy_init,  data, phy,       0xf000,  0x1000
ota_0,     app,  ota_0,    0x10000, 0x80000
ota_1,     app,  ota_1,    0x90000, 0x80000
fb_data,   0x40, ,        0x110000, 0xf0000

Full files attached.

Debug Logs

All console output from failing app on ota_1:

 ets Jan  8 2013,rst cause:1, boot mode:(3,7)

load 0x40100000, len 7168, room 16 
tail 0
chksum 0xe0
load 0x3ffe8408, len 24, room 8 
tail 0
chksum 0x69
load 0x3ffe8420, len 3544, room 8 
tail 0
chksum 0x11
csum 0x11
I (46) boot: ESP-IDF v3.3-14-gb6634dcd 2nd stage bootloader
I (46) boot: compile time 13:40:23
I (47) qio_mode: Enabling default flash chip QIO
I (54) boot: SPI Speed      : 40MHz
I (60) boot: SPI Mode       : QIO
I (66) boot: SPI Flash Size : 2MB
I (72) boot: Partition Table:
I (78) boot: ## Label            Usage          Type ST Offset   Length
I (89) boot:  0 nvs              WiFi data        01 02 00009000 00004000
I (101) boot:  1 otadata          OTA data         01 00 0000d000 00002000
I (112) boot:  2 phy_init         RF data          01 01 0000f000 00001000
I (124) boot:  3 ota_0            OTA app          00 10 00010000 00080000
I (135) boot:  4 ota_1            OTA app          00 11 00090000 00080000
I (147) boot:  5 fb_data          unknown          40 00 00110000 000f0000
I (159) boot: End of partition table
I (165) esp_image: segment 0: paddr=0x00090010 vaddr=0x40210010 size=0x222fc (140028) map
I (225) esp_image: segment 1: paddr=0x000b2314 vaddr=0x4023230c size=0x050fc ( 20732) map
I (233) esp_image: segment 2: paddr=0x000b7418 vaddr=0x3ffe8000 size=0x00548 (  1352) load
I (237) esp_image: segment 3: paddr=0x000b7968 vaddr=0x40100000 size=0x008c0 (  2240) load
I (250) esp_image: segment 4: paddr=0x000b8230 vaddr=0x401008c0 size=0x055b8 ( 21944) load
I (271) boot: Loaded app from partition at offset 0x90000
I (288) system_api: Base MAC address is not set, read default base MAC address from EFUSE
I (291) system_api: Base MAC address is not set, read default base MAC address from EFUSE
phy_version: 1163.0, 665d56c, Jun 24 2020, 10:00:08, RTOS new
I (360) phy_init: phy ver: 1163_0
I (362) reset_reason: RTC reset 1 wakeup 0 store 3, reason is 3
SDK version: v3.3-14-gb6634dcd
Boot partition: label ota_1, offset x90000, len x80000
Running  partition: label ota_0, offset x10000, len x80000
Next update partition: label ota_1, offset x90000, len x80000
u - change boot partition

Other items if possible

sdkconfig.txt

user_main.c.txt

flameboss commented 4 years ago

I have a work-around which does not use esp_ota_get_next_update_partition().

static const esp_partition_t *find_partition(char *label)
{
    const esp_partition_t *p;
    esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP,
                                                     ESP_PARTITION_SUBTYPE_ANY,
                                                     NULL);
    while (it != NULL) {
        p = esp_partition_get(it);
        if (strcmp(p->label, label) == 0) {
            esp_partition_iterator_release(it);
            return p;
        }
        it = esp_partition_next(it);
    }
    return NULL;
}

... 

    const esp_partition_t *p;

    p = esp_ota_get_boot_partition();
    printf("Boot partition: label %s, offset x%x, len x%x\n", p->label, p->address, p->size);

    char *label = strcmp(p->label, "ota_0") == 0 ? "ota_1" : "ota_0";
    p = find_partition(label);
    next_update_partition = p;

Whole file attached. user_main.c.txt

flameboss commented 4 years ago

The other work around was to configure partitions so that start of ota_1 is exactly 1M after start of ota_0. If that is a requirement it would be nice to enforce it at build time instead of just crashing.

nsfilho commented 4 years ago

I passed by the same problem. I reconfigured my partition tables to get the same as you probably wold. You can take a look at https://github.com/nsfilho/E12AIO3 -- where you can see my partition table.

Best regards,