Skip to content

Commit bf90077

Browse files
authored
Merge pull request #14 from arduino/ota
OTA support
2 parents 2b49c49 + 3f4e668 commit bf90077

11 files changed

+539
-19
lines changed

UNOR4USBBridge/UNOR4USBBridge.ino

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "USB.h"
1414
#include "USBCDC.h"
1515
#include "DAP.h"
16+
#include "Arduino_DebugUtils.h"
1617

1718
//#define DEBUG_AT
1819

@@ -33,12 +34,31 @@ static uint32_t _baud = 0;
3334
static CAtHandler atHandler(&SERIAL_AT);
3435
USBCDC USBSerial(0);
3536

36-
#define GPIO_BOOT 9
37-
#define GPIO_RST 4
3837

3938
bool enableSTA(bool enable);
4039
bool enableAP(bool enable);
4140

41+
ssize_t write_fn(void* cookie, const char* buf, ssize_t size)
42+
{
43+
/* redirect the bytes somewhere; writing to Serial just for an example */
44+
USBSerial.write((uint8_t*) buf, size);
45+
return size;
46+
}
47+
48+
void ets_putc_handler(char c)
49+
{
50+
/* this gets called from various ets_printf / esp_rom_printf calls */
51+
static char buf[256];
52+
static size_t buf_pos = 0;
53+
buf[buf_pos] = c;
54+
buf_pos++;
55+
if (c == '\n' || buf_pos == sizeof(buf)) {
56+
/* flush */
57+
write_fn(NULL, buf, buf_pos);
58+
buf_pos = 0;
59+
}
60+
}
61+
4262
/* -------------------------------------------------------------------------- */
4363
void CAtHandler::onWiFiEvent(WiFiEvent_t event) {
4464
/* -------------------------------------------------------------------------- */
@@ -102,6 +122,14 @@ void atLoop(void* param) {
102122
void setup() {
103123
/* -------------------------------------------------------------------------- */
104124

125+
/* redirect stdout */
126+
stdout = funopen(NULL, NULL, &write_fn, NULL, NULL);
127+
static char linebuf[256];
128+
setvbuf(stdout, linebuf, _IOLBF, sizeof(linebuf));
129+
130+
/* redirect ets_printf / esp_rom_printf output */
131+
ets_install_putc1(&ets_putc_handler);
132+
105133
pinMode(GPIO_BOOT, OUTPUT);
106134
pinMode(GPIO_RST, OUTPUT);
107135
digitalWrite(GPIO_BOOT, HIGH);
@@ -134,14 +162,18 @@ void setup() {
134162
/* Set up wifi event */
135163
WiFi.onEvent(CAtHandler::onWiFiEvent);
136164

165+
Debug.setDebugOutputStream(&USBSerial);
166+
Debug.setDebugLevel(DBG_ERROR);
167+
137168
xTaskCreatePinnedToCore(
138169
atLoop, /* Function to implement the task */
139170
"Task1", /* Name of the task */
140171
10000, /* Stack size in words */
141172
NULL, /* Task input parameter */
142-
0, /* Priority of the task */
173+
1, /* Priority of the task */
143174
&atTask, /* Task handle. */
144175
0); /* Core where the task should run */
176+
145177
}
146178

147179
/*

UNOR4USBBridge/at_handler.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "cmds_wifi_SSL.h"
1212
#include "cmds_wifi_udp.h"
1313
#include "cmds_ble_bridge.h"
14+
#include "cmds_ota.h"
1415

1516
using namespace SudoMaker;
1617

@@ -66,6 +67,7 @@ CClientWrapper CAtHandler::getClient(int sock) {
6667
void CAtHandler::run() {
6768
/* -------------------------------------------------------------------------- */
6869
at_srv.run();
70+
vTaskDelay(1);
6971
}
7072

7173

@@ -126,4 +128,5 @@ CAtHandler::CAtHandler(HardwareSerial *s) : last_server_client_sock(0) {
126128
add_cmds_wifi_netif();
127129
add_cmds_wifi_udp();
128130
add_cmds_ble_bridge();
129-
}
131+
add_cmds_ota();
132+
}

UNOR4USBBridge/at_handler.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
#define MAX_SERVER_AVAILABLE 4
1515
#define MAX_UDP_AVAILABLE 4
1616

17-
#define ESP_FW_VERSION "0.2.1"
17+
#define ESP_FW_VERSION "0.3.0"
1818
#define FIRMWARE_MAYOR 0
19-
#define FIRMWARE_MINOR 2
20-
#define FIRMWARE_PATCH 1
19+
#define FIRMWARE_MINOR 3
20+
#define FIRMWARE_PATCH 0
21+
22+
#define GPIO_BOOT 9
23+
#define GPIO_RST 4
2124

2225
using namespace SudoMaker;
2326

@@ -77,6 +80,7 @@ class CAtHandler {
7780
void add_cmds_wifi_netif();
7881
void add_cmds_wifi_udp();
7982
void add_cmds_ble_bridge();
83+
void add_cmds_ota();
8084
public:
8185
std::vector<std::uint8_t> cert_buf;
8286
CAtHandler(HardwareSerial *s);

UNOR4USBBridge/cmds_ota.h

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#ifndef CMDS_OTA_H
2+
#define CMDS_OTA_H
3+
4+
#include "at_handler.h"
5+
#include "Arduino_ESP32_OTA.h"
6+
#include <BossaArduino.h>
7+
8+
Arduino_ESP32_OTA OTA;
9+
10+
void CAtHandler::add_cmds_ota() {
11+
/* ....................................................................... */
12+
command_table[_OTA_SETCAROOT] = [this](auto & srv, auto & parser) {
13+
/* ....................................................................... */
14+
switch (parser.cmd_mode) {
15+
case chAT::CommandMode::Write: {
16+
if (parser.args.size() != 1) {
17+
return chAT::CommandStatus::ERROR;
18+
}
19+
20+
int ca_root_size = 0;
21+
auto &ca_root_size_str = parser.args[0];
22+
if (ca_root_size_str.empty()) {
23+
return chAT::CommandStatus::ERROR;
24+
}
25+
ca_root_size = atoi(ca_root_size_str.c_str());
26+
if(!ca_root_size) {
27+
return chAT::CommandStatus::ERROR;
28+
}
29+
30+
cert_buf = srv.inhibit_read(ca_root_size);
31+
size_t offset = cert_buf.size();
32+
if(offset < ca_root_size) {
33+
cert_buf.resize(ca_root_size);
34+
do {
35+
offset += serial->read(cert_buf.data() + offset, ca_root_size - offset);
36+
} while (offset < ca_root_size);
37+
}
38+
OTA.setCACert((const char *)cert_buf.data());
39+
srv.continue_read();
40+
return chAT::CommandStatus::OK;
41+
}
42+
default:
43+
return chAT::CommandStatus::ERROR;
44+
}
45+
};
46+
47+
/* ....................................................................... */
48+
command_table[_OTA_BEGIN] = [this](auto & srv, auto & parser) {
49+
/* ....................................................................... */
50+
switch (parser.cmd_mode) {
51+
case chAT::CommandMode::Run: {
52+
Arduino_ESP32_OTA::Error ota_error = OTA.begin();
53+
String error = String((int)ota_error) + "\r\n";
54+
srv.write_response_prompt();
55+
srv.write_str((const char *)(error.c_str()));
56+
srv.write_line_end();
57+
return chAT::CommandStatus::OK;
58+
}
59+
case chAT::CommandMode::Write: {
60+
if (parser.args.size() != 1) {
61+
return chAT::CommandStatus::ERROR;
62+
}
63+
64+
auto &path = parser.args[0];
65+
if (path.empty()) {
66+
return chAT::CommandStatus::ERROR;
67+
}
68+
69+
Arduino_ESP32_OTA::Error ota_error = OTA.begin(path.c_str());
70+
String error = String((int)ota_error) + "\r\n";
71+
srv.write_response_prompt();
72+
srv.write_str((const char *)(error.c_str()));
73+
srv.write_line_end();
74+
return chAT::CommandStatus::OK;
75+
76+
}
77+
default:
78+
return chAT::CommandStatus::ERROR;
79+
}
80+
};
81+
82+
/* ....................................................................... */
83+
command_table[_OTA_DOWNLOAD] = [this](auto & srv, auto & parser) {
84+
/* ....................................................................... */
85+
switch (parser.cmd_mode) {
86+
case chAT::CommandMode::Write: {
87+
if (parser.args.size() == 1) {
88+
auto &url = parser.args[0];
89+
if (url.empty()) {
90+
return chAT::CommandStatus::ERROR;
91+
}
92+
93+
int ota_error = OTA.download(url.c_str());
94+
String error = String((int)ota_error) + "\r\n";
95+
srv.write_response_prompt();
96+
srv.write_str((const char *)(error.c_str()));
97+
srv.write_line_end();
98+
return chAT::CommandStatus::OK;
99+
} else if(parser.args.size() == 2) {
100+
auto &url = parser.args[0];
101+
if (url.empty()) {
102+
return chAT::CommandStatus::ERROR;
103+
}
104+
105+
auto &path = parser.args[1];
106+
if (path.empty()) {
107+
return chAT::CommandStatus::ERROR;
108+
}
109+
110+
int ota_error = OTA.download(url.c_str(), path.c_str());
111+
String error = String((int)ota_error) + "\r\n";
112+
srv.write_response_prompt();
113+
srv.write_str((const char *)(error.c_str()));
114+
srv.write_line_end();
115+
return chAT::CommandStatus::OK;
116+
} else {
117+
return chAT::CommandStatus::ERROR;
118+
}
119+
120+
}
121+
default:
122+
return chAT::CommandStatus::ERROR;
123+
}
124+
};
125+
126+
/* ....................................................................... */
127+
command_table[_OTA_VERIFY] = [this](auto & srv, auto & parser) {
128+
/* ....................................................................... */
129+
switch (parser.cmd_mode) {
130+
case chAT::CommandMode::Run: {
131+
Arduino_ESP32_OTA::Error ota_error = OTA.verify();
132+
String error = String((int)ota_error) + "\r\n";
133+
srv.write_response_prompt();
134+
srv.write_str((const char *)(error.c_str()));
135+
srv.write_line_end();
136+
return chAT::CommandStatus::OK;
137+
}
138+
default:
139+
return chAT::CommandStatus::ERROR;
140+
}
141+
};
142+
143+
/* ....................................................................... */
144+
command_table[_OTA_UPDATE] = [this](auto & srv, auto & parser) {
145+
/* ....................................................................... */
146+
switch (parser.cmd_mode) {
147+
case chAT::CommandMode::Run: {
148+
Arduino_ESP32_OTA::Error ota_error = OTA.update();
149+
String error = String((int)ota_error) + "\r\n";
150+
srv.write_response_prompt();
151+
srv.write_str((const char *)(error.c_str()));
152+
srv.write_line_end();
153+
return chAT::CommandStatus::OK;
154+
}
155+
case chAT::CommandMode::Write: {
156+
if (parser.args.size() != 1) {
157+
return chAT::CommandStatus::ERROR;
158+
}
159+
160+
auto &path = parser.args[0];
161+
if (path.empty()) {
162+
return chAT::CommandStatus::ERROR;
163+
}
164+
165+
int flash_error = BOSSA::flashUnoR4WiFi(path.c_str(), Serial, GPIO_BOOT, GPIO_RST);
166+
String error = String(flash_error) + "\r\n";
167+
srv.write_response_prompt();
168+
srv.write_str((const char *)(error.c_str()));
169+
srv.write_line_end();
170+
return chAT::CommandStatus::OK;
171+
}
172+
default:
173+
return chAT::CommandStatus::ERROR;
174+
}
175+
};
176+
177+
/* ....................................................................... */
178+
command_table[_OTA_RESET] = [this](auto & srv, auto & parser) {
179+
/* ....................................................................... */
180+
switch (parser.cmd_mode) {
181+
case chAT::CommandMode::Run: {
182+
OTA.reset();
183+
srv.write_response_prompt();
184+
srv.write_str("0");
185+
srv.write_line_end();
186+
return chAT::CommandStatus::OK;
187+
}
188+
default:
189+
return chAT::CommandStatus::ERROR;
190+
}
191+
};
192+
}
193+
194+
#endif

UNOR4USBBridge/commands.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ enum {
112112
#define _HCI_WRITE "+HCIWRITE"
113113
#define _HCI_AVAILABLE "+HCIAVAILABLE"
114114

115+
#define _OTA_SETCAROOT "+OTASETCAROOT"
116+
#define _OTA_BEGIN "+OTABEGIN"
117+
#define _OTA_DOWNLOAD "+OTADOWNLOAD"
118+
#define _OTA_VERIFY "+OTAVERIFY"
119+
#define _OTA_UPDATE "+OTAUPDATE"
120+
#define _OTA_RESET "+OTARESET"
115121

116122

117123
#define CMD(x) _AT x _ENDL

combine.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
import sys;
44

5-
booloaderData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/UNOR4USBBridge.ino.bootloader.bin", "rb").read()
6-
partitionData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/UNOR4USBBridge.ino.partitions.bin", "rb").read()
5+
booloaderData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/UNOR4USBBridge.ino.bootloader.bin", "rb").read()
6+
partitionData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/UNOR4USBBridge.ino.partitions.bin", "rb").read()
77
bootApp = open("boot/boot_app0.bin", "rb").read()
8-
appData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/UNOR4USBBridge.ino.bin", "rb").read()
9-
certsData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/x509_crt_bundle", "rb").read()
8+
appData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/UNOR4USBBridge.ino.bin", "rb").read()
9+
spiffsData = open("spiffs/spiffs.bin", "rb").read()
10+
certsData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/x509_crt_bundle", "rb").read()
1011

1112
# 0x000000 bootloader
1213
# 0x008000 partitions
1314
# 0x00E000 boot_app
1415
# 0x010000 app
16+
# 0x330000 spiffs
1517
# 0x3C0000 certs
1618

1719
# calculate the output binary size, app offset
@@ -35,11 +37,14 @@
3537
for i in range(0, len(appData)):
3638
outputData[0x10000 + i] = appData[i]
3739

40+
for i in range(0, len(spiffsData)):
41+
outputData[0x330000 + i] = spiffsData[i]
42+
3843
for i in range(0, len(certsData)):
3944
outputData[0x3C0000 + i] = certsData[i]
4045

4146

42-
outputFilename = "UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/S3.bin"
47+
outputFilename = "UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/S3.bin"
4348
if (len(sys.argv) > 1):
4449
outputFilename = sys.argv[1]
4550

compile.sh

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,21 @@ if [ ! -d hardware ]; then
1414
cd hardware/esp32-patched/esp32/libraries
1515
git clone https://github.com/facchinm/ArduinoBLE.git
1616
cd ArduinoBLE/
17-
git checkout uno_r4_wifi
18-
cd ../../../../../
17+
git checkout 4e4a7cef7718f6787ef89c24aa3ffd0fd2a9ced3
18+
cd ..
19+
git clone https://github.com/pennam/Arduino_ESP32_OTA.git
20+
cd Arduino_ESP32_OTA/
21+
git checkout e27f822406986354197a09516edaaeea3ed18e79
22+
cd ..
23+
git clone https://github.com/pennam/BOSSA.git
24+
cd BOSSA
25+
git checkout 43a8feff9dfd07109d25cb2005279dd92e81d8fc
26+
cd ..
27+
git clone https://github.com/arduino-libraries/Arduino_DebugUtils.git
28+
cd ../../../../
1929

2030
ln -s $(pwd)/hardware/esp32-patched/esp32/esptool hardware/esp32-patched/esp32/tools/esptool
2131
ln -s $(pwd)/hardware/esp32-patched/esp32/xtensa-esp32s3-elf hardware/esp32-patched/esp32/tools/xtensa-esp32s3-elf
2232
fi
2333

24-
arduino-cli compile -e --config-file arduino-cli.yaml --fqbn=esp32-patched:esp32:esp32s3:JTAGAdapter=default,PSRAM=disabled,FlashMode=qio,FlashSize=4M,LoopCore=1,EventsCore=1,USBMode=default,CDCOnBoot=default,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,PartitionScheme=huge_app,CPUFreq=240,UploadSpeed=921600,DebugLevel=none,EraseFlash=none -v UNOR4USBBridge
34+
arduino-cli compile -e --config-file arduino-cli.yaml --fqbn=esp32-patched:esp32:arduino_unor4wifi_usb_bridge:JTAGAdapter=default,PSRAM=disabled,FlashMode=qio,FlashSize=4M,LoopCore=1,EventsCore=1,USBMode=default,CDCOnBoot=default,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,PartitionScheme=unor4wifi,CPUFreq=240,UploadSpeed=921600,DebugLevel=none,EraseFlash=none -v UNOR4USBBridge

0 commit comments

Comments
 (0)