OTA of micropython code on ESP32?

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
happyday
Posts: 14
Joined: Sat Jan 21, 2017 12:11 pm

OTA of micropython code on ESP32?

Post by happyday » Thu Oct 10, 2019 4:04 pm

I am exploring "the best" way to do OTA of my micropython code that runs on an ESP32. Do you have any recommendations?

Thank you.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: OTA of micropython code on ESP32?

Post by jimmo » Wed Oct 16, 2019 4:47 am

Do you want to update the Python code or the actual firmware?

If it's the Python code, I'm not sure there's a "best" way...probably this is much more a question of how your application protocol works -- actually updating the files on the flash is pretty straightforward. You might definitely want to consider some sort of "safe mode" though -- i.e. never modify main.py, and ensure that main.py has enough logic to download new firmware.

User avatar
nebenzahl
Posts: 26
Joined: Mon Jul 01, 2019 5:38 pm
Location: Uruguaiana, Brazil
Contact:

Re: OTA of micropython code on ESP32?

Post by nebenzahl » Mon Dec 16, 2019 7:51 pm

Hi!
Would you have any code that would download files from an FTP server?
I've been studying this for a long time and I can't move forward.

Thank
Eng. Luiz Nebenzahl


User avatar
nebenzahl
Posts: 26
Joined: Mon Jul 01, 2019 5:38 pm
Location: Uruguaiana, Brazil
Contact:

Re: OTA of micropython code on ESP32?

Post by nebenzahl » Mon Dec 16, 2019 8:36 pm

Thanks, I saw this post.
However this is not what I am looking for, because there are file updates, downloading on github, also making an esp32 be an FTP server.
But what I only want is my ESP32 to download files from an FTP server on the internet, that's all.
That simple.
Does anyone have an example?
Eng. Luiz Nebenzahl

BjHave
Posts: 5
Joined: Fri Aug 09, 2019 12:32 pm

Re: OTA of micropython code on ESP32?

Post by BjHave » Fri Jan 24, 2020 1:57 pm

I'm also looking for an OTA update. There is some progress there, but not yet documented.

So far I managed to create a OTA supporting partition table.

Create your own board spec in the boards folder inside ports/esp32.

Like "GENERIC_OTA" for example.
Copy the mpconfigboard.h and the mpconfigboard.mk from another board e.g. GENERIC or add them to you folder.

In the mpconfigboard.h you could change the BoardName.

In the mpconfigboard.mk you could add a reference to your partition.csv (You can find an example in the GENERIC_D2WD/mpconfigboard.mk

Mine is looking like this:
SDKCONFIG += boards/sdkconfig.base
PART_SRC = partitions-ota.csv
FLASH_SIZE = 4MB
FLASH_MODE = dio
FLASH_FREQ = 40m

My partitions-ota.csv file resides in the ports/esp32 folder and looks like this:
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000,
Mini_0, app, ota_0, , 1536K
Mini_1, app, ota_1, , 1536K,
vfs, data, fat, , 768K

I build my firmware with some modules so i needed some more space than 1MB the missing offsets are getting filled by esp partition tool.

That's all I've got so far.

On the first boot the partition table gets created. With :
from esp32 import Partition
you can access the different partitions as objects.
More on this here:
https://github.com/micropython/micropython/pull/4910

I'm struggling at the moment on how to get another firmware to the Mini_1 partition via download or copy. I'm fairly new to MCUs and (Micro)Python...

Once you managed to get the data to the other partition you can select it with the use of the Partition class and call part.set_boot() to mark this as active partition for the next boot.

If you or somebody else knows how to get the data to the other partition, please let me know.
Last edited by BjHave on Fri Jan 31, 2020 8:20 am, edited 1 time in total.

BjHave
Posts: 5
Joined: Fri Aug 09, 2019 12:32 pm

Re: OTA of micropython code on ESP32?

Post by BjHave » Fri Jan 31, 2020 8:01 am

It was pretty straight forward to implement a PartitionCopy Method. I don't know if it is Pythonic ;) but I will share it:

Code: Select all


from esp32 import Partition
import gc

class Ota:
  
  SEC_SIZE = 4096
  
  def copyPartition(self):
    currentPartition = Partition(Partition.RUNNING)
    nextPartition = currentPartition.get_next_update()
    buf = bytearray(self.SEC_SIZE)
    for i in range(0, currentPartition.info()[3] // self.SEC_SIZE):
      currentPartition.readblocks(i, buf)
      nextPartition.writeblocks(i, buf)
      print('Block No. ' + str(i) + ' copied')
      gc.collect()
    print('Partition copied')
    nextPartition.set_boot()
    
    

rikvermeer
Posts: 3
Joined: Fri Oct 15, 2021 6:14 pm

Re: OTA of micropython code on ESP32?

Post by rikvermeer » Fri Oct 15, 2021 6:23 pm

@BjHave

Thanks for the forumpost with the OTA python code, this is one of the few examples that got me going.
When I call nextPartition.set_boot I'm not changing to ota_1 though.
First I ran your code, copying the content of currentPartition to nextPartion.

Code: Select all

from esp32 import Partition
currentPartition = Partition(Partition.RUNNING)
nextPartition = currentPartition.get_next_update()
nextPartition.set_boot()
When checking after boot, the ota_0 is still selected for boot.
Enable app rollback support is disabled.
Am I missing something?

Regards,
Rik

bulletmark
Posts: 59
Joined: Mon Mar 29, 2021 1:36 am
Location: Brisbane Australia

Re: OTA of micropython code on ESP32?

Post by bulletmark » Fri Oct 15, 2021 11:22 pm

@rikvermeer, are you doing a:

Code: Select all

Partition.mark_app_valid_cancel_rollback()
after boot of the new partition?

rikvermeer
Posts: 3
Joined: Fri Oct 15, 2021 6:14 pm

Re: OTA of micropython code on ESP32?

Post by rikvermeer » Sun Oct 31, 2021 5:50 pm

I found that config parameter as well and found that it was turned on automatically when building an OTA board.

However, it seemed that I got better results with calling it on the classmethod.

Code: Select all

Partition.set_boot(nextPartition)
I could be mistaking here, but non the less, the latter worked for me.

Post Reply