8000 Add OTA update support (#711) · ZZKK000/arduino-pico@da86a89 · GitHub
[go: up one dir, main page]

Skip to content

Commit da86a89

Browse files
Add OTA update support (earlephilhower#711)
Adds a 12K OTA stub 3rd stage bootloader, which reads new firmware from the LittleFS filesystem and flashes on reboot. By storing the OTA commands in a file in flash, it is possible to recover from a power failure during OTA programming. On power resume, the OTA block will simply re-program from the beginning. Support cryptographic signed OTA updates, if desired. Includes host-side signing logic via openssl. Add PicoOTA library which encapsulates the file format for the updater, including CRC32 checking. Add LEAmDNS support to allow Arduino IDE discovery Add ArduinoOTA class for IDE uploads Add MD5Builder class Add Updater class which supports writing and validating cryptographically signed binaries from any source (http, Ethernet, WiFi, Serial, etc.) Add documentation and readmes.
1 parent 71be07e commit da86a89

File tree

87 files changed

+23808
-315
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+23808
-315
lines changed

.github/workflows/pull-request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: Run codespell
2121
uses: codespell-project/actions-codespell@master
2222
with:
23-
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server
23+
skip: ./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS,./tools/libbearssl/bearssl,./include,./libraries/WiFi/examples/BearSSL_Server,./ota/uzlib
2424
ignore_words_list: ser,dout
2525

2626
# Consistent style

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
.DS_Store
22
system
33
tools/dist
4-
tools/libpico/build
4+
docs/_build
5+
ota/build
6+
tools/libpico/build

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@
3131
[submodule "tools/libbearssl/bearssl"]
3232
path = tools/libbearssl/bearssl
3333
url = https://github.com/earlephilhower/bearssl-esp8266.git
34+
[submodule "ota/uzlib"]
35+
path = ota/uzlib
36+
url = https://github.com/pfalcon/uzlib.git

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
146146
# Features
147147
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
148148
* Generic Arduino USB Serial, Keyboard, and Mouse emulation
149+
* WiFi (Pico W)
150+
* Over-the-Air (OTA) upgrades
149151
* Filesystems (LittleFS and SD/SDFS)
150152
* Multicore support (setup1() and loop1())
151153
* FreeRTOS SMP support
@@ -184,6 +186,8 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
184186
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
185187
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
186188
* [BearSSL](https://bearssl.org) library written by Thomas Pornin, is distributed under the [MIT License](https://bearssl.org/#legal-details).
189+
* [UZLib](https://github.com/pfalcon/uzlib) is copyright (c) 2003 Joergen Ibsen and distributed under the zlib license.
190+
* [LEAmDMS](https://github.com/LaborEtArs/ESP8266mDNS) is copyright multiple authors and distributed under the MIT license.
187191
188192
-Earle F. Philhower, III
189193
earlephilhower@yahoo.com

cores/rp2040/FS.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ class File : public Stream {
9090
uint8_t obuf[256];
9191
size_t doneLen = 0;
9292
size_t sentLen;
93-
int i;
9493

95-
while (src.available() > sizeof(obuf)) {
94+
while ((size_t)src.available() > sizeof(obuf)) {
9695
src.read(obuf, sizeof(obuf));
9796
sentLen = write(obuf, sizeof(obuf));
9897
doneLen = doneLen + sentLen;

cores/rp2040/RP2040Support.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include <hardware/clocks.h>
2222
#include <hardware/irq.h>
2323
#include <hardware/pio.h>
24+
#include <pico/unique_id.h>
2425
#include <hardware/exception.h>
26+
#include <hardware/watchdog.h>
2527
#include <hardware/structs/rosc.h>
2628
#include <hardware/structs/systick.h>
2729
#include <pico/multicore.h>
@@ -311,6 +313,22 @@ class RP2040 {
311313
multicore_launch_core1(main1);
312314
}
313315

316+
void reboot() {
317+
watchdog_reboot(0, 0, 100);
318+
}
319+
320+
inline void restart() {
321+
reboot();
322+
}
323+
324+
const char *getChipID() {
325+
static char id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1] = { 0 };
326+
if (!id[0]) {
327+
pico_get_unique_board_id_string(id, sizeof(id));
328+
}
329+
return id;
330+
}
331+
314332
// Multicore comms FIFO
315333
_MFIFO fifo;
316334

cores/rp2040/StreamString.h

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/**
2+
StreamString.h
3+
4+
Copyright (c) 2020 D. Gauchard. All rights reserved.
5+
This file is part of the esp8266 core for Arduino environment.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
21+
*/
22+
23+
#ifndef __STREAMSTRING_H
24+
#define __STREAMSTRING_H
25+
26+
#include <limits>
27+
#include <algorithm>
28+
#include "Stream.h"
29+
#include "api/String.h"
30+
31+
///////////////////////////////////////////////////////////////
32+
// S2Stream points to a String and makes it a Stream
33+
// (it is also the helper for StreamString)
34+
35+
class S2Stream: public Stream {
36+
public:
37+
S2Stream(String& string, int peekPointer = -1) : string(&string), peekPointer(peekPointer) { }
38+
39+
S2Stream(String* string, int peekPointer = -1) : string(string), peekPointer(peekPointer) { }
40+
41+
virtual int available() override {
42+
return string->length();
43+
}
44+
45+
virtual int availableForWrite() override {
46+
return std::numeric_limits<int16_t>::max();
47+
}
48+
49+
virtual int read() override {
50+
if (peekPointer < 0) {
51+
// consume chars
52+
if (string->length()) {
53+
char c = string->charAt(0);
54+
string->remove(0, 1);
55+
return c;
56+
}
57+
} else if (peekPointer < (int)string->length()) {
58+
// return pointed and move pointer
59+
return string->charAt(peekPointer++);
60+
}
61+
62+
// everything is read
63+
return -1;
64+
}
65+
66+
virtual size_t write(uint8_t data) override {
67+
return string->concat((char)data);
68+
}
69+
70+
// virtual int read(uint8_t* buffer, size_t len) override
71+
// {
72+
// if (peekPointer < 0)
73+
// {
74+
// // string will be consumed
75+
// size_t l = std::min(len, (size_t)string->length());
76+
// memcpy(buffer, string->c_str(), l);
77+
// string->remove(0, l);
78+
// return l;
79+
// }
80+
//
81+
// if (peekPointer >= (int)string->length())
82+
// {
83+
// return 0;
84+
// }
85+
//
86+
// // only the pointer is moved
87+
// size_t l = std::min(len, (size_t)(string->length() - peekPointer));
88+
// memcpy(buffer, string->c_str() + peekPointer, l);
89+
// peekPointer += l;
90+
// return l;
91+
// }
92+
93+
virtual size_t write(const uint8_t* buffer, size_t len) override {
94+
return string->concat((const char*)buffer, len) ? len : 0;
95+
}
96+
97+
virtual int peek() override {
98+
if (peekPointer < 0) {
99+
if (string->length()) {
100+
return string->charAt(0);
101+
}
102+
} else if (peekPointer < (int)string->length()) {
103+
return string->charAt(peekPointer);
104+
}
105+
106+
return -1;
107+
}
108+
109+
virtual void flush() override {
110+
// nothing to do
111+
}
112+
113+
#if 0
114+
virtual bool inputCanTimeout() override {
115+
return false;
116+
}
117+
118+
virtual bool outputCanTimeout() override {
119+
return false;
120+
}
121+
122+
//// Stream's peekBufferAPI
123+
124+
virtual bool hasPeekBufferAPI() const override {
125+
return true;
126+
}
127+
128+
virtual size_t peekAvailable() {
129+
if (peekPointer < 0) {
130+
return string->length();
131+
}
132+
return string->length() - peekPointer;
133+
}
134+
135+
virtual const char* peekBuffer() override {
136+
if (peekPointer < 0) {
137+
return string->c_str();
138+
}
139+
if (peekPointer < (int)string->length()) {
140+
return string->c_str() + peekPointer;
141+
}
142+
return nullptr;
143+
}
144+
145+
virtual void peekConsume(size_t consume) override {
146+
if (peekPointer < 0) {
147+
// string is really consumed
148+
string->remove(0, consume);
149+
} else {
150+
// only the pointer is moved
151+
peekPointer = std::min((size_t)string->length(), peekPointer + consume);
152+
}
153+
}
154+
155+
virtual ssize_t streamRemaining() override {
156+
return peekPointer < 0 ? string->length() : string->length() - peekPointer;
157+
}
158+
159+
// calling setConsume() will consume bytes as the stream is read
160+
// (enabled by default)
161+
void setConsume() {
162+
peekPointer = -1;
163+
}
164+
#endif
165+
// Reading this stream will mark the string as read without consuming
166+
// (not enabled by default)
167+
// Calling resetPointer() resets the read state and allows rereading.
168+
void resetPointer(int pointer = 0) {
169+
peekPointer = pointer;
170+
}
171+
172+
protected:
173+
String* string;
174+
int peekPointer; // -1:String is consumed / >=0:resettable pointer
175+
};
176+
177+
// StreamString is a S2Stream holding the String
178+
179+
class StreamString: public String, public S2Stream {
180+
protected:
181+
void resetpp() {
182+
if (peekPointer > 0) {
183+
peekPointer = 0;
184+
}
185+
}
186+
187+
public:
188+
StreamString(StreamString&& bro) : String(bro), S2Stream(this) { }
189+
StreamString(const StreamString& bro) : String(bro), S2Stream(this) { }
190+
191+
// duplicate String constructors and operator=:
192+
193+
StreamString(const char* text = nullptr) : String(text), S2Stream(this) { }
194+
StreamString(const String& string) : String(string), S2Stream(this) { }
195+
StreamString(const __FlashStringHelper* str) : String(str), S2Stream(this) { }
196+
StreamString(String&& string) : String(string), S2Stream(this) { }
197+
198+
explicit StreamString(char c) : String(c), S2Stream(this) { }
199+
explicit StreamString(unsigned char c, unsigned char base = 10) :
200+
String(c, base), S2Stream(this) {
201+
}
202+
explicit StreamString(int i, unsigned char base = 10) : String(i, base), S2Stream(this) { }
203+
explicit StreamString(unsigned int i, unsigned char base = 10) : String(i, base), S2Stream(this) {
204+
}
205+
explicit StreamString(long l, unsigned char base = 10) : String(l, base), S2Stream(this) { }
206+
explicit StreamString(unsigned long l, unsigned char base = 10) :
207+
String(l, base), S2Stream(this) {
208+
}
209+
explicit StreamString(float f, unsigned char decimalPlaces = 2) :
210+
String(f, decimalPlaces), S2Stream(this) {
211+
}
212+
explicit StreamString(double d, unsigned char decimalPlaces = 2) :
213+
String(d, decimalPlaces), S2Stream(this) {
214+
}
215+
216+
StreamString& operator=(const StreamString& rhs) {
217+
String::operator=(rhs);
218+
resetpp();
219+
return *this;
220+
}
221+
222+
StreamString& operator=(const String& rhs) {
223+
String::operator=(rhs);
224+
resetpp();
225+
return *this;
226+
}
227+
228+
StreamString& operator=(const char* cstr) {
229+
String::operator=(cstr);
230+
resetpp();
231+
return *this;
232+
}
233+
234+
StreamString& operator=(const __FlashStringHelper* str) {
235+
String::operator=(str);
236+
resetpp();
237+
return *this;
238+
}
239+
240+
StreamString& operator=(String&& rval) {
241+
String::operator=(rval);
242+
resetpp();
243+
return *this;
244+
}
245+
};
246+
247+
#endif // __STREAMSTRING_H

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
5050
WiFiClientSecure (TLS/SSL/HTTPS) <bearssl-client-secure-class>
5151
WiFiServerSecure (TLS/SSL/HTTPS) <bearssl-server-secure-class>
5252

53+
Over-the-Air (OTA) Updates <ota>
54+
5355
Ported/Optimized Libraries <libraries>
5456
Using Pico-SDK <sdk>
5557

0 commit comments

Comments
 (0)
0