commit
2ace1c26f9
16
.github/workflows/examples.yml
vendored
16
.github/workflows/examples.yml
vendored
@ -11,6 +11,8 @@ jobs:
|
|||||||
example:
|
example:
|
||||||
- "examples/arduino-blink"
|
- "examples/arduino-blink"
|
||||||
- "examples/arduino-wifi-scan"
|
- "examples/arduino-wifi-scan"
|
||||||
|
- "examples/arduino-ota"
|
||||||
|
- "examples/arduino-signed-ota"
|
||||||
- "examples/arduino-external-libs"
|
- "examples/arduino-external-libs"
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@ -25,6 +27,20 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pip install -U https://github.com/platformio/platformio/archive/develop.zip
|
pip install -U https://github.com/platformio/platformio/archive/develop.zip
|
||||||
pio pkg install --global --platform symlink://.
|
pio pkg install --global --platform symlink://.
|
||||||
|
# OpenSSL needed for signed OTA update example
|
||||||
|
- name: Install OpenSSL
|
||||||
|
run: |
|
||||||
|
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||||
|
sudo apt-get install -y openssl
|
||||||
|
elif [ "$RUNNER_OS" == "Windows" ]; then
|
||||||
|
choco install openssl
|
||||||
|
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||||
|
brew install openssl
|
||||||
|
else
|
||||||
|
echo "$RUNNER_OS not supported"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shell: bash
|
||||||
- name: Build examples
|
- name: Build examples
|
||||||
run: |
|
run: |
|
||||||
pio run -d ${{ matrix.example }}
|
pio run -d ${{ matrix.example }}
|
||||||
|
123
builder/main.py
123
builder/main.py
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
from platform import system
|
from platform import system
|
||||||
from os import makedirs
|
from os import makedirs, remove
|
||||||
from os.path import isdir, join, isfile
|
from os.path import isdir, join, isfile
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
@ -184,6 +184,22 @@ env.Append(
|
|||||||
"$TARGET"
|
"$TARGET"
|
||||||
]), "Building $TARGET"),
|
]), "Building $TARGET"),
|
||||||
suffix=".hex"
|
suffix=".hex"
|
||||||
|
),
|
||||||
|
BinToSignedBin=Builder(
|
||||||
|
action=env.VerboseAction(" ".join([
|
||||||
|
'"$PYTHONEXE" "%s"' % join(
|
||||||
|
platform.get_package_dir("framework-arduinopico") or "",
|
||||||
|
"tools", "signing.py"),
|
||||||
|
"--mode",
|
||||||
|
"sign",
|
||||||
|
"--privatekey",
|
||||||
|
'"%s"' % join("$PROJECT_SRC_DIR", "private.key"),
|
||||||
|
"--bin",
|
||||||
|
"$SOURCES",
|
||||||
|
"--out",
|
||||||
|
"$TARGET"
|
||||||
|
]), "Building $TARGET"),
|
||||||
|
suffix=".bin.signed"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -209,14 +225,30 @@ env.Append(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is_arduino_pico_build = env.BoardConfig().get("build.core", "arduino") == "earlephilhower" and "arduino" in env.get("PIOFRAMEWORK")
|
||||||
|
if is_arduino_pico_build:
|
||||||
|
pubkey = join(env.subst("$PROJECT_SRC_DIR"), "public.key")
|
||||||
|
if isfile(pubkey):
|
||||||
|
header_file = join(env.subst("$BUILD_DIR"), "core", "Updater_Signing.h")
|
||||||
|
env.Prepend(CCFLAGS=['-I"%s"' % join("$BUILD_DIR", "core")])
|
||||||
|
env.Execute(" ".join([
|
||||||
|
'"$PYTHONEXE" "%s"' % join(
|
||||||
|
platform.get_package_dir("framework-arduinopico"), "tools", "signing.py"),
|
||||||
|
"--mode", "header",
|
||||||
|
"--publickey", '"%s"' % join("$PROJECT_SRC_DIR", "public.key"),
|
||||||
|
"--out", '"%s"' % join("$BUILD_DIR", "core", "Updater_Signing.h")
|
||||||
|
]))
|
||||||
|
|
||||||
#
|
#
|
||||||
# Target: Build executable and linkable firmware
|
# Target: Build executable and linkable firmware
|
||||||
#
|
#
|
||||||
|
|
||||||
target_elf = None
|
target_elf = None
|
||||||
|
target_signed_bin = None
|
||||||
if "nobuild" in COMMAND_LINE_TARGETS:
|
if "nobuild" in COMMAND_LINE_TARGETS:
|
||||||
target_elf = join("$BUILD_DIR", "${PROGNAME}.elf")
|
target_elf = join("$BUILD_DIR", "${PROGNAME}.elf")
|
||||||
target_firm = join("$BUILD_DIR", "${PROGNAME}.bin")
|
target_firm = join("$BUILD_DIR", "${PROGNAME}.bin")
|
||||||
|
target_firm = join("$BUILD_DIR", "${PROGNAME}.bin.signed")
|
||||||
else:
|
else:
|
||||||
target_elf = env.BuildProgram()
|
target_elf = env.BuildProgram()
|
||||||
if set(["buildfs", "uploadfs"]) & set(COMMAND_LINE_TARGETS):
|
if set(["buildfs", "uploadfs"]) & set(COMMAND_LINE_TARGETS):
|
||||||
@ -225,11 +257,14 @@ else:
|
|||||||
AlwaysBuild(target_firm)
|
AlwaysBuild(target_firm)
|
||||||
else:
|
else:
|
||||||
target_firm = env.ElfToBin(join("$BUILD_DIR", "${PROGNAME}"), target_elf)
|
target_firm = env.ElfToBin(join("$BUILD_DIR", "${PROGNAME}"), target_elf)
|
||||||
|
if is_arduino_pico_build:
|
||||||
|
target_signed_bin = env.BinToSignedBin(join("$BUILD_DIR", "${PROGNAME}"), target_firm)
|
||||||
|
env.Depends(target_signed_bin, "checkprogsize")
|
||||||
env.Depends(target_firm, "checkprogsize")
|
env.Depends(target_firm, "checkprogsize")
|
||||||
|
|
||||||
env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image")
|
env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image")
|
||||||
AlwaysBuild(env.Alias("nobuild", target_firm))
|
AlwaysBuild(env.Alias("nobuild", target_firm))
|
||||||
target_buildprog = env.Alias("buildprog", target_firm, target_firm)
|
target_buildprog = env.Alias("buildprog", [target_firm, target_signed_bin], target_firm)
|
||||||
|
|
||||||
env.AddPostAction(
|
env.AddPostAction(
|
||||||
target_elf, env.VerboseAction(generate_uf2, "Generating UF2 image")
|
target_elf, env.VerboseAction(generate_uf2, "Generating UF2 image")
|
||||||
@ -284,14 +319,93 @@ def UploadUF2ToDisk(target, source, env):
|
|||||||
copyfile(fpath, join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext)))
|
copyfile(fpath, join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext)))
|
||||||
print(
|
print(
|
||||||
"Firmware has been successfully uploaded.\n"
|
"Firmware has been successfully uploaded.\n"
|
||||||
"(Some boards may require manual hard reset)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def TryResetPico(target, source, env):
|
||||||
|
upload_options = {}
|
||||||
|
if "BOARD" in env:
|
||||||
|
upload_options = env.BoardConfig().get("upload", {})
|
||||||
|
ports = list_serial_ports()
|
||||||
|
if len(ports) != 0:
|
||||||
|
last_port = ports[-1]["port"]
|
||||||
|
if upload_options.get("use_1200bps_touch", False):
|
||||||
|
env.TouchSerialPort(last_port, 1200)
|
||||||
|
time.sleep(2.0)
|
||||||
|
|
||||||
|
from platformio.device.list.util import list_logical_devices
|
||||||
|
from platformio.device.finder import is_pattern_port
|
||||||
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
|
def find_rpi_disk(initial_port):
|
||||||
|
msdlabels = ("RPI-RP2")
|
||||||
|
item:str
|
||||||
|
for item in list_logical_devices():
|
||||||
|
if item["path"].startswith("/net"):
|
||||||
|
continue
|
||||||
|
if (
|
||||||
|
initial_port
|
||||||
|
and is_pattern_port(initial_port)
|
||||||
|
and not fnmatch(item["path"], initial_port)
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
mbed_pages = [join(item["path"], n) for n in ("INDEX.HTM", "INFO_UF2.TXT")]
|
||||||
|
if any(isfile(p) for p in mbed_pages):
|
||||||
|
return item["path"]
|
||||||
|
if item["name"] and any(l in item["name"].lower() for l in msdlabels):
|
||||||
|
return item["path"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def AutodetectPicoDisk(target, source, env):
|
||||||
|
initial_port = env.subst("$UPLOAD_PORT")
|
||||||
|
if initial_port and not is_pattern_port(initial_port):
|
||||||
|
print(env.subst("Using manually specified: $UPLOAD_PORT"))
|
||||||
|
return
|
||||||
|
|
||||||
|
if upload_protocol == "mbed":
|
||||||
|
env.Replace(UPLOAD_PORT=find_rpi_disk(initial_port))
|
||||||
|
|
||||||
|
if env.subst("$UPLOAD_PORT"):
|
||||||
|
print(env.subst("Auto-detected: $UPLOAD_PORT"))
|
||||||
|
else:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Error: Please specify `upload_port` for environment or use "
|
||||||
|
"global `--upload-port` option.\n"
|
||||||
|
"For some development platforms it can be a USB flash "
|
||||||
|
"drive (i.e. /media/<user>/<device name>)\n"
|
||||||
|
)
|
||||||
|
env.Exit(1)
|
||||||
|
|
||||||
if upload_protocol == "mbed":
|
if upload_protocol == "mbed":
|
||||||
upload_actions = [
|
upload_actions = [
|
||||||
env.VerboseAction(env.AutodetectUploadPort, "Looking for upload disk..."),
|
env.VerboseAction(TryResetPico, "Trying to reset Pico into bootloader mode..."),
|
||||||
|
env.VerboseAction(AutodetectPicoDisk, "Looking for upload disk..."),
|
||||||
env.VerboseAction(UploadUF2ToDisk, "Uploading $SOURCE")
|
env.VerboseAction(UploadUF2ToDisk, "Uploading $SOURCE")
|
||||||
]
|
]
|
||||||
|
elif upload_protocol == "espota":
|
||||||
|
if not env.subst("$UPLOAD_PORT"):
|
||||||
|
sys.stderr.write(
|
||||||
|
"Error: Please specify IP address or host name of ESP device "
|
||||||
|
"using `upload_port` for build environment or use "
|
||||||
|
"global `--upload-port` option.\n"
|
||||||
|
"See https://docs.platformio.org/page/platforms/"
|
||||||
|
"espressif8266.html#over-the-air-ota-update\n")
|
||||||
|
env.Replace(
|
||||||
|
UPLOADER=join(
|
||||||
|
platform.get_package_dir("framework-arduinopico") or "",
|
||||||
|
"tools", "espota.py"),
|
||||||
|
UPLOADERFLAGS=["--debug", "--progress", "-i", "$UPLOAD_PORT", "-p", "2040"],
|
||||||
|
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE'
|
||||||
|
)
|
||||||
|
if "uploadfs" in COMMAND_LINE_TARGETS:
|
||||||
|
env.Append(UPLOADERFLAGS=["-s"])
|
||||||
|
else:
|
||||||
|
# check if we have a .bin.signed file available.
|
||||||
|
# since the file may not be build yet, we try to predict that we will
|
||||||
|
# have that file if they private signing key exists.
|
||||||
|
if isfile(join(env.subst("$PROJECT_SRC_DIR"), "private.key")):
|
||||||
|
sys.stdout.write("Using signed OTA update file.")
|
||||||
|
upload_source = target_signed_bin
|
||||||
|
upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
|
||||||
elif upload_protocol == "picotool":
|
elif upload_protocol == "picotool":
|
||||||
env.Replace(
|
env.Replace(
|
||||||
UPLOADER=join(platform.get_package_dir("tool-rp2040tools") or "", "rp2040load"),
|
UPLOADER=join(platform.get_package_dir("tool-rp2040tools") or "", "rp2040load"),
|
||||||
@ -405,5 +519,4 @@ env.AddPlatformTarget("uploadfs", target_firm, upload_actions, "Upload Filesyste
|
|||||||
#
|
#
|
||||||
# Default targets
|
# Default targets
|
||||||
#
|
#
|
||||||
|
|
||||||
Default([target_buildprog, target_size])
|
Default([target_buildprog, target_size])
|
||||||
|
1
examples/arduino-ota/.gitignore
vendored
Normal file
1
examples/arduino-ota/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.pio
|
33
examples/arduino-ota/README.md
Normal file
33
examples/arduino-ota/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
How to build PlatformIO based project
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html)
|
||||||
|
2. Download [development platform with examples](https://github.com/platformio/platform-raspberrypi/archive/develop.zip)
|
||||||
|
3. Extract ZIP archive
|
||||||
|
4. Run these commands:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Change directory to example
|
||||||
|
$ cd platform-raspberrypi/examples/arduino-ota
|
||||||
|
|
||||||
|
# Build project
|
||||||
|
$ pio run
|
||||||
|
|
||||||
|
# Upload firmware
|
||||||
|
$ pio run --target upload
|
||||||
|
|
||||||
|
# Clean build files
|
||||||
|
$ pio run --target clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
This examples showcases the usage of Over-The-Air (OTA) updates with the Raspberry Pi Pico W.
|
||||||
|
|
||||||
|
For more details, see the [documentation](https://arduino-pico.readthedocs.io/en/latest/ota.html).
|
||||||
|
|
||||||
|
For the initial firmware update, use the `rpipicow_via_usb` environment.
|
||||||
|
|
||||||
|
Then, open the serial monitor and note down the IP of the Pico that it outputs.
|
||||||
|
|
||||||
|
Use this IP as the `upload_port` in the `rpipicow_via_ota` environment and use the "Upload" project task there.
|
39
examples/arduino-ota/include/README
Normal file
39
examples/arduino-ota/include/README
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
examples/arduino-ota/lib/README
Normal file
46
examples/arduino-ota/lib/README
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
23
examples/arduino-ota/platformio.ini
Normal file
23
examples/arduino-ota/platformio.ini
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter, extra scripting
|
||||||
|
; Upload options: custom port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env]
|
||||||
|
platform = raspberrypi
|
||||||
|
framework = arduino
|
||||||
|
|
||||||
|
; upload via USB
|
||||||
|
[env:rpipicow_via_usb]
|
||||||
|
board = rpipicow
|
||||||
|
upload_protocol = mbed
|
||||||
|
|
||||||
|
; upload via OTA (change IP)
|
||||||
|
[env:rpipicow_via_ota]
|
||||||
|
board = rpipicow
|
||||||
|
upload_protocol = espota
|
||||||
|
upload_port = 192.168.0.206
|
78
examples/arduino-ota/src/main.cpp
Normal file
78
examples/arduino-ota/src/main.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
#include "Updater_Signing.h"
|
||||||
|
|
||||||
|
#ifndef STASSID
|
||||||
|
#define STASSID "YourSSID"
|
||||||
|
#define STAPSK "YourPassword"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* ssid = STASSID;
|
||||||
|
const char* password = STAPSK;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Booting");
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||||
|
Serial.println("Connection Failed! Rebooting...");
|
||||||
|
delay(5000);
|
||||||
|
rp2040.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port defaults to 8266
|
||||||
|
// ArduinoOTA.setPort(8266);
|
||||||
|
|
||||||
|
// Hostname defaults to esp8266-[ChipID]
|
||||||
|
// ArduinoOTA.setHostname("myesp8266");
|
||||||
|
|
||||||
|
// No authentication by default
|
||||||
|
// ArduinoOTA.setPassword("admin");
|
||||||
|
|
||||||
|
// Password can be set with it's md5 value as well
|
||||||
|
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
|
||||||
|
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
|
||||||
|
|
||||||
|
ArduinoOTA.onStart([]() {
|
||||||
|
String type;
|
||||||
|
if (ArduinoOTA.getCommand() == U_FLASH) {
|
||||||
|
type = "sketch";
|
||||||
|
} else { // U_FS
|
||||||
|
type = "filesystem";
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
|
||||||
|
Serial.println("Start updating " + type);
|
||||||
|
});
|
||||||
|
ArduinoOTA.onEnd([]() {
|
||||||
|
Serial.println("\nEnd");
|
||||||
|
});
|
||||||
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||||
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||||
|
});
|
||||||
|
ArduinoOTA.onError([](ota_error_t error) {
|
||||||
|
Serial.printf("Error[%u]: ", error);
|
||||||
|
if (error == OTA_AUTH_ERROR) {
|
||||||
|
Serial.println("Auth Failed");
|
||||||
|
} else if (error == OTA_BEGIN_ERROR) {
|
||||||
|
Serial.println("Begin Failed");
|
||||||
|
} else if (error == OTA_CONNECT_ERROR) {
|
||||||
|
Serial.println("Connect Failed");
|
||||||
|
} else if (error == OTA_RECEIVE_ERROR) {
|
||||||
|
Serial.println("Receive Failed");
|
||||||
|
} else if (error == OTA_END_ERROR) {
|
||||||
|
Serial.println("End Failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
Serial.println("Ready");
|
||||||
|
Serial.print("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
}
|
11
examples/arduino-ota/test/README
Normal file
11
examples/arduino-ota/test/README
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
This directory is intended for PIO Unit Testing and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/page/plus/unit-testing.html
|
1
examples/arduino-signed-ota/.gitignore
vendored
Normal file
1
examples/arduino-signed-ota/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.pio
|
37
examples/arduino-signed-ota/README.md
Normal file
37
examples/arduino-signed-ota/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
How to build PlatformIO based project
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html)
|
||||||
|
2. Download [development platform with examples](https://github.com/platformio/platform-raspberrypi/archive/develop.zip)
|
||||||
|
3. Extract ZIP archive
|
||||||
|
4. Run these commands:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Change directory to example
|
||||||
|
$ cd platform-raspberrypi/examples/arduino-signed-ota
|
||||||
|
|
||||||
|
# Build project
|
||||||
|
$ pio run
|
||||||
|
|
||||||
|
# Upload firmware
|
||||||
|
$ pio run --target upload
|
||||||
|
|
||||||
|
# Clean build files
|
||||||
|
$ pio run --target clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
This examples showcases the usage of **signed** Over-The-Air (OTA) updates with the Raspberry Pi Pico W.
|
||||||
|
|
||||||
|
The difference to regular OTA updates is that update binaries are signed using the `private.key` to produce a `firmware.bin.signed` file.
|
||||||
|
|
||||||
|
The firmware then uses the `public.key` file to verify the signature on the binary it receives in an OTA update. It will reject OTA update binaries that were not properly signed.
|
||||||
|
|
||||||
|
For more details, see the [documentation](https://arduino-pico.readthedocs.io/en/latest/ota.html).
|
||||||
|
|
||||||
|
For the initial firmware update, use the `rpipicow_via_usb` environment.
|
||||||
|
|
||||||
|
Then, open the serial monitor and note down the IP of the Pico that it outputs.
|
||||||
|
|
||||||
|
Use this IP as the `upload_port` in the `rpipicow_via_ota` environment and use the "Upload" project task there.
|
39
examples/arduino-signed-ota/include/README
Normal file
39
examples/arduino-signed-ota/include/README
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
examples/arduino-signed-ota/lib/README
Normal file
46
examples/arduino-signed-ota/lib/README
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
23
examples/arduino-signed-ota/platformio.ini
Normal file
23
examples/arduino-signed-ota/platformio.ini
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter, extra scripting
|
||||||
|
; Upload options: custom port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env]
|
||||||
|
platform = raspberrypi
|
||||||
|
framework = arduino
|
||||||
|
|
||||||
|
; upload via USB
|
||||||
|
[env:rpipicow_via_usb]
|
||||||
|
board = rpipicow
|
||||||
|
upload_protocol = mbed
|
||||||
|
|
||||||
|
; upload via OTA (change IP)
|
||||||
|
[env:rpipicow_via_ota]
|
||||||
|
board = rpipicow
|
||||||
|
upload_protocol = espota
|
||||||
|
upload_port = 192.168.0.206
|
78
examples/arduino-signed-ota/src/main.cpp
Normal file
78
examples/arduino-signed-ota/src/main.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
#include "Updater_Signing.h"
|
||||||
|
|
||||||
|
#ifndef STASSID
|
||||||
|
#define STASSID "YourSSID"
|
||||||
|
#define STAPSK "YourPassword"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* ssid = STASSID;
|
||||||
|
const char* password = STAPSK;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Booting");
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||||
|
Serial.println("Connection Failed! Rebooting...");
|
||||||
|
delay(5000);
|
||||||
|
rp2040.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port defaults to 8266
|
||||||
|
// ArduinoOTA.setPort(8266);
|
||||||
|
|
||||||
|
// Hostname defaults to esp8266-[ChipID]
|
||||||
|
// ArduinoOTA.setHostname("myesp8266");
|
||||||
|
|
||||||
|
// No authentication by default
|
||||||
|
// ArduinoOTA.setPassword("admin");
|
||||||
|
|
||||||
|
// Password can be set with it's md5 value as well
|
||||||
|
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
|
||||||
|
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
|
||||||
|
|
||||||
|
ArduinoOTA.onStart([]() {
|
||||||
|
String type;
|
||||||
|
if (ArduinoOTA.getCommand() == U_FLASH) {
|
||||||
|
type = "sketch";
|
||||||
|
} else { // U_FS
|
||||||
|
type = "filesystem";
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
|
||||||
|
Serial.println("Start updating " + type);
|
||||||
|
});
|
||||||
|
ArduinoOTA.onEnd([]() {
|
||||||
|
Serial.println("\nEnd");
|
||||||
|
});
|
||||||
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||||
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||||
|
});
|
||||||
|
ArduinoOTA.onError([](ota_error_t error) {
|
||||||
|
Serial.printf("Error[%u]: ", error);
|
||||||
|
if (error == OTA_AUTH_ERROR) {
|
||||||
|
Serial.println("Auth Failed");
|
||||||
|
} else if (error == OTA_BEGIN_ERROR) {
|
||||||
|
Serial.println("Begin Failed");
|
||||||
|
} else if (error == OTA_CONNECT_ERROR) {
|
||||||
|
Serial.println("Connect Failed");
|
||||||
|
} else if (error == OTA_RECEIVE_ERROR) {
|
||||||
|
Serial.println("Receive Failed");
|
||||||
|
} else if (error == OTA_END_ERROR) {
|
||||||
|
Serial.println("End Failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
Serial.println("Ready");
|
||||||
|
Serial.print("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
}
|
27
examples/arduino-signed-ota/src/private.key
Normal file
27
examples/arduino-signed-ota/src/private.key
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEogIBAAKCAQEAu1Pt7yEk/xI+6cozLj5Bu4xV8gXDXcHS0rSJFfl4wBTk4UXp
|
||||||
|
aJRaLfR1k0juEEa5LBRZaoA0iLj2e6kfCibONx0VVoWmeqN2HBc3zkA1eqCksI0Q
|
||||||
|
Uudzto4KhKHp0odiZ2zo6c/2Tn1zqD/m3OLoSjVTbsJmGuwx8RGMBXozpg/uL0hH
|
||||||
|
flihX+HND4Xfw92QXv7SaPBhgvM9xyRxn0/w3J2nNjtuPuVN5vcQkd8ncMexVfy9
|
||||||
|
AWp+HSA5AT5N8CJ/EeIsdDMY1US28bUePzj1WIo75bZHKZNFw/iXe2xoPpm74qri
|
||||||
|
MNSlW2craFP2K3KYnI28vJeUU6t9I6LS9zt2zQIDAQABAoIBAE5GpuDKb8Qp4qIc
|
||||||
|
fMBxAVSWMn+cSuONj0O+bp4BDaTt1ioP5ZVukDQtt0ehLOEePFgf9LEc+1a6Ozy3
|
||||||
|
EaJTTs4W2Ai8djE+xqa8SPRlPjOMluSzPUP3NRHuTpTXd3YiXksrZjP1U02+/Cos
|
||||||
|
8ZIROtFvcPqSPso3MjMyitjrFFPqEtf1P+UiamjDrMSM72YX4W55kOkiCWCnAOmw
|
||||||
|
mGTlXOIqDSTBb1lloKWJfpB3RdnNo2izkU1HMBn7hVi433NUBA22o+RZhDFSZdD4
|
||||||
|
3kbkUqXd4p+vc/sh6muJtWS/COSIPFkLzdEYpBdt3XQ4FhlsRtILJaPWXa4OPjR6
|
||||||
|
ZoOwMB0CgYEA6OHfIofQiu4+HlTDN5YdyTmtYEYcrtbaQUxuQSEa2mshBphHP8uT
|
||||||
|
mYRVl2BzuprFmXZPz+FcjnPnfxqEehljvA3wMjA/PE+nQo9yyOC0N4ulXpkkqHdR
|
||||||
|
f+4KZVR7D+hesGe+57OQmvTqYZSHEt/ubjC9wZ90UFonLjsa4zibbrsCgYEAzexn
|
||||||
|
XDnThb3ffyBgvprP0IJjgMAEY0pXD++PKPQqPu9JMz68t7roYzkKFCFVOsaWpKxC
|
||||||
|
vX9mvYjTBjLpWh+ltIAN+EFz6seIbeSJ0RNybsAXYwT/mFWGHx2tMtlW6DgBu3UD
|
||||||
|
J2Yf76n0JaddBkfNMQI00Dl41+MU+AwwTB9fTBcCgYB2+f6Pm6d1cyYVROS/X1g0
|
||||||
|
V9011FwPDwFOXwftCka31Ad5YQ71jsIHqk44GjTF3xCYyJMZ917cAGcCzr9jydjk
|
||||||
|
WJKgcXm9DEy9ep//9Jzdy+BepgrObrcajriM8E424FaP9VDY+yojoICl/cXMZM9h
|
||||||
|
SFGJvDcmXgiqW9PuxhrSxQKBgAMN2oqXoPd+1W3BQS4ShbqF9IvYTThbxebKmsj0
|
||||||
|
thuw2NkVuR7Qetnd4rRhui3g/CL9GxBMb22oNdkFsEhR59dBfvOLpPh6dR+MIC8l
|
||||||
|
prDV0IL7c/8CZbbYbdUvPAa9rejl12IiNZ8MWj6kuNB7CCQN8FKWR6CMEaeMJrs6
|
||||||
|
S+OJAoGAbehNOUwEzmUKkfxf+279kBkgabcQ3NTaeSx0QOnI9KWHFGLYLQk9cMSu
|
||||||
|
maQJ1TYpbIoP1njzJ4bI2tynhwEuSMEhh4afP6U5H10NJX4PqSd0Rqc1vSJYcszr
|
||||||
|
5mUWil8FfbCBZ8jod2NQ55KYMVY5CphCqaK/s2bw2pvIR3uqJGg=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
9
examples/arduino-signed-ota/src/public.key
Normal file
9
examples/arduino-signed-ota/src/public.key
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1Pt7yEk/xI+6cozLj5B
|
||||||
|
u4xV8gXDXcHS0rSJFfl4wBTk4UXpaJRaLfR1k0juEEa5LBRZaoA0iLj2e6kfCibO
|
||||||
|
Nx0VVoWmeqN2HBc3zkA1eqCksI0QUudzto4KhKHp0odiZ2zo6c/2Tn1zqD/m3OLo
|
||||||
|
SjVTbsJmGuwx8RGMBXozpg/uL0hHflihX+HND4Xfw92QXv7SaPBhgvM9xyRxn0/w
|
||||||
|
3J2nNjtuPuVN5vcQkd8ncMexVfy9AWp+HSA5AT5N8CJ/EeIsdDMY1US28bUePzj1
|
||||||
|
WIo75bZHKZNFw/iXe2xoPpm74qriMNSlW2craFP2K3KYnI28vJeUU6t9I6LS9zt2
|
||||||
|
zQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
11
examples/arduino-signed-ota/test/README
Normal file
11
examples/arduino-signed-ota/test/README
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
This directory is intended for PIO Unit Testing and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/page/plus/unit-testing.html
|
@ -47,7 +47,7 @@
|
|||||||
"type": "framework",
|
"type": "framework",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"owner": "earlephilhower",
|
"owner": "earlephilhower",
|
||||||
"version": "https://github.com/earlephilhower/arduino-pico.git#d019f31ef1c98b9e7a0535d6fb873b99fd64c9cb"
|
"version": "https://github.com/earlephilhower/arduino-pico.git#2044d2e51c481ba83a783134a12b0fe9feaf2026"
|
||||||
},
|
},
|
||||||
"tool-rp2040tools": {
|
"tool-rp2040tools": {
|
||||||
"type": "uploader",
|
"type": "uploader",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user