mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Fixes and HTTP Post update example
Because eboot first erases the space required for the new sketch, and if the new sketch is larger then the old one, with the old way, part of the beginning of new sketch will be deleted. Therefore for now I opted to keep the max update size either half the available space for sketches or what's left from the first one, whichever is smaller. To be able to create a simple post mechanism for updates, I needed to have a way to write the new binary, without knowing it's final size, so I added an option to the end() method. Example in the WebServer examples.
This commit is contained in:
parent
3427299065
commit
0d969e9760
@ -350,7 +350,7 @@ uint32_t EspClass::getFreeSketchSpace() {
|
||||
uint32_t usedSize = getSketchSize();
|
||||
// round one sector up
|
||||
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000;
|
||||
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000 - (5 * FLASH_SECTOR_SIZE);
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd);
|
||||
|
@ -35,11 +35,14 @@ bool UpdaterClass::begin(size_t size){
|
||||
_error = 0;
|
||||
|
||||
uint32_t usedSize = ESP.getSketchSize();
|
||||
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000;
|
||||
uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000 - (5 * FLASH_SECTOR_SIZE);
|
||||
uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
uint32_t freeSpaceStart = freeSpaceEnd - roundedSize;
|
||||
|
||||
if(roundedSize > (freeSpaceEnd - freeSpaceStart)){
|
||||
//new sketch can not be more then half the size or more than the free space
|
||||
//this means that max sketch size is (1MB - 20KB) / 2 for flash 2MB and above
|
||||
//and the current sketch should not be more than that either
|
||||
if(freeSpaceStart < usedSize || roundedSize > (freeSpaceEnd/2)){
|
||||
_error = UPDATE_ERROR_SPACE;
|
||||
#ifdef DEBUG_UPDATER
|
||||
printError(DEBUG_UPDATER);
|
||||
@ -64,7 +67,7 @@ bool UpdaterClass::begin(size_t size){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdaterClass::end(){
|
||||
bool UpdaterClass::end(bool evenIfRemaining){
|
||||
if(_size == 0){
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.println("no update");
|
||||
@ -72,27 +75,39 @@ bool UpdaterClass::end(){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_buffer) os_free(_buffer);
|
||||
_bufferLen = 0;
|
||||
|
||||
if(hasError() || !isFinished()){
|
||||
if(hasError() || (!isFinished() && !evenIfRemaining)){
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
|
||||
#endif
|
||||
if(_buffer) os_free(_buffer);
|
||||
_bufferLen = 0;
|
||||
_currentAddress = 0;
|
||||
_startAddress = 0;
|
||||
_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(evenIfRemaining){
|
||||
if(_bufferLen > 0){
|
||||
_writeBuffer();
|
||||
}
|
||||
_size = progress();
|
||||
}
|
||||
if(_buffer) os_free(_buffer);
|
||||
_bufferLen = 0;
|
||||
_currentAddress = 0;
|
||||
|
||||
eboot_command ebcmd;
|
||||
ebcmd.action = ACTION_COPY_RAW;
|
||||
ebcmd.args[0] = _startAddress;
|
||||
ebcmd.args[1] = 0x00000;
|
||||
ebcmd.args[2] = _size;
|
||||
eboot_command_write(&ebcmd);
|
||||
|
||||
_currentAddress = 0;
|
||||
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size);
|
||||
#endif
|
||||
|
||||
_startAddress = 0;
|
||||
_size = 0;
|
||||
_error = UPDATE_ERROR_OK;
|
||||
|
@ -40,12 +40,12 @@ class UpdaterClass {
|
||||
If all bytes are written
|
||||
this call will write the config to eboot
|
||||
and return true
|
||||
If there is already an update running but is not finished
|
||||
If there is already an update running but is not finished and !evenIfRemainanig
|
||||
or there is an error
|
||||
this will clear everything and return false
|
||||
the last error is available through getError()
|
||||
*/
|
||||
bool end();
|
||||
bool end(bool evenIfRemaining = false);
|
||||
|
||||
/*
|
||||
Prints the last error to an output stream
|
||||
|
70
libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino
Normal file
70
libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino
Normal file
@ -0,0 +1,70 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
|
||||
const char* host = "esp8266-webupdate";
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
|
||||
|
||||
void setup(void){
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println("Booting Sketch...");
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
if(WiFi.waitForConnectResult() == WL_CONNECTED){
|
||||
MDNS.begin(host);
|
||||
server.on("/", HTTP_GET, [](){
|
||||
server.sendHeader("Connection", "close");
|
||||
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||
server.send(200, "text/html", serverIndex);
|
||||
});
|
||||
server.onFileUpload([](){
|
||||
if(server.uri() != "/update") return;
|
||||
HTTPUpload& upload = server.upload();
|
||||
if(upload.status == UPLOAD_FILE_START){
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||
uint32_t maxSketchSpace = ((ESP.getFreeSketchSpace() + ESP.getSketchSize()) / 2) & 0xFFFFF000;
|
||||
if(!Update.begin(maxSketchSpace)){//start with max available size
|
||||
Update.printError(Serial);
|
||||
return;
|
||||
}
|
||||
} else if(upload.status == UPLOAD_FILE_WRITE){
|
||||
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
|
||||
Update.printError(Serial);
|
||||
return;
|
||||
}
|
||||
} else if(upload.status == UPLOAD_FILE_END){
|
||||
if(Update.end(true)){ //true to set the size to the current progress
|
||||
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||
} else {
|
||||
Update.printError(Serial);
|
||||
}
|
||||
Serial.setDebugOutput(false);
|
||||
}
|
||||
yield();
|
||||
});
|
||||
server.on("/update", HTTP_POST, [](){
|
||||
server.sendHeader("Connection", "close");
|
||||
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
|
||||
ESP.restart();
|
||||
});
|
||||
server.begin();
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
|
||||
Serial.println("Ready! Open http:\/\/%s.local in your browser\n", host);
|
||||
} else {
|
||||
Serial.println("WiFi Failed");
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
delay(1);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user