Skip to content

Pico 2 W OTA Update Example #559

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

Merged
merged 19 commits into from
Jul 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ App|Description
[picow_http_client](pico_w/wifi/http_client) | Demonstrates how to make http and https requests
[picow_http_client_verify](pico_w/wifi/http_client) | Demonstrates how to make a https request with server authentication
[picow_mqtt_client](pico_w/wifi/mqtt) | Demonstrates how to implement a MQTT client application
[picow_ota_update](pico_w/wifi/ota_update) | A minimal OTA update server (RP235x Only). See the separate [README](pico_w/wifi/ota_update/README.md) for more details.

#### FreeRTOS examples

Expand Down
6 changes: 4 additions & 2 deletions pico_w/wifi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ else()
add_subdirectory_exclude_platforms(http_client)
add_subdirectory_exclude_platforms(mqtt)

if (NOT PICO_MBEDTLS_PATH)
message("Skipping tls examples as PICO_MBEDTLS_PATH is not defined")
if (NOT TARGET pico_mbedtls)
message("Skipping tls_client and ota_update examples as Mbed TLS is not available")
else()
add_subdirectory_exclude_platforms(tls_client)
# note ota_update doesn't use Mbed TLS, but it requires picotool with Mbed TLS, so the above check is a good proxy
add_subdirectory_exclude_platforms(ota_update rp2040)
endif()
endif()
33 changes: 33 additions & 0 deletions pico_w/wifi/ota_update/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
add_executable(picow_ota_update
picow_ota_update.c
)
target_compile_definitions(picow_ota_update PRIVATE
WIFI_SSID=\"${WIFI_SSID}\"
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
PICO_CRT0_IMAGE_TYPE_TBYB=1
)
target_include_directories(picow_ota_update PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
)
target_link_libraries(picow_ota_update
pico_cyw43_arch_lwip_threadsafe_background
pico_stdlib
pico_sha256
boot_uf2_headers
)

pico_use_wifi_firmware_partition(picow_ota_update)

pico_hash_binary(picow_ota_update)
pico_sign_binary(picow_ota_update ${CMAKE_CURRENT_LIST_DIR}/private.pem)

# By default this example requires a partition table in flash, and will
# update the partition that is not currently in use. To use it without
# a partition table in flash, uncomment the following lines to make it
# a no_flash binary, so it can update the currently running program.

# pico_set_binary_type(picow_ota_update no_flash)
# pico_package_uf2_output(picow_ota_update 0x10000000)

pico_add_extra_outputs(picow_ota_update)
20 changes: 20 additions & 0 deletions pico_w/wifi/ota_update/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
This example requires a partition table in flash. This can be loaded by creating a UF2 from the partition table JSON in this folder:
```
picotool partition create main.json pt.uf2
```
then dragging & dropping this UF2 onto the device, or loading it using `picotool` and rebooting:
```
picotool load pt.uf2
picotool reboot -u
```

Once the partition table is loaded, you first need to load the Wi-Fi firmware UF2 (`picow_ota_update_wifi_firmware.uf2`) followed by loading & executing the main program (`picow_ota_update.uf2`) - either by dragging and dropping them in order, or using `picotool`:
```
picotool load picow_ota_update_wifi_firmware.uf2
picotool load -x picow_ota_update.uf2
```

Once running, you can use [python_ota_update.py](python_ota_update.py) to upload new UF2s to it using it's IP address:
```
python python_ota_update.py 192.168.0.103 picow_ota_update.uf2
```
10 changes: 10 additions & 0 deletions pico_w/wifi/ota_update/lwipopts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _LWIPOPTS_H
#define _LWIPOPTS_H

// Generally you would define your own explicit list of lwIP options
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html)
//
// This example uses a common include to avoid repetition
#include "lwipopts_examples_common.h"

#endif
64 changes: 64 additions & 0 deletions pico_w/wifi/ota_update/main.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"version": [1, 0],
"unpartitioned": {
"families": ["absolute"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
}
},
"partitions": [
{
"name": "Main A",
"id": 0,
"size": "1744K",
"families": ["rp2350-arm-s", "rp2350-riscv"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
}
},
{
"name": "Main B",
"id": 0,
"size": "1744K",
"families": ["rp2350-arm-s", "rp2350-riscv"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
},
"link": ["a", 0]
},
{
"name": "Firmware A",
"id": "0x776966696669726d",
"start": "3500k",
"size": "256K",
"families": ["cyw43-firmware"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
},
"ignored_during_riscv_boot": true,
"no_reboot_on_uf2_download": true
},
{
"name": "Firmware B",
"id": 12345,
"size": "256K",
"families": ["cyw43-firmware"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
},
"link": ["a", 2],
"ignored_during_riscv_boot": true,
"no_reboot_on_uf2_download": true
}
]
}
Loading