Skip to content

OTA support #14

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 14 commits into from
Aug 30, 2023
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
38 changes: 35 additions & 3 deletions UNOR4USBBridge/UNOR4USBBridge.ino
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "USB.h"
#include "USBCDC.h"
#include "DAP.h"
#include "Arduino_DebugUtils.h"

//#define DEBUG_AT

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

#define GPIO_BOOT 9
#define GPIO_RST 4

bool enableSTA(bool enable);
bool enableAP(bool enable);

ssize_t write_fn(void* cookie, const char* buf, ssize_t size)
{
/* redirect the bytes somewhere; writing to Serial just for an example */
USBSerial.write((uint8_t*) buf, size);
return size;
}

void ets_putc_handler(char c)
{
/* this gets called from various ets_printf / esp_rom_printf calls */
static char buf[256];
static size_t buf_pos = 0;
buf[buf_pos] = c;
buf_pos++;
if (c == '\n' || buf_pos == sizeof(buf)) {
/* flush */
write_fn(NULL, buf, buf_pos);
buf_pos = 0;
}
}

/* -------------------------------------------------------------------------- */
void CAtHandler::onWiFiEvent(WiFiEvent_t event) {
/* -------------------------------------------------------------------------- */
Expand Down Expand Up @@ -102,6 +122,14 @@ void atLoop(void* param) {
void setup() {
/* -------------------------------------------------------------------------- */

/* redirect stdout */
stdout = funopen(NULL, NULL, &write_fn, NULL, NULL);
static char linebuf[256];
setvbuf(stdout, linebuf, _IOLBF, sizeof(linebuf));

/* redirect ets_printf / esp_rom_printf output */
ets_install_putc1(&ets_putc_handler);

pinMode(GPIO_BOOT, OUTPUT);
pinMode(GPIO_RST, OUTPUT);
digitalWrite(GPIO_BOOT, HIGH);
Expand Down Expand Up @@ -134,14 +162,18 @@ void setup() {
/* Set up wifi event */
WiFi.onEvent(CAtHandler::onWiFiEvent);

Debug.setDebugOutputStream(&USBSerial);
Debug.setDebugLevel(DBG_ERROR);

xTaskCreatePinnedToCore(
atLoop, /* Function to implement the task */
"Task1", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
1, /* Priority of the task */
&atTask, /* Task handle. */
0); /* Core where the task should run */

}

/*
Expand Down
5 changes: 4 additions & 1 deletion UNOR4USBBridge/at_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "cmds_wifi_SSL.h"
#include "cmds_wifi_udp.h"
#include "cmds_ble_bridge.h"
#include "cmds_ota.h"

using namespace SudoMaker;

Expand Down Expand Up @@ -66,6 +67,7 @@ CClientWrapper CAtHandler::getClient(int sock) {
void CAtHandler::run() {
/* -------------------------------------------------------------------------- */
at_srv.run();
vTaskDelay(1);
}


Expand Down Expand Up @@ -126,4 +128,5 @@ CAtHandler::CAtHandler(HardwareSerial *s) : last_server_client_sock(0) {
add_cmds_wifi_netif();
add_cmds_wifi_udp();
add_cmds_ble_bridge();
}
add_cmds_ota();
}
10 changes: 7 additions & 3 deletions UNOR4USBBridge/at_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
#define MAX_SERVER_AVAILABLE 4
#define MAX_UDP_AVAILABLE 4

#define ESP_FW_VERSION "0.2.1"
#define ESP_FW_VERSION "0.3.0"
#define FIRMWARE_MAYOR 0
#define FIRMWARE_MINOR 2
#define FIRMWARE_PATCH 1
#define FIRMWARE_MINOR 3
#define FIRMWARE_PATCH 0

#define GPIO_BOOT 9
#define GPIO_RST 4

using namespace SudoMaker;

Expand Down Expand Up @@ -77,6 +80,7 @@ class CAtHandler {
void add_cmds_wifi_netif();
void add_cmds_wifi_udp();
void add_cmds_ble_bridge();
void add_cmds_ota();
public:
std::vector<std::uint8_t> cert_buf;
CAtHandler(HardwareSerial *s);
Expand Down
194 changes: 194 additions & 0 deletions UNOR4USBBridge/cmds_ota.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#ifndef CMDS_OTA_H
#define CMDS_OTA_H

#include "at_handler.h"
#include "Arduino_ESP32_OTA.h"
#include <BossaArduino.h>

Arduino_ESP32_OTA OTA;

void CAtHandler::add_cmds_ota() {
/* ....................................................................... */
command_table[_OTA_SETCAROOT] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Write: {
if (parser.args.size() != 1) {
return chAT::CommandStatus::ERROR;
}

int ca_root_size = 0;
auto &ca_root_size_str = parser.args[0];
if (ca_root_size_str.empty()) {
return chAT::CommandStatus::ERROR;
}
ca_root_size = atoi(ca_root_size_str.c_str());
if(!ca_root_size) {
return chAT::CommandStatus::ERROR;
}

cert_buf = srv.inhibit_read(ca_root_size);
size_t offset = cert_buf.size();
if(offset < ca_root_size) {
cert_buf.resize(ca_root_size);
do {
offset += serial->read(cert_buf.data() + offset, ca_root_size - offset);
} while (offset < ca_root_size);
}
OTA.setCACert((const char *)cert_buf.data());
srv.continue_read();
return chAT::CommandStatus::OK;
}
default:
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_OTA_BEGIN] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Run: {
Arduino_ESP32_OTA::Error ota_error = OTA.begin();
String error = String((int)ota_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;
}
case chAT::CommandMode::Write: {
if (parser.args.size() != 1) {
return chAT::CommandStatus::ERROR;
}

auto &path = parser.args[0];
if (path.empty()) {
return chAT::CommandStatus::ERROR;
}

Arduino_ESP32_OTA::Error ota_error = OTA.begin(path.c_str());
String error = String((int)ota_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;

}
default:
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_OTA_DOWNLOAD] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Write: {
if (parser.args.size() == 1) {
auto &url = parser.args[0];
if (url.empty()) {
return chAT::CommandStatus::ERROR;
}

int ota_error = OTA.download(url.c_str());
String error = String((int)ota_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;
} else if(parser.args.size() == 2) {
auto &url = parser.args[0];
if (url.empty()) {
return chAT::CommandStatus::ERROR;
}

auto &path = parser.args[1];
if (path.empty()) {
return chAT::CommandStatus::ERROR;
}

int ota_error = OTA.download(url.c_str(), path.c_str());
String error = String((int)ota_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;
} else {
return chAT::CommandStatus::ERROR;
}

}
default:
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_OTA_VERIFY] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Run: {
Arduino_ESP32_OTA::Error ota_error = OTA.verify();
String error = String((int)ota_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;
}
default:
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_OTA_UPDATE] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Run: {
Arduino_ESP32_OTA::Error ota_error = OTA.update();
String error = String((int)ota_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;
}
case chAT::CommandMode::Write: {
if (parser.args.size() != 1) {
return chAT::CommandStatus::ERROR;
}

auto &path = parser.args[0];
if (path.empty()) {
return chAT::CommandStatus::ERROR;
}

int flash_error = BOSSA::flashUnoR4WiFi(path.c_str(), Serial, GPIO_BOOT, GPIO_RST);
String error = String(flash_error) + "\r\n";
srv.write_response_prompt();
srv.write_str((const char *)(error.c_str()));
srv.write_line_end();
return chAT::CommandStatus::OK;
}
default:
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_OTA_RESET] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Run: {
OTA.reset();
srv.write_response_prompt();
srv.write_str("0");
srv.write_line_end();
return chAT::CommandStatus::OK;
}
default:
return chAT::CommandStatus::ERROR;
}
};
}

#endif
6 changes: 6 additions & 0 deletions UNOR4USBBridge/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ enum {
#define _HCI_WRITE "+HCIWRITE"
#define _HCI_AVAILABLE "+HCIAVAILABLE"

#define _OTA_SETCAROOT "+OTASETCAROOT"
#define _OTA_BEGIN "+OTABEGIN"
#define _OTA_DOWNLOAD "+OTADOWNLOAD"
#define _OTA_VERIFY "+OTAVERIFY"
#define _OTA_UPDATE "+OTAUPDATE"
#define _OTA_RESET "+OTARESET"


#define CMD(x) _AT x _ENDL
Expand Down
15 changes: 10 additions & 5 deletions combine.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

import sys;

booloaderData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/UNOR4USBBridge.ino.bootloader.bin", "rb").read()
partitionData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/UNOR4USBBridge.ino.partitions.bin", "rb").read()
booloaderData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/UNOR4USBBridge.ino.bootloader.bin", "rb").read()
partitionData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/UNOR4USBBridge.ino.partitions.bin", "rb").read()
bootApp = open("boot/boot_app0.bin", "rb").read()
appData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/UNOR4USBBridge.ino.bin", "rb").read()
certsData = open("UNOR4USBBridge/build/esp32-patched.esp32.esp32s3/x509_crt_bundle", "rb").read()
appData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/UNOR4USBBridge.ino.bin", "rb").read()
spiffsData = open("spiffs/spiffs.bin", "rb").read()
certsData = open("UNOR4USBBridge/build/esp32-patched.esp32.arduino_unor4wifi_usb_bridge/x509_crt_bundle", "rb").read()

# 0x000000 bootloader
# 0x008000 partitions
# 0x00E000 boot_app
# 0x010000 app
# 0x330000 spiffs
# 0x3C0000 certs

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

for i in range(0, len(spiffsData)):
outputData[0x330000 + i] = spiffsData[i]

for i in range(0, len(certsData)):
outputData[0x3C0000 + i] = certsData[i]


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

Expand Down
16 changes: 13 additions & 3 deletions compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@ if [ ! -d hardware ]; then
cd hardware/esp32-patched/esp32/libraries
git clone https://github.com/facchinm/ArduinoBLE.git
cd ArduinoBLE/
git checkout uno_r4_wifi
cd ../../../../../
git checkout 4e4a7cef7718f6787ef89c24aa3ffd0fd2a9ced3
cd ..
git clone https://github.com/pennam/Arduino_ESP32_OTA.git
cd Arduino_ESP32_OTA/
git checkout e27f822406986354197a09516edaaeea3ed18e79
cd ..
git clone https://github.com/pennam/BOSSA.git
cd BOSSA
git checkout 43a8feff9dfd07109d25cb2005279dd92e81d8fc
cd ..
git clone https://github.com/arduino-libraries/Arduino_DebugUtils.git
cd ../../../../

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

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
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
Loading