Uploading to ota_0 instead of factory partition

I’m trying to upload the program to an esp32 devkitv1 and I get the following issue (on the esp32s it works correctly).

When I press the upload button in vscode the firmware is uploaded to the wrong partition. Because the bootstrap points to the factory partition, the app doesn’t starts.
Prior to upload I did a flash erase.

This is my custom partition table

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x19000,  0x5000,
otadata,  data, ota,     0x1E000,  0x2000,
factory,  app,  factory, 0x20000, 0x100000,
app0,     app,  ota_0,   0x120000, 0x150000,
app1,     app,  ota_1,   0x270000, 0x150000,
spiffs,   data, spiffs,  0x3C0000, 0x40000,

And this is the command displayed in the console:

platformio.exe run --target upload

and this the point that it says it’s writing to ota0 (0x120000) instead that factory (0x20000)

Wrote 764096 bytes (471615 compressed) at 0x00120000 in 11.0 seconds (effective 554.5 kbit/s)...

If I flash it to the right position with the “Flash Download Tools” by EspressIf, it starts to work

If you add

board_upload.offset_address = 0x20000

what address does it flash to now?

Sadly I get the same result:

Wrote 764240 bytes (471706 compressed) at 0x00120000 in 11.0 seconds (effective 554.7 kbit/s)...

this is my platformio.ini now:

platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.3/platform-espressif32-v.2.0.3.zip
board = esp32dev
framework = arduino, espidf
monitor_speed = 115200
lib_deps = 
monitor_filters = esp32_exception_decoder
board_build.partitions = partitions_custom.csv
board_upload.offset_address = 0x20000

As you can see I use a custom platform to use idf with arduino, I don’t know it this mean anything with the issue

For the life of me I can’t figure out where it gets the address for the firmware.bin… All I see in here is that maximum size computtatin, which takes the biggests “app” type partition. And due to your factory partition being size 0x100000 but the app0 and app1 partitions being bigger, it will assume the bigger size as the program size. This itself smells like a bug.

Just for testing, what happens when all app partitions are of equal size? I.e, use

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x19000,  0x5000,
otadata,  data, ota,     0x1E000,  0x2000,
factory,  app,  factory, 0x20000,  0x100000,
app0,     app,  ota_0,   0x120000, 0x100000,
app1,     app,  ota_1,   0x220000, 0x100000,
spiffs,   data, spiffs,  0x320000, 0x40000,

as your partition table?

Still the same :frowning_face:

Wrote 764240 bytes (471706 compressed) at 0x00120000 in 11.0 seconds (effective 554.4 kbit/s)...

I set a smaller size for factory partition, so I can reserve more for future developements

What’s the platformio.ini for reference?

This one as I posted before. Or am I misunderstood your question?

My bad I overlooked it.

The current latest official platform should also give you the ability to do ESP-IDF + Arduino with the 2.0.3 core. Does it compile with platform = espressif32? Does it fail the upload the same way?

This is a great news! But still get the same issue:

Wrote 764240 bytes (471705 compressed) at 0x00120000 in 11.0 seconds (effective 555.0 kbit/s)...

it’s a byte smaller, though :smile:

I’ve activated the boot logs and I see the following:

D (259) boot: Trying partition index -1 offs 0x20000 size 0x100000
D (265) esp_image: reading image header @ 0x20000
D (270) bootloader_flash: mmu set block paddr=0x00020000 (was 0xffffffff)
D (277) esp_image: image header: 0xff 0xff 0xff 0x0f ffffffff
E (283) esp_image: image at 0x20000 has invalid magic byte (nothing flashed here?)
E (291) boot: Factory app partition is not bootable
D (297) boot: Trying partition index 0 offs 0x120000 size 0x100000
D (303) esp_image: reading image header @ 0x120000
D (308) bootloader_flash: mmu set block paddr=0x00120000 (was 0x00020000)
D (315) esp_image: image header: 0xe9 0x06 0x02 0x02 40082094

And the app starts correctly… It’s not exactly what I expected, but now I starts, at least.

And with your original partition table and no board_upload.offset_address, it still uploads incorrectly, right? If yes, please open an issue at Issues · platformio/platform-espressif32 · GitHub so this can be resolved by the developers.

Yes it still, thanks for help.
I’ve better checked that it happen also with the devkitS
for future reference, this is the opened issue:

Max you are right. There is no code in Platformio to support a factory image. It is even worse, the firmware address is hardcoded to 0x10000. I did a probably not 100% working change (PR is open) to solve this. After this change we are now able to flash a factory image and the main firmware to a different address than 0x10000.
We use this as default for Tasmota (since v12).

Hi. Has this PR been merged? I’m trying to do a similar thing, and platform seems to ignore my partition .csv file and always write to 0x10000.

I’m using 0x10000 for now, but I would really like to be able to write directly to where the apps should go, since I then use another project to write my eta code to a separate partition.

Also, I noticed something that I don’t know if it is me or a bug. When I have my .csv stating:

Name, Type, SubType, Offset, Size, Flags

nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x80000,
spiffs, data, spiffs, 0x90000, 0x10000,

I see this during build:

Flash will be erased from 0x00010000 to 0x00070fff…

Shouldn’t the last address be 0x7ffff and not 0x70fff ?

No, not merged. Became stale and was auto closed.

Do you happen to know if there are workarounds or shall it be reopened?

Also, any thoughts on my second issue? Just change my last sentence to:

Shouldn’t the last address be 0x8ffff and not 0x70fff ?

Here’s what I am trying to do, in case there is a workaround.

I want to be able to put one app at one location and a second app at another. The use case is that I want a small single-use app that only does OTA firmware updates. call that app1. And I have my main app that does everything else, and that is app0. If the user needs to update, they go through some steps to get the main app to set the app1 as the app to boot up into and restarts the device. app1 gets control, finds the update, downloads it to app0’s location and then restarts with app0 active.

Why not just have app0 do the update and download the new app0 into a secondary spot? Because my firmware is too large to be able to have two copies of it on the device at the same time. By splitting up the OTA code from the rest, I can have a small OTA app partition, and leave the rest of the space for downloading the new firmware.

We do exactly this what you describe in Project Tasmota.
To do this we forked Platformio espressif32 and using a platformio (python) script and our own boards manifests. Works perfect.