Add Library
This commit is contained in:
parent
e365b9dbd9
commit
3c47103b39
318 changed files with 56465 additions and 0 deletions
112
libraries/ArduinoOTA/src/ArduinoOTA.h
Normal file
112
libraries/ArduinoOTA/src/ArduinoOTA.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright (c) 2018 Juraj Andrassy
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ARDUINOOTA_H_
|
||||
#define _ARDUINOOTA_H_
|
||||
|
||||
#include "WiFiOTA.h"
|
||||
#ifdef __AVR__
|
||||
#if FLASHEND >= 0xFFFF
|
||||
#include "InternalStorageAVR.h"
|
||||
#endif
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#include "InternalStorageESP.h"
|
||||
#else
|
||||
#include "InternalStorage.h"
|
||||
#endif
|
||||
#ifdef __SD_H__
|
||||
#include "SDStorage.h"
|
||||
SDStorageClass SDStorage;
|
||||
#endif
|
||||
#ifdef SerialFlash_h_
|
||||
#include "SerialFlashStorage.h"
|
||||
SerialFlashStorageClass SerialFlashStorage;
|
||||
#endif
|
||||
|
||||
|
||||
template <class NetServer, class NetClient>
|
||||
class ArduinoOTAClass : public WiFiOTAClass {
|
||||
|
||||
private:
|
||||
NetServer server;
|
||||
|
||||
public:
|
||||
ArduinoOTAClass() : server(65280) {};
|
||||
|
||||
void begin(IPAddress localIP, const char* name, const char* password, OTAStorage& storage) {
|
||||
WiFiOTAClass::begin(localIP, name, password, storage);
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void poll() {
|
||||
NetClient client = server.available();
|
||||
pollServer(client);
|
||||
}
|
||||
|
||||
void handle() { // alias
|
||||
poll();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class NetServer, class NetClient, class NetUDP>
|
||||
class ArduinoOTAMdnsClass : public ArduinoOTAClass<NetServer, NetClient> {
|
||||
|
||||
private:
|
||||
NetUDP mdnsSocket;
|
||||
|
||||
public:
|
||||
ArduinoOTAMdnsClass() {};
|
||||
|
||||
void begin(IPAddress localIP, const char* name, const char* password, OTAStorage& storage) {
|
||||
ArduinoOTAClass<NetServer, NetClient>::begin(localIP, name, password, storage);
|
||||
#if defined(ESP8266) && !(defined(ethernet_h_) || defined(ethernet_h) || defined(UIPETHERNET_H))
|
||||
mdnsSocket.beginMulticast(localIP, IPAddress(224, 0, 0, 251), 5353);
|
||||
#else
|
||||
mdnsSocket.beginMulticast(IPAddress(224, 0, 0, 251), 5353);
|
||||
#endif
|
||||
}
|
||||
|
||||
void poll() {
|
||||
ArduinoOTAClass<NetServer, NetClient>::poll();
|
||||
WiFiOTAClass::pollMdns(mdnsSocket);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if defined(ethernet_h_) || defined(ethernet_h) // Ethernet library
|
||||
ArduinoOTAMdnsClass <EthernetServer, EthernetClient, EthernetUDP> ArduinoOTA;
|
||||
|
||||
#elif defined(UIPETHERNET_H) // no UDP multicast implementation yet
|
||||
ArduinoOTAClass <EthernetServer, EthernetClient> ArduinoOTA;
|
||||
|
||||
#elif defined(WiFiNINA_h) || defined(WIFI_H) || defined(ESP8266) || defined(ESP32) // NINA, WiFi101 and Espressif WiFi
|
||||
#include <WiFiUdp.h>
|
||||
ArduinoOTAMdnsClass <WiFiServer, WiFiClient, WiFiUDP> ArduinoOTA;
|
||||
|
||||
#elif defined(WiFi_h) // WiFi and WiFiLink lib (no UDP multicast), for WiFiLink firmware handles mdns
|
||||
ArduinoOTAClass <WiFiServer, WiFiClient> ArduinoOTA;
|
||||
|
||||
#elif defined(_WIFISPI_H_INCLUDED) // no UDP multicast implementation
|
||||
ArduinoOTAClass <WiFiSpiServer, WiFiSpiClient> ArduinoOTA;
|
||||
|
||||
#else
|
||||
#error "Network library not included or not supported"
|
||||
#endif
|
||||
|
||||
#endif
|
159
libraries/ArduinoOTA/src/InternalStorage.cpp
Normal file
159
libraries/ArduinoOTA/src/InternalStorage.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
WiFi101OTA version Feb 2017
|
||||
by Sandeep Mistry (Arduino)
|
||||
modified for ArduinoOTA Dec 2018
|
||||
by Juraj Andrassy
|
||||
*/
|
||||
|
||||
#if !defined(__AVR__) && !defined(ESP8266) && !defined(ESP32)
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "InternalStorage.h"
|
||||
|
||||
InternalStorageClass::InternalStorageClass() :
|
||||
MAX_PARTIONED_SKETCH_SIZE((MAX_FLASH - SKETCH_START_ADDRESS) / 2),
|
||||
STORAGE_START_ADDRESS(SKETCH_START_ADDRESS + MAX_PARTIONED_SKETCH_SIZE)
|
||||
{
|
||||
_writeIndex = 0;
|
||||
_writeAddress = nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// these functions must be in RAM (.data) and NOT inlined
|
||||
// as they erase and copy the sketch data in flash
|
||||
|
||||
__attribute__ ((long_call, noinline, section (".data#"))) //
|
||||
void waitForReady() {
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
while (!NVMCTRL->INTFLAG.bit.READY);
|
||||
#elif defined(ARDUINO_ARCH_NRF5)
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__ ((long_call, noinline, section (".data#")))
|
||||
static void eraseFlash(int address, int length, int pageSize)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
int rowSize = pageSize * 4;
|
||||
for (int i = 0; i < length; i += rowSize) {
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)(address + i)) / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||
|
||||
waitForReady();
|
||||
}
|
||||
#elif defined(ARDUINO_ARCH_NRF5)
|
||||
// Enable erasing flash
|
||||
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
|
||||
|
||||
// Erase page(s)
|
||||
int end_address = address + length;
|
||||
while (address < end_address) {
|
||||
waitForReady();
|
||||
// Erase one 1k/4k page
|
||||
NRF_NVMC->ERASEPAGE = address;
|
||||
address = address + pageSize;
|
||||
}
|
||||
// Disable erasing, enable write
|
||||
waitForReady();
|
||||
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
|
||||
waitForReady();
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__ ((long_call, noinline, section (".data#")))
|
||||
static void copyFlashAndReset(int dest, int src, int length, int pageSize)
|
||||
{
|
||||
uint32_t* d = (uint32_t*)dest;
|
||||
uint32_t* s = (uint32_t*)src;
|
||||
|
||||
eraseFlash(dest, length, pageSize);
|
||||
|
||||
for (int i = 0; i < length; i += 4) {
|
||||
*d++ = *s++;
|
||||
|
||||
waitForReady();
|
||||
}
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
}
|
||||
|
||||
int InternalStorageClass::open(int length)
|
||||
{
|
||||
(void)length;
|
||||
_writeIndex = 0;
|
||||
_writeAddress = (uint32_t*)STORAGE_START_ADDRESS;
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAMD
|
||||
// enable auto page writes
|
||||
NVMCTRL->CTRLB.bit.MANW = 0;
|
||||
#endif
|
||||
|
||||
eraseFlash(STORAGE_START_ADDRESS, MAX_PARTIONED_SKETCH_SIZE, PAGE_SIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t InternalStorageClass::write(uint8_t b)
|
||||
{
|
||||
_addressData.u8[_writeIndex] = b;
|
||||
_writeIndex++;
|
||||
|
||||
if (_writeIndex == 4) {
|
||||
_writeIndex = 0;
|
||||
|
||||
*_writeAddress = _addressData.u32;
|
||||
|
||||
_writeAddress++;
|
||||
|
||||
waitForReady();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InternalStorageClass::close()
|
||||
{
|
||||
while ((int)_writeAddress % PAGE_SIZE) {
|
||||
write(0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void InternalStorageClass::clear()
|
||||
{
|
||||
}
|
||||
|
||||
void InternalStorageClass::apply()
|
||||
{
|
||||
// disable interrupts, as vector table will be erase during flash sequence
|
||||
noInterrupts();
|
||||
|
||||
copyFlashAndReset(SKETCH_START_ADDRESS, STORAGE_START_ADDRESS, MAX_PARTIONED_SKETCH_SIZE, PAGE_SIZE);
|
||||
}
|
||||
|
||||
long InternalStorageClass::maxSize()
|
||||
{
|
||||
return MAX_PARTIONED_SKETCH_SIZE;
|
||||
}
|
||||
|
||||
InternalStorageClass InternalStorage;
|
||||
|
||||
#endif
|
55
libraries/ArduinoOTA/src/InternalStorage.h
Normal file
55
libraries/ArduinoOTA/src/InternalStorage.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
WiFi101OTA version Feb 2017
|
||||
by Sandeep Mistry (Arduino)
|
||||
modified for ArduinoOTA Dec 2018
|
||||
by Juraj Andrassy
|
||||
*/
|
||||
|
||||
#ifndef _INTERNAL_STORAGE_H_INCLUDED
|
||||
#define _INTERNAL_STORAGE_H_INCLUDED
|
||||
|
||||
#include "OTAStorage.h"
|
||||
|
||||
class InternalStorageClass : public OTAStorage {
|
||||
public:
|
||||
|
||||
InternalStorageClass();
|
||||
|
||||
virtual int open(int length);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual void close();
|
||||
virtual void clear();
|
||||
virtual void apply();
|
||||
virtual long maxSize();
|
||||
|
||||
private:
|
||||
const uint32_t MAX_PARTIONED_SKETCH_SIZE, STORAGE_START_ADDRESS;
|
||||
|
||||
union {
|
||||
uint32_t u32;
|
||||
uint8_t u8[4];
|
||||
} _addressData;
|
||||
|
||||
int _writeIndex;
|
||||
uint32_t* _writeAddress;
|
||||
};
|
||||
|
||||
extern InternalStorageClass InternalStorage;
|
||||
|
||||
#endif
|
77
libraries/ArduinoOTA/src/InternalStorageAVR.cpp
Normal file
77
libraries/ArduinoOTA/src/InternalStorageAVR.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright (c) 2018 Juraj Andrassy
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(__AVR__) && FLASHEND >= 0xFFFF
|
||||
|
||||
#include "InternalStorageAVR.h"
|
||||
#include "utility/optiboot.h"
|
||||
|
||||
InternalStorageAVRClass::InternalStorageAVRClass() {
|
||||
maxSketchSize = (MAX_FLASH - bootloaderSize) / 2;
|
||||
maxSketchSize = (maxSketchSize / SPM_PAGESIZE) * SPM_PAGESIZE; // align to page
|
||||
pageAddress = maxSketchSize;
|
||||
pageIndex = 0;
|
||||
}
|
||||
|
||||
int InternalStorageAVRClass::open(int length) {
|
||||
(void)length;
|
||||
pageAddress = maxSketchSize;
|
||||
pageIndex = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t InternalStorageAVRClass::write(uint8_t b) {
|
||||
if (pageIndex == 0) {
|
||||
optiboot_page_erase(pageAddress);
|
||||
}
|
||||
dataWord.u8[pageIndex % 2] = b;
|
||||
if (pageIndex % 2) {
|
||||
optiboot_page_fill(pageAddress + pageIndex, dataWord.u16);
|
||||
}
|
||||
pageIndex++;
|
||||
if (pageIndex == SPM_PAGESIZE) {
|
||||
optiboot_page_write(pageAddress);
|
||||
pageIndex = 0;
|
||||
pageAddress += SPM_PAGESIZE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InternalStorageAVRClass::close() {
|
||||
if (pageIndex) {
|
||||
optiboot_page_write(pageAddress);
|
||||
}
|
||||
pageIndex = 0;
|
||||
}
|
||||
|
||||
void InternalStorageAVRClass::clear() {
|
||||
}
|
||||
|
||||
void InternalStorageAVRClass::apply() {
|
||||
copy_flash_pages_cli(SKETCH_START_ADDRESS, maxSketchSize, (pageAddress - maxSketchSize) / SPM_PAGESIZE + 1, true);
|
||||
}
|
||||
|
||||
long InternalStorageAVRClass::maxSize() {
|
||||
return maxSketchSize;
|
||||
}
|
||||
|
||||
InternalStorageAVRClass InternalStorage;
|
||||
|
||||
#endif
|
50
libraries/ArduinoOTA/src/InternalStorageAVR.h
Normal file
50
libraries/ArduinoOTA/src/InternalStorageAVR.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright (c) 2018 Juraj Andrassy
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INTERNAL_STORAGE_AVR_H_INCLUDED
|
||||
#define _INTERNAL_STORAGE_AVR_H_INCLUDED
|
||||
|
||||
#include "OTAStorage.h"
|
||||
|
||||
class InternalStorageAVRClass : public OTAStorage {
|
||||
public:
|
||||
|
||||
InternalStorageAVRClass();
|
||||
|
||||
virtual int open(int length);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual void close();
|
||||
virtual void clear();
|
||||
virtual void apply();
|
||||
virtual long maxSize();
|
||||
|
||||
private:
|
||||
uint32_t maxSketchSize;
|
||||
uint32_t pageAddress;
|
||||
uint16_t pageIndex;
|
||||
|
||||
union {
|
||||
uint16_t u16;
|
||||
uint8_t u8[2];
|
||||
} dataWord;
|
||||
};
|
||||
|
||||
extern InternalStorageAVRClass InternalStorage;
|
||||
|
||||
#endif
|
64
libraries/ArduinoOTA/src/InternalStorageESP.cpp
Normal file
64
libraries/ArduinoOTA/src/InternalStorageESP.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright (c) 2019 Juraj Andrassy. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef ESP32
|
||||
#include <Update.h>
|
||||
#endif
|
||||
|
||||
#include "InternalStorageESP.h"
|
||||
|
||||
InternalStorageESPClass::InternalStorageESPClass()
|
||||
{
|
||||
}
|
||||
|
||||
int InternalStorageESPClass::open(int length, uint8_t command)
|
||||
{
|
||||
return Update.begin(length, command == 0 ? U_FLASH : U_SPIFFS);
|
||||
}
|
||||
|
||||
size_t InternalStorageESPClass::write(uint8_t b)
|
||||
{
|
||||
return Update.write(&b, 1);
|
||||
}
|
||||
|
||||
void InternalStorageESPClass::close()
|
||||
{
|
||||
Update.end(false);
|
||||
}
|
||||
|
||||
void InternalStorageESPClass::clear()
|
||||
{
|
||||
}
|
||||
|
||||
void InternalStorageESPClass::apply()
|
||||
{
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
long InternalStorageESPClass::maxSize()
|
||||
{
|
||||
return ESP.getFlashChipSize() / 2; // Update.begin() in open() does the exact check
|
||||
}
|
||||
|
||||
InternalStorageESPClass InternalStorage;
|
||||
|
||||
#endif
|
44
libraries/ArduinoOTA/src/InternalStorageESP.h
Normal file
44
libraries/ArduinoOTA/src/InternalStorageESP.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright (c) 2019 Juraj Andrassy. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _INTERNAL_STORAGE_ESP_H_INCLUDED
|
||||
#define _INTERNAL_STORAGE_ESP_H_INCLUDED
|
||||
|
||||
#include "OTAStorage.h"
|
||||
|
||||
class InternalStorageESPClass : public OTAStorage {
|
||||
public:
|
||||
|
||||
InternalStorageESPClass();
|
||||
|
||||
virtual int open(int length) {
|
||||
return open(length, 0);
|
||||
}
|
||||
virtual int open(int length, uint8_t command);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual void close();
|
||||
virtual void clear();
|
||||
virtual void apply();
|
||||
virtual long maxSize();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
extern InternalStorageESPClass InternalStorage;
|
||||
|
||||
#endif
|
58
libraries/ArduinoOTA/src/OTAStorage.cpp
Normal file
58
libraries/ArduinoOTA/src/OTAStorage.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include "OTAStorage.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
static const uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
|
||||
extern "C" {
|
||||
char * __text_start__(); // 0x2000, 0x0 without bootloader and 0x4000 for M0 original bootloader
|
||||
}
|
||||
#elif defined(ARDUINO_ARCH_NRF5)
|
||||
extern "C" {
|
||||
char * __isr_vector();
|
||||
}
|
||||
#elif defined(__AVR__)
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/boot.h>
|
||||
#define MIN_BOOTSZ (4 * SPM_PAGESIZE)
|
||||
#endif
|
||||
|
||||
OTAStorage::OTAStorage() :
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
SKETCH_START_ADDRESS((uint32_t) __text_start__),
|
||||
PAGE_SIZE(pageSizes[NVMCTRL->PARAM.bit.PSZ]),
|
||||
MAX_FLASH(PAGE_SIZE * NVMCTRL->PARAM.bit.NVMP)
|
||||
#elif defined(ARDUINO_ARCH_NRF5)
|
||||
SKETCH_START_ADDRESS((uint32_t) __isr_vector),
|
||||
PAGE_SIZE((size_t) NRF_FICR->CODEPAGESIZE),
|
||||
MAX_FLASH(PAGE_SIZE * (uint32_t) NRF_FICR->CODESIZE)
|
||||
#elif defined(__AVR__)
|
||||
SKETCH_START_ADDRESS(0),
|
||||
PAGE_SIZE(SPM_PAGESIZE),
|
||||
MAX_FLASH((uint32_t) FLASHEND + 1)
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
SKETCH_START_ADDRESS(0), // not used
|
||||
PAGE_SIZE(0), // not used
|
||||
MAX_FLASH(0) // not used
|
||||
#endif
|
||||
{
|
||||
bootloaderSize = 0;
|
||||
#ifdef __AVR__
|
||||
cli();
|
||||
uint8_t highBits = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
|
||||
sei();
|
||||
if (!(highBits & bit(FUSE_BOOTRST))) {
|
||||
byte v = (highBits & ((~FUSE_BOOTSZ1 ) + (~FUSE_BOOTSZ0 )));
|
||||
bootloaderSize = MIN_BOOTSZ << ((v >> 1) ^ 3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExternalOTAStorage::apply() {
|
||||
#ifdef __AVR__
|
||||
wdt_enable(WDTO_15MS);
|
||||
while (true);
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
ESP.restart();
|
||||
#else
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
}
|
69
libraries/ArduinoOTA/src/OTAStorage.h
Normal file
69
libraries/ArduinoOTA/src/OTAStorage.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
WiFi101OTA version Feb 2017
|
||||
by Sandeep Mistry (Arduino)
|
||||
modified for ArduinoOTA Dec 2018, Apr 2019
|
||||
by Juraj Andrassy
|
||||
*/
|
||||
|
||||
#ifndef _OTA_STORAGE_H_INCLUDED
|
||||
#define _OTA_STORAGE_H_INCLUDED
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class OTAStorage {
|
||||
public:
|
||||
|
||||
OTAStorage();
|
||||
|
||||
virtual int open(int length) = 0;
|
||||
virtual int open(int length, uint8_t command) {
|
||||
(void) command;
|
||||
return open(length);
|
||||
}
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void apply() = 0;
|
||||
|
||||
virtual long maxSize() {
|
||||
return (MAX_FLASH - SKETCH_START_ADDRESS - bootloaderSize);
|
||||
}
|
||||
|
||||
protected:
|
||||
const uint32_t SKETCH_START_ADDRESS;
|
||||
const uint32_t PAGE_SIZE;
|
||||
const uint32_t MAX_FLASH;
|
||||
uint32_t bootloaderSize;
|
||||
|
||||
};
|
||||
|
||||
class ExternalOTAStorage : public OTAStorage {
|
||||
|
||||
protected:
|
||||
const char* updateFileName = "UPDATE.BIN";
|
||||
|
||||
public:
|
||||
void setUpdateFileName(const char* _updateFileName) {
|
||||
updateFileName = _updateFileName;
|
||||
}
|
||||
|
||||
virtual void apply();
|
||||
};
|
||||
|
||||
#endif
|
55
libraries/ArduinoOTA/src/SDStorage.h
Normal file
55
libraries/ArduinoOTA/src/SDStorage.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _SD_STORAGE_H_INCLUDED
|
||||
#define _SD_STORAGE_H_INCLUDED
|
||||
|
||||
#include <SD.h>
|
||||
|
||||
#include "OTAStorage.h"
|
||||
|
||||
#ifndef SDCARD_SS_PIN
|
||||
#define SDCARD_SS_PIN 4
|
||||
#endif
|
||||
|
||||
class SDStorageClass : public ExternalOTAStorage {
|
||||
public:
|
||||
|
||||
virtual int open(int length) {
|
||||
_file = SD.open(updateFileName, O_CREAT | O_WRITE);
|
||||
if (!_file)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t b) {
|
||||
return _file.write(b);
|
||||
}
|
||||
virtual void close() {
|
||||
_file.close();
|
||||
}
|
||||
|
||||
virtual void clear() {
|
||||
SD.remove(updateFileName);
|
||||
}
|
||||
|
||||
private:
|
||||
File _file;
|
||||
};
|
||||
|
||||
#endif
|
72
libraries/ArduinoOTA/src/SerialFlashStorage.h
Normal file
72
libraries/ArduinoOTA/src/SerialFlashStorage.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _SERIALFLASH_STORAGE_H_INCLUDED
|
||||
#define _SERIALFLASH_STORAGE_H_INCLUDED
|
||||
|
||||
#include <SerialFlash.h>
|
||||
|
||||
#include "OTAStorage.h"
|
||||
|
||||
#define SERIAL_FLASH_BUFFER_SIZE 64
|
||||
#define SERIAL_FLASH_CS 5
|
||||
|
||||
class SerialFlashStorageClass : public ExternalOTAStorage {
|
||||
public:
|
||||
|
||||
virtual int open(int length) {
|
||||
if (!SerialFlash.begin(SERIAL_FLASH_CS)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!SerialFlash.ready()) {}
|
||||
|
||||
if (SerialFlash.exists(updateFileName)) {
|
||||
SerialFlash.remove(updateFileName);
|
||||
}
|
||||
|
||||
if (SerialFlash.create(updateFileName, length)) {
|
||||
_file = SerialFlash.open(updateFileName);
|
||||
}
|
||||
|
||||
if (!_file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t b) {
|
||||
while (!SerialFlash.ready()) {}
|
||||
int ret = _file.write(&b, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual void close() {
|
||||
_file.close();
|
||||
}
|
||||
|
||||
virtual void clear() {
|
||||
SerialFlash.remove(updateFileName);
|
||||
}
|
||||
|
||||
private:
|
||||
SerialFlashFile _file;
|
||||
};
|
||||
|
||||
#endif
|
358
libraries/ArduinoOTA/src/WiFiOTA.cpp
Normal file
358
libraries/ArduinoOTA/src/WiFiOTA.cpp
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
WiFi101OTA version Feb 2017
|
||||
by Sandeep Mistry (Arduino)
|
||||
modified for ArduinoOTA Dec 2018, Apr 2019
|
||||
by Juraj Andrassy
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "WiFiOTA.h"
|
||||
|
||||
#define BOARD "arduino"
|
||||
#define BOARD_LENGTH (sizeof(BOARD) - 1)
|
||||
|
||||
static String base64Encode(const String& in)
|
||||
{
|
||||
static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
int b;
|
||||
String out;
|
||||
out.reserve((in.length()) * 4 / 3);
|
||||
|
||||
for (unsigned int i = 0; i < in.length(); i += 3) {
|
||||
b = (in.charAt(i) & 0xFC) >> 2;
|
||||
out += CODES[b];
|
||||
|
||||
b = (in.charAt(i) & 0x03) << 4;
|
||||
if (i + 1 < in.length()) {
|
||||
b |= (in.charAt(i + 1) & 0xF0) >> 4;
|
||||
out += CODES[b];
|
||||
b = (in.charAt(i + 1) & 0x0F) << 2;
|
||||
if (i + 2 < in.length()) {
|
||||
b |= (in.charAt(i + 2) & 0xC0) >> 6;
|
||||
out += CODES[b];
|
||||
b = in.charAt(i + 2) & 0x3F;
|
||||
out += CODES[b];
|
||||
} else {
|
||||
out += CODES[b];
|
||||
out += '=';
|
||||
}
|
||||
} else {
|
||||
out += CODES[b];
|
||||
out += "==";
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
WiFiOTAClass::WiFiOTAClass() :
|
||||
_storage(NULL),
|
||||
localIp(0),
|
||||
_lastMdnsResponseTime(0),
|
||||
beforeApplyCallback(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void WiFiOTAClass::begin(IPAddress& localIP, const char* name, const char* password, OTAStorage& storage)
|
||||
{
|
||||
localIp = localIP;
|
||||
_name = name;
|
||||
_expectedAuthorization = "Basic " + base64Encode("arduino:" + String(password));
|
||||
_storage = &storage;
|
||||
}
|
||||
|
||||
void WiFiOTAClass::pollMdns(UDP &_mdnsSocket)
|
||||
{
|
||||
int packetLength = _mdnsSocket.parsePacket();
|
||||
|
||||
if (packetLength <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const byte ARDUINO_SERVICE_REQUEST[37] = {
|
||||
0x00, 0x00, // transaction id
|
||||
0x00, 0x00, // flags
|
||||
0x00, 0x01, // questions
|
||||
0x00, 0x00, // answer RRs
|
||||
0x00, 0x00, // authority RRs
|
||||
0x00, 0x00, // additional RRs
|
||||
0x08,
|
||||
0x5f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, // _arduino
|
||||
0x04,
|
||||
0x5f, 0x74, 0x63, 0x70, // _tcp
|
||||
0x05,
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, // local
|
||||
0x00, 0x0c, // PTR
|
||||
0x00, 0x01 // Class IN
|
||||
};
|
||||
|
||||
if (packetLength != sizeof(ARDUINO_SERVICE_REQUEST)) {
|
||||
while (packetLength) {
|
||||
if (_mdnsSocket.available()) {
|
||||
packetLength--;
|
||||
_mdnsSocket.read();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
byte request[packetLength];
|
||||
|
||||
_mdnsSocket.read(request, sizeof(request));
|
||||
|
||||
if (memcmp(&request[2], &ARDUINO_SERVICE_REQUEST[2], packetLength - 2) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((millis() - _lastMdnsResponseTime) < 1000) {
|
||||
// ignore request
|
||||
return;
|
||||
}
|
||||
_lastMdnsResponseTime = millis();
|
||||
|
||||
_mdnsSocket.beginPacket(IPAddress(224, 0, 0, 251), 5353);
|
||||
|
||||
const byte responseHeader[] = {
|
||||
0x00, 0x00, // transaction id
|
||||
0x84, 0x00, // flags
|
||||
0x00, 0x00, // questions
|
||||
0x00, 0x04, // answers RRs
|
||||
0x00, 0x00, // authority RRs
|
||||
0x00, 0x00 // additional RRS
|
||||
};
|
||||
_mdnsSocket.write(responseHeader, sizeof(responseHeader));
|
||||
|
||||
const byte ptrRecordStart[] = {
|
||||
0x08,
|
||||
'_', 'a', 'r', 'd', 'u', 'i', 'n', 'o',
|
||||
|
||||
0x04,
|
||||
'_', 't', 'c', 'p',
|
||||
|
||||
0x05,
|
||||
'l', 'o', 'c', 'a', 'l',
|
||||
0x00,
|
||||
|
||||
0x00, 0x0c, // PTR
|
||||
0x00, 0x01, // class IN
|
||||
0x00, 0x00, 0x11, 0x94, // TTL
|
||||
|
||||
0x00, (byte)(_name.length() + 3), // length
|
||||
(byte)_name.length()
|
||||
};
|
||||
|
||||
const byte ptrRecordEnd[] = {
|
||||
0xc0, 0x0c
|
||||
};
|
||||
|
||||
_mdnsSocket.write(ptrRecordStart, sizeof(ptrRecordStart));
|
||||
_mdnsSocket.write((const byte*) _name.c_str(), _name.length());
|
||||
_mdnsSocket.write(ptrRecordEnd, sizeof(ptrRecordEnd));
|
||||
|
||||
const byte txtRecord[] = {
|
||||
0xc0, 0x2b,
|
||||
0x00, 0x10, // TXT strings
|
||||
0x80, 0x01, // class
|
||||
0x00, 0x00, 0x11, 0x94, // TTL
|
||||
0x00, (50 + BOARD_LENGTH),
|
||||
13,
|
||||
's', 's', 'h', '_', 'u', 'p', 'l', 'o', 'a', 'd', '=', 'n', 'o',
|
||||
12,
|
||||
't', 'c', 'p', '_', 'c', 'h', 'e', 'c', 'k', '=', 'n', 'o',
|
||||
15,
|
||||
'a', 'u', 't', 'h', '_', 'u', 'p', 'l', 'o', 'a', 'd', '=', 'y', 'e', 's',
|
||||
(6 + BOARD_LENGTH),
|
||||
'b', 'o', 'a', 'r', 'd', '=',
|
||||
};
|
||||
_mdnsSocket.write(txtRecord, sizeof(txtRecord));
|
||||
_mdnsSocket.write((byte*)BOARD, BOARD_LENGTH);
|
||||
|
||||
const byte srvRecordStart[] = {
|
||||
0xc0, 0x2b,
|
||||
0x00, 0x21, // SRV
|
||||
0x80, 0x01, // class
|
||||
0x00, 0x00, 0x00, 0x78, // TTL
|
||||
0x00, (byte)(_name.length() + 9), // length
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0xff, 0x00, // port
|
||||
(byte)_name.length()
|
||||
};
|
||||
|
||||
const byte srvRecordEnd[] = {
|
||||
0xc0, 0x1a
|
||||
};
|
||||
|
||||
_mdnsSocket.write(srvRecordStart, sizeof(srvRecordStart));
|
||||
_mdnsSocket.write((const byte*) _name.c_str(), _name.length());
|
||||
_mdnsSocket.write(srvRecordEnd, sizeof(srvRecordEnd));
|
||||
|
||||
byte aRecordNameOffset = sizeof(responseHeader) +
|
||||
sizeof(ptrRecordStart) + _name.length() + sizeof(ptrRecordEnd) +
|
||||
sizeof(txtRecord) + BOARD_LENGTH +
|
||||
sizeof(srvRecordStart) - 1;
|
||||
|
||||
byte aRecord[] = {
|
||||
0xc0, aRecordNameOffset,
|
||||
|
||||
0x00, 0x01, // A record
|
||||
0x80, 0x01, // class
|
||||
0x00, 0x00, 0x00, 0x78, // TTL
|
||||
0x00, 0x04,
|
||||
0xff, 0xff, 0xff, 0xff // IP
|
||||
};
|
||||
memcpy(&aRecord[sizeof(aRecord) - 4], &localIp, sizeof(localIp));
|
||||
_mdnsSocket.write(aRecord, sizeof(aRecord));
|
||||
|
||||
_mdnsSocket.endPacket();
|
||||
}
|
||||
|
||||
void WiFiOTAClass::pollServer(Client& client)
|
||||
{
|
||||
|
||||
if (client) {
|
||||
String request = client.readStringUntil('\n');
|
||||
request.trim();
|
||||
|
||||
String header;
|
||||
long contentLength = -1;
|
||||
String authorization;
|
||||
|
||||
do {
|
||||
header = client.readStringUntil('\n');
|
||||
header.trim();
|
||||
|
||||
if (header.startsWith("Content-Length: ")) {
|
||||
header.remove(0, 16);
|
||||
|
||||
contentLength = header.toInt();
|
||||
} else if (header.startsWith("Authorization: ")) {
|
||||
header.remove(0, 15);
|
||||
|
||||
authorization = header;
|
||||
}
|
||||
} while (header != "");
|
||||
|
||||
bool dataUpload = false;
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
if (request == "POST /data HTTP/1.1") {
|
||||
dataUpload = true;
|
||||
} else
|
||||
#endif
|
||||
if (request != "POST /sketch HTTP/1.1") {
|
||||
flushRequestBody(client, contentLength);
|
||||
sendHttpResponse(client, 404, "Not Found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_expectedAuthorization != authorization) {
|
||||
flushRequestBody(client, contentLength);
|
||||
sendHttpResponse(client, 401, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (contentLength <= 0) {
|
||||
sendHttpResponse(client, 400, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_storage == NULL || !_storage->open(contentLength, dataUpload)) {
|
||||
flushRequestBody(client, contentLength);
|
||||
sendHttpResponse(client, 500, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (contentLength > _storage->maxSize()) {
|
||||
_storage->close();
|
||||
flushRequestBody(client, contentLength);
|
||||
sendHttpResponse(client, 413, "Payload Too Large");
|
||||
return;
|
||||
}
|
||||
|
||||
long read = 0;
|
||||
byte buff[64];
|
||||
|
||||
while (client.connected() && read < contentLength) {
|
||||
while (client.available()) {
|
||||
int l = client.read(buff, sizeof(buff));
|
||||
for (int i = 0; i < l; i++) {
|
||||
_storage->write(buff[i]);
|
||||
}
|
||||
read += l;
|
||||
}
|
||||
}
|
||||
|
||||
_storage->close();
|
||||
|
||||
if (read == contentLength) {
|
||||
sendHttpResponse(client, 200, "OK");
|
||||
|
||||
delay(500);
|
||||
|
||||
if (beforeApplyCallback) {
|
||||
beforeApplyCallback();
|
||||
}
|
||||
|
||||
// apply the update
|
||||
_storage->apply();
|
||||
|
||||
while (true);
|
||||
} else {
|
||||
|
||||
sendHttpResponse(client, 414, "Payload size wrong");
|
||||
_storage->clear();
|
||||
|
||||
delay(500);
|
||||
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiOTAClass::sendHttpResponse(Client& client, int code, const char* status)
|
||||
{
|
||||
while (client.available()) {
|
||||
client.read();
|
||||
}
|
||||
|
||||
client.print("HTTP/1.1 ");
|
||||
client.print(code);
|
||||
client.print(" ");
|
||||
client.println(status);
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
delay(500);
|
||||
client.stop();
|
||||
}
|
||||
|
||||
void WiFiOTAClass::flushRequestBody(Client& client, long contentLength)
|
||||
{
|
||||
long read = 0;
|
||||
|
||||
while (client.connected() && read < contentLength) {
|
||||
if (client.available()) {
|
||||
read++;
|
||||
|
||||
client.read();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
64
libraries/ArduinoOTA/src/WiFiOTA.h
Normal file
64
libraries/ArduinoOTA/src/WiFiOTA.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright (c) 2017 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
WiFi101OTA version Feb 2017
|
||||
by Sandeep Mistry (Arduino)
|
||||
modified for ArduinoOTA Dec 2018
|
||||
by Juraj Andrassy
|
||||
*/
|
||||
|
||||
#ifndef _WIFI_OTA_H_INCLUDED
|
||||
#define _WIFI_OTA_H_INCLUDED
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Server.h>
|
||||
#include <Client.h>
|
||||
#include <IPAddress.h>
|
||||
#include <Udp.h>
|
||||
|
||||
#include "OTAStorage.h"
|
||||
|
||||
class WiFiOTAClass {
|
||||
protected:
|
||||
WiFiOTAClass();
|
||||
|
||||
void begin(IPAddress& localIP, const char* name, const char* password, OTAStorage& storage);
|
||||
|
||||
void pollMdns(UDP &mdnsSocket);
|
||||
void pollServer(Client& client);
|
||||
|
||||
public:
|
||||
void beforeApply(void (*fn)(void)) {
|
||||
beforeApplyCallback = fn;
|
||||
}
|
||||
|
||||
private:
|
||||
void sendHttpResponse(Client& client, int code, const char* status);
|
||||
void flushRequestBody(Client& client, long contentLength);
|
||||
|
||||
private:
|
||||
String _name;
|
||||
String _expectedAuthorization;
|
||||
OTAStorage* _storage;
|
||||
|
||||
uint32_t localIp;
|
||||
uint32_t _lastMdnsResponseTime;
|
||||
|
||||
void (*beforeApplyCallback)(void);
|
||||
};
|
||||
|
||||
#endif
|
200
libraries/ArduinoOTA/src/utility/optiboot.h
Normal file
200
libraries/ArduinoOTA/src/utility/optiboot.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*------------------------ Optiboot header file ----------------------------|
|
||||
| |
|
||||
| June 2015 by Marek Wodzinski, https://github.com/majekw |
|
||||
| Modified June 2016 by MCUdude, https://github.com/MCUdude |
|
||||
| Modified Dec 2018 by Juraj Andrassy, https://github.com/jandrassy |
|
||||
| Released to public domain |
|
||||
| |
|
||||
| This header file gives possibility to use SPM instruction |
|
||||
| from Optiboot bootloader memory. |
|
||||
| |
|
||||
| There are 5 convenient functions available here: |
|
||||
| * optiboot_page_erase - to erase a FLASH page |
|
||||
| * optiboot_page_fill - to put words into temporary buffer |
|
||||
| * optiboot_page_write - to write contents of temporary buffer into FLASH | |
|
||||
| * optiboot_readPage - higher level function to read a flash page and |
|
||||
| store it in an array |
|
||||
| * optiboot_writePage - higher level function to write content to |
|
||||
| a flash page |
|
||||
| |
|
||||
| For some hardcore users, you could use 'do_spm' as raw entry to |
|
||||
| bootloader spm function. |
|
||||
|-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _OPTIBOOT_H_
|
||||
#define _OPTIBOOT_H_ 1
|
||||
|
||||
#include <avr/boot.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
/*
|
||||
* Main 'magic' function - enter to bootloader do_spm function
|
||||
*
|
||||
* address - address to write (in bytes) but must be even number
|
||||
* command - one of __BOOT_PAGE_WRITE, __BOOT_PAGE_ERASE or __BOOT_PAGE_FILL
|
||||
* data - data to write in __BOOT_PAGE_FILL. In __BOOT_PAGE_ERASE or
|
||||
* __BOOT_PAGE_WRITE it control if boot_rww_enable is run
|
||||
* (0 = run, !0 = skip running boot_rww_enable)
|
||||
*
|
||||
*/
|
||||
|
||||
// 'typedef' (in following line) and 'const' (few lines below) are a way to define external function at some arbitrary address
|
||||
typedef void (*do_spm_t)(uint16_t address, uint8_t command, uint16_t data);
|
||||
typedef void (*copy_flash_pages_t)(uint32_t dest, uint32_t src, uint16_t page_count, uint8_t reset);
|
||||
|
||||
|
||||
/*
|
||||
* Devices with more than 64KB of flash:
|
||||
* - have larger bootloader area (1KB) (they are BIGBOOT targets)
|
||||
* - have RAMPZ register :-)
|
||||
* - need larger variable to hold address (pgmspace.h uses uint32_t)
|
||||
*/
|
||||
#ifdef RAMPZ
|
||||
typedef uint32_t optiboot_addr_t;
|
||||
#else
|
||||
typedef uint16_t optiboot_addr_t;
|
||||
#endif
|
||||
|
||||
#if FLASHEND > 65534
|
||||
const do_spm_t do_spm = (do_spm_t)((FLASHEND-1023+2)>>1);
|
||||
const copy_flash_pages_t copy_flash_pages = (copy_flash_pages_t)((FLASHEND-1023+4)>>1);
|
||||
#else
|
||||
const do_spm_t do_spm = (do_spm_t)((FLASHEND-511+2)>>1);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The same as do_spm but with disable/restore interrupts state
|
||||
* required to succesfull SPM execution
|
||||
*
|
||||
* On devices with more than 64kB flash, 16 bit address is not enough,
|
||||
* so there is also RAMPZ used in that case.
|
||||
*
|
||||
* On devices with more than 128kB flash, 16 bit word address is not enough
|
||||
* for a function call above 0x20000, so there is also EIND used in that case.
|
||||
*/
|
||||
void do_spm_cli(optiboot_addr_t address, uint8_t command, uint16_t data) {
|
||||
uint8_t sreg_save;
|
||||
|
||||
sreg_save = SREG; // save old SREG value
|
||||
asm volatile("cli"); // disable interrupts
|
||||
#ifdef RAMPZ
|
||||
RAMPZ = (address >> 16) & 0xff; // address bits 23-16 goes to RAMPZ
|
||||
#ifdef EIND
|
||||
uint8_t eind = EIND;
|
||||
EIND = FLASHEND / 0x20000;
|
||||
#endif
|
||||
do_spm((address & 0xffff), command, data); // do_spm accepts only lower 16 bits of address
|
||||
#ifdef EIND
|
||||
EIND = eind;
|
||||
#endif
|
||||
#else
|
||||
do_spm(address, command, data); // 16 bit address - no problems to pass directly
|
||||
#endif
|
||||
SREG = sreg_save; // restore last interrupts state
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy contents of the flash pages. Addresses must be aligned to page boundary.
|
||||
*
|
||||
* On devices with more than 128kB flash, 16 bit word address is not enough
|
||||
* for a function call above 0x20000, so there is also EIND used in that case.
|
||||
*
|
||||
* If reset_mcu is true, watchdog is used to reset the MCU after pages are copied.
|
||||
* That enables to copy a new version of application from upper half of the flash.
|
||||
*/
|
||||
#if FLASHEND > 65534
|
||||
void copy_flash_pages_cli(uint32_t dest, uint32_t src, uint16_t page_count, uint8_t reset_mcu) {
|
||||
uint8_t sreg_save = SREG; // save old SREG value
|
||||
asm volatile("cli"); // disable interrupts
|
||||
#ifdef EIND
|
||||
uint8_t eind = EIND;
|
||||
EIND = FLASHEND / 0x20000;
|
||||
#endif
|
||||
copy_flash_pages(dest, src, page_count, reset_mcu);
|
||||
#ifdef EIND
|
||||
EIND = eind;
|
||||
#endif
|
||||
SREG = sreg_save; // restore last interrupts state
|
||||
}
|
||||
#endif
|
||||
|
||||
// Erase page in FLASH
|
||||
void optiboot_page_erase(optiboot_addr_t address) {
|
||||
do_spm_cli(address, __BOOT_PAGE_ERASE, 0);
|
||||
}
|
||||
|
||||
|
||||
// Write word into temporary buffer
|
||||
void optiboot_page_fill(optiboot_addr_t address, uint16_t data) {
|
||||
do_spm_cli(address, __BOOT_PAGE_FILL, data);
|
||||
}
|
||||
|
||||
|
||||
//Write temporary buffer into FLASH
|
||||
void optiboot_page_write(optiboot_addr_t address) {
|
||||
do_spm_cli(address, __BOOT_PAGE_WRITE, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Higher level functions for reading and writing from flash
|
||||
* See the examples for more info on how to use these functions
|
||||
*/
|
||||
|
||||
// Function to read a flash page and store it in an array (storage_array[])
|
||||
void optiboot_readPage(const uint8_t allocated_flash_space[], uint8_t storage_array[], uint16_t page, char blank_character)
|
||||
{
|
||||
uint8_t read_character;
|
||||
for(uint16_t j = 0; j < SPM_PAGESIZE; j++)
|
||||
{
|
||||
read_character = pgm_read_byte(&allocated_flash_space[j + SPM_PAGESIZE*(page-1)]);
|
||||
if(read_character != 0 && read_character != 255)
|
||||
storage_array[j] = read_character;
|
||||
else
|
||||
storage_array[j] = blank_character;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Function to read a flash page and store it in an array (storage_array[]), but without blank_character
|
||||
void optiboot_readPage(const uint8_t allocated_flash_space[], uint8_t storage_array[], uint16_t page)
|
||||
{
|
||||
uint8_t read_character;
|
||||
for(uint16_t j = 0; j < SPM_PAGESIZE; j++)
|
||||
{
|
||||
read_character = pgm_read_byte(&allocated_flash_space[j + SPM_PAGESIZE*(page-1)]);
|
||||
if(read_character != 0 && read_character != 255)
|
||||
storage_array[j] = read_character;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Function to write data to a flash page
|
||||
void optiboot_writePage(const uint8_t allocated_flash_space[], uint8_t data_to_store[], uint16_t page)
|
||||
{
|
||||
uint16_t word_buffer = 0;
|
||||
|
||||
// Erase the flash page
|
||||
optiboot_page_erase((optiboot_addr_t)(void*) &allocated_flash_space[SPM_PAGESIZE*(page-1)]);
|
||||
|
||||
// Copy ram buffer to temporary flash buffer
|
||||
for(uint16_t i = 0; i < SPM_PAGESIZE; i++)
|
||||
{
|
||||
if(i % 2 == 0) // We must write words
|
||||
word_buffer = data_to_store[i];
|
||||
else
|
||||
{
|
||||
word_buffer += (data_to_store[i] << 8);
|
||||
optiboot_page_fill((optiboot_addr_t)(void*) &allocated_flash_space[i + SPM_PAGESIZE*(page-1)], word_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Writing temporary buffer to flash
|
||||
optiboot_page_write((optiboot_addr_t)(void*) &allocated_flash_space[SPM_PAGESIZE*(page-1)]);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _OPTIBOOT_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue