diff --git a/boards.txt b/boards.txt index 12d639290..22a168c5b 100644 --- a/boards.txt +++ b/boards.txt @@ -27,6 +27,7 @@ generic.build.spiffs_pagesize=256 generic.menu.UploadTool.esptool=Serial generic.menu.UploadTool.esptool.upload.tool=esptool +generic.menu.UploadTool.esptool.upload.verbose=-vv generic.menu.UploadTool.espota=OTA generic.menu.UploadTool.espota.upload.tool=espota @@ -169,6 +170,10 @@ huzzah.menu.CpuFrequency.80.build.f_cpu=80000000L huzzah.menu.CpuFrequency.160=160 MHz huzzah.menu.CpuFrequency.160.build.f_cpu=160000000L +huzzah.menu.UploadTool.esptool=Serial +huzzah.menu.UploadTool.esptool.upload.tool=esptool +huzzah.menu.UploadTool.esptool.upload.verbose=-vv + huzzah.menu.UploadSpeed.115200=115200 huzzah.menu.UploadSpeed.115200.upload.speed=115200 huzzah.menu.UploadSpeed.9600=9600 @@ -222,6 +227,10 @@ nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L nodemcu.menu.CpuFrequency.160=160 MHz nodemcu.menu.CpuFrequency.160.build.f_cpu=160000000L +nodemcu.menu.UploadTool.esptool=Serial +nodemcu.menu.UploadTool.esptool.upload.tool=esptool +nodemcu.menu.UploadTool.esptool.upload.verbose=-vv + nodemcu.menu.UploadSpeed.115200=115200 nodemcu.menu.UploadSpeed.115200.upload.speed=115200 nodemcu.menu.UploadSpeed.9600=9600 @@ -284,6 +293,10 @@ nodemcuv2.menu.CpuFrequency.80.build.f_cpu=80000000L nodemcuv2.menu.CpuFrequency.160=160 MHz nodemcuv2.menu.CpuFrequency.160.build.f_cpu=160000000L +nodemcuv2.menu.UploadTool.esptool=Serial +nodemcuv2.menu.UploadTool.esptool.upload.tool=esptool +nodemcuv2.menu.UploadTool.esptool.upload.verbose=-vv + nodemcuv2.menu.UploadSpeed.115200=115200 nodemcuv2.menu.UploadSpeed.115200.upload.speed=115200 nodemcuv2.menu.UploadSpeed.9600=9600 @@ -353,6 +366,10 @@ modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L modwifi.menu.CpuFrequency.160=160 MHz modwifi.menu.CpuFrequency.160.build.f_cpu=160000000L +modwifi.menu.UploadTool.esptool=Serial +modwifi.menu.UploadTool.esptool.upload.tool=esptool +modwifi.menu.UploadTool.esptool.upload.verbose=-vv + modwifi.menu.UploadSpeed.115200=115200 modwifi.menu.UploadSpeed.115200.upload.speed=115200 modwifi.menu.UploadSpeed.9600=9600 @@ -405,6 +422,10 @@ thing.menu.CpuFrequency.80.build.f_cpu=80000000L thing.menu.CpuFrequency.160=160 MHz thing.menu.CpuFrequency.160.build.f_cpu=160000000L +thing.menu.UploadTool.esptool=Serial +thing.menu.UploadTool.esptool.upload.tool=esptool +thing.menu.UploadTool.esptool.upload.verbose=-vv + thing.menu.UploadSpeed.115200=115200 thing.menu.UploadSpeed.115200.upload.speed=115200 thing.menu.UploadSpeed.9600=9600 @@ -450,6 +471,10 @@ esp210.menu.CpuFrequency.80.build.f_cpu=80000000L esp210.menu.CpuFrequency.160=160 MHz esp210.menu.CpuFrequency.160.build.f_cpu=160000000L +esp210.menu.UploadTool.esptool=Serial +esp210.menu.UploadTool.esptool.upload.tool=esptool +esp210.menu.UploadTool.esptool.upload.verbose=-vv + esp210.menu.UploadSpeed.57600=57600 esp210.menu.UploadSpeed.57600.upload.speed=57600 esp210.menu.UploadSpeed.115200=115200 diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 511f916c8..f92344b84 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -118,7 +118,9 @@ ICACHE_FLASH_ATTR String::String(double value, unsigned char decimalPlaces) { } ICACHE_FLASH_ATTR String::~String() { - free(buffer); + if(buffer) { + free(buffer); + } } // /*********************************************/ diff --git a/libraries/ArduinoOTA/ArduinoOTA.cpp b/libraries/ArduinoOTA/ArduinoOTA.cpp new file mode 100644 index 000000000..82b4d1411 --- /dev/null +++ b/libraries/ArduinoOTA/ArduinoOTA.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include "ArduinoOTA.h" + +ArduinoOTA::ArduinoOTA(const char *mdns_host_prefix, int port, bool serial_debug) +{ + _port = port; + _mdns_host = new String(mdns_host_prefix); + *_mdns_host += String(ESP.getChipId(), HEX); + _udp_ota = new WiFiUDP(); + _serial_debug = serial_debug; + + _start_callback = NULL; + _end_callback = NULL; + _progress_callback = NULL; + _error_callback = NULL; +} + +void ArduinoOTA::onStart(OTA_CALLBACK(fn)){ + _start_callback = fn; +} + +void ArduinoOTA::onEnd(OTA_CALLBACK(fn)){ + _end_callback = fn; +} + +void ArduinoOTA::onProgress(OTA_CALLBACK_PROGRESS(fn)){ + _progress_callback = fn; +} + +void ArduinoOTA::onError(OTA_CALLBACK(fn)){ + _error_callback = fn; +} + +ArduinoOTA::~ArduinoOTA(){ + delete _udp_ota; + delete _mdns_host; +} + +void ArduinoOTA::setup() { + _udp_ota->begin(_port); + if (_mdns_host) { + if (_serial_debug) + Serial.printf("OTA server at: %s:%u\n", + _mdns_host->c_str(), + _port); + MDNS.begin(_mdns_host->c_str()); + MDNS.addService("arduino", "tcp", _port); + } +} + +void ArduinoOTA::handle() { + + if (!_udp_ota->parsePacket()) return; + + IPAddress remote = _udp_ota->remoteIP(); + int cmd = _udp_ota->parseInt(); + int port = _udp_ota->parseInt(); + int size = _udp_ota->parseInt(); + + if (_serial_debug){ + Serial.print("Update Start: ip:"); + Serial.print(remote); + Serial.printf(", port:%d, size:%d\n", port, size); + } + + WiFiUDP::stopAll(); + + if(!Update.begin(size)){ + if (_serial_debug) + Serial.println("Update Begin Error"); + if (_error_callback) _error_callback(); + _udp_ota->begin(_port); + return; + } + if (_start_callback) _start_callback(); + if (_progress_callback) _progress_callback(0, size); + + WiFiClient client; + if (!client.connect(remote, port)) { + if (_serial_debug) + Serial.printf("Connect Failed\n"); + _udp_ota->begin(_port); + if (_error_callback) _error_callback(); + } + + uint32_t written; + while(!Update.isFinished() && client.connected()){ + // TODO(mangelajo): enhance the Update.write(client) to + // accept a progress callback + written = Update.write(client); + if(written > 0) client.print(written, DEC); + if(_progress_callback) _progress_callback(written, size); + } + + Serial.setDebugOutput(false); + + if(Update.end()){ + client.println("OK"); + if (_serial_debug) + Serial.printf("Update Success\nRebooting...\n"); + if(_end_callback) _end_callback(); + ESP.restart(); + } else { + // Update failed: listen UDP again, callback and print + _udp_ota->begin(_port); + if (_error_callback) _error_callback(); + Update.printError(client); + if (_serial_debug) + Update.printError(Serial); + } +} diff --git a/libraries/ArduinoOTA/ArduinoOTA.h b/libraries/ArduinoOTA/ArduinoOTA.h new file mode 100644 index 000000000..1413306e8 --- /dev/null +++ b/libraries/ArduinoOTA/ArduinoOTA.h @@ -0,0 +1,35 @@ +#ifndef __ARDUINO_OTA_H +#define __ARDUINO_OTA_H + +class WiFiUDP; + +#define OTA_CALLBACK(callback) void (*callback)() +#define OTA_CALLBACK_PROGRESS(callback) void (*callback)(unsigned int, unsigned int) + +class ArduinoOTA +{ + int _port; + String* _mdns_host; + WiFiUDP* _udp_ota; + bool _serial_debug; + + OTA_CALLBACK(_start_callback); + OTA_CALLBACK(_end_callback); + OTA_CALLBACK(_error_callback); + + OTA_CALLBACK_PROGRESS(_progress_callback); + + public: + ArduinoOTA(const char *mdns_host="ESP8266-OTA-", + int port=8266, + bool serial_debug=true); + ~ArduinoOTA(); + void setup(); + void handle(); + void onStart(OTA_CALLBACK(fn)); + void onEnd(OTA_CALLBACK(fn)); + void onProgress(OTA_CALLBACK_PROGRESS(fn)); + void onError(OTA_CALLBACK (fn)); +}; + +#endif /* __ARDUINO_OTA_H */ diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino new file mode 100644 index 000000000..0f8967f89 --- /dev/null +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +const char* ssid = "..."; +const char* password = "..."; + +ArduinoOTA ota_server; + +void setup() { + Serial.begin(115200); + + Serial.println("Booting"); + WiFi.mode(WIFI_STA); + + /* try the flash stored password first */ + WiFi.begin(); + + while (WiFi.waitForConnectResult() != WL_CONNECTED){ + WiFi.begin(ssid, password); + Serial.println("Retrying connection..."); + } + ota_server.setup(); + Serial.println("Ready"); +} + +void loop() { + ota_server.handle(); + yield(); +} diff --git a/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino b/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino new file mode 100644 index 000000000..208e0be08 --- /dev/null +++ b/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +const char* ssid = "..."; +const char* password = "..."; +const char* host_prefix = "OTA-LEDS-"; + +ArduinoOTA ota_server(host_prefix, 8266, /* debug_serial= */ true); + +int led_pin = 13; +#define N_DIMMERS 3 +int dimmer_pin[] = {14, 5, 15}; + +void setup() { + Serial.begin(115200); + + /* switch on led */ + pinMode(led_pin, OUTPUT); + digitalWrite(led_pin, LOW); + + Serial.println("Booting"); + WiFi.mode(WIFI_STA); + + /* try the flash stored password first */ + WiFi.begin(); + + while (WiFi.waitForConnectResult() != WL_CONNECTED){ + WiFi.begin(ssid, password); + Serial.println("Retrying connection..."); + } + /* switch off led */ + digitalWrite(led_pin, HIGH); + + /* setup the OTA server */ + ota_server.setup(); + Serial.println("Ready"); + + /* configure dimmers, and OTA server events */ + analogWriteRange(1000); + analogWrite(led_pin,990); + + for (int i=0; i +sentence=Enables Over The Air upgrades, via wifi and espota.py UDP request/TCP download. +paragraph=With this library you can enable your sketch to be upgraded over network. Includes mdns anounces to get discovered by the arduino IDE. +category=Communication +url= +architectures=esp8266 diff --git a/libraries/DNSServer/src/DNSServer.cpp b/libraries/DNSServer/src/DNSServer.cpp index 5cd5535da..3c31717b0 100644 --- a/libraries/DNSServer/src/DNSServer.cpp +++ b/libraries/DNSServer/src/DNSServer.cpp @@ -13,6 +13,7 @@ bool DNSServer::start(const uint16_t &port, const String &domainName, const IPAddress &resolvedIP) { _port = port; + _buffer = NULL; _domainName = domainName; _resolvedIP[0] = resolvedIP[0]; _resolvedIP[1] = resolvedIP[1]; @@ -35,6 +36,8 @@ void DNSServer::setTTL(const uint32_t &ttl) void DNSServer::stop() { _udp.stop(); + free(_buffer); + _buffer = NULL; } void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName) @@ -48,7 +51,9 @@ void DNSServer::processNextRequest() _currentPacketSize = _udp.parsePacket(); if (_currentPacketSize) { + if (_buffer != NULL) free(_buffer); _buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char)); + if (_buffer == NULL) return; _udp.read(_buffer, _currentPacketSize); _dnsHeader = (DNSHeader*) _buffer; @@ -66,6 +71,7 @@ void DNSServer::processNextRequest() } free(_buffer); + _buffer = NULL; } } @@ -80,6 +86,7 @@ bool DNSServer::requestIncludesOnlyOneQuestion() String DNSServer::getDomainNameWithoutWwwPrefix() { String parsedDomainName = ""; + if (_buffer == NULL) return parsedDomainName; unsigned char *start = _buffer + 12; if (*start == 0) { @@ -109,6 +116,7 @@ String DNSServer::getDomainNameWithoutWwwPrefix() void DNSServer::replyWithIP() { + if (_buffer == NULL) return; _dnsHeader->QR = DNS_QR_RESPONSE; _dnsHeader->ANCount = _dnsHeader->QDCount; _dnsHeader->QDCount = _dnsHeader->QDCount; @@ -152,6 +160,7 @@ void DNSServer::replyWithIP() void DNSServer::replyWithCustomCode() { + if (_buffer == NULL) return; _dnsHeader->QR = DNS_QR_RESPONSE; _dnsHeader->RCode = (unsigned char)_errorReplyCode; _dnsHeader->QDCount = 0; @@ -159,4 +168,4 @@ void DNSServer::replyWithCustomCode() _udp.beginPacket(_udp.remoteIP(), _udp.remotePort()); _udp.write(_buffer, sizeof(DNSHeader)); _udp.endPacket(); -} \ No newline at end of file +} diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index f0ab929f3..7e9e75870 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -222,7 +222,7 @@ void ESP8266WebServer::sendContent_P(PGM_P content) { } else { // reached terminator - contentUnitLen = contentNext - content; + contentUnitLen = contentNext - contentUnit; content = NULL; } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index f40014e55..b3c522579 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -370,6 +370,12 @@ IPAddress ESP8266WiFiClass::gatewayIP() return IPAddress(ip.gw.addr); } +IPAddress ESP8266WiFiClass::dnsIP(int dns_no) +{ + ip_addr_t dns_ip = dns_getserver(dns_no); + return IPAddress(dns_ip.addr); +} + String ESP8266WiFiClass::SSID() const { static struct station_config conf; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/ESP8266WiFi/src/ESP8266WiFi.h index 70538127f..4fcc21f26 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -168,6 +168,13 @@ public: */ IPAddress gatewayIP(); + /* + * Get the DNS ip address. + * + * return: DNS ip address value + */ + IPAddress dnsIP(int dns_no = 0); + /* * Return the current SSID associated with the network * diff --git a/libraries/ESP8266mDNS/ESP8266mDNS.cpp b/libraries/ESP8266mDNS/ESP8266mDNS.cpp index 0767d14e0..687f88623 100644 --- a/libraries/ESP8266mDNS/ESP8266mDNS.cpp +++ b/libraries/ESP8266mDNS/ESP8266mDNS.cpp @@ -134,7 +134,7 @@ bool MDNSResponder::begin(const char* domain){ } void MDNSResponder::update() { - if (!_conn->next()) { + if (!_conn || !_conn->next()) { return; } _parsePacket(); diff --git a/libraries/Servo/src/esp8266/Servo.cpp b/libraries/Servo/src/esp8266/Servo.cpp index 9893156a3..637265cd3 100644 --- a/libraries/Servo/src/esp8266/Servo.cpp +++ b/libraries/Servo/src/esp8266/Servo.cpp @@ -28,7 +28,7 @@ const uint32_t c_CycleCompensation = 4; // compensation us to trim adjust for d struct ServoInfo { uint8_t pin : 6; // a pin number from 0 to 63 - uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false + uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false }; struct ServoState { @@ -57,7 +57,11 @@ static uint8_t s_servoCount = 0; // the total number of attached s_se // Interrupt handler template method that takes a class that implements // a standard set of methods for the timer abstraction //------------------------------------------------------------------------------ -template void Servo_Handler(T* timer) +template +static void Servo_Handler(T* timer) ICACHE_RAM_ATTR; + +template +static void Servo_Handler(T* timer) { uint8_t servoIndex; @@ -75,7 +79,7 @@ template void Servo_Handler(T* timer) } timer->nextChannel(); } - + servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel()); if (servoIndex < s_servoCount && timer->getCurrentChannel() < SERVOS_PER_TIMER) { @@ -96,20 +100,32 @@ template void Servo_Handler(T* timer) // at least REFRESH_INTERVAL has elapsed timer->SetCycleCompare(timer->GetCycleCount() + c_CycleCompensation * 2); } - + timer->setEndOfCycle(); } } +static void handler0() ICACHE_RAM_ATTR; +static void handler0() +{ + Servo_Handler(&s_servoTimer0); +} + +static void handler1() ICACHE_RAM_ATTR; +static void handler1() +{ + Servo_Handler(&s_servoTimer1); +} + static void initISR(ServoTimerSequence timerId) { #if !defined (SERVO_EXCLUDE_TIMER0) if (timerId == ServoTimerSequence_Timer0) - s_servoTimer0.InitInterrupt([]() {Servo_Handler(&s_servoTimer0); }); + s_servoTimer0.InitInterrupt(&handler0); #endif #if !defined (SERVO_EXCLUDE_TIMER1) if (timerId == ServoTimerSequence_Timer1) - s_servoTimer1.InitInterrupt([]() {Servo_Handler(&s_servoTimer1); }); + s_servoTimer1.InitInterrupt(&handler1); #endif } @@ -169,13 +185,13 @@ uint8_t Servo::attach(int pin, int minUs, int maxUs) pinMode(pin, OUTPUT); // set servo pin to output digitalWrite(pin, LOW); s_servos[_servoIndex].info.pin = pin; - + // keep the min and max within 200-3000 us, these are extreme - // ranges and should support extreme servos while maintaining + // ranges and should support extreme servos while maintaining // reasonable ranges _maxUs = max(250, min(3000, maxUs)); _minUs = max(200, min(_maxUs, minUs)); - + // initialize the timerId if it has not already been initialized timerId = SERVO_INDEX_TO_TIMER(_servoIndex); if (!isTimerActive(timerId)) { @@ -242,5 +258,4 @@ bool Servo::attached() return s_servos[_servoIndex].info.isActive; } -#endif - +#endif diff --git a/libraries/Servo/src/esp8266/ServoTimers.h b/libraries/Servo/src/esp8266/ServoTimers.h index 56ee18671..1bfac5fb4 100644 --- a/libraries/Servo/src/esp8266/ServoTimers.h +++ b/libraries/Servo/src/esp8266/ServoTimers.h @@ -18,7 +18,7 @@ // // Defines for timer abstractions used with Servo library -// +// // ServoTimerSequence enumerates the sequence that the timers should be allocated // ServoTimerSequence_COUNT indicates how many timers are available. // @@ -47,7 +47,7 @@ public: } - uint32_t usToTicks(uint32_t us) const + uint32_t usToTicks(uint32_t us) const { return (clockCyclesPerMicrosecond() * us); // converts microseconds to tick } @@ -56,7 +56,7 @@ public: return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds } - void InitInterrupt(timercallback handler) + void InitInterrupt(timercallback handler) { timer0_isr_init(); timer0_attachInterrupt(handler); @@ -64,7 +64,7 @@ public: void ResetInterrupt() {}; // timer0 doesn't have a clear interrupt - void StopInterrupt() + void StopInterrupt() { timer0_detachInterrupt(); } @@ -74,7 +74,7 @@ public: timer0_write(ESP.getCycleCount() + value); } - void SetCycleCompare(uint32_t value) + void SetCycleCompare(uint32_t value) { timer0_write(_cycleStart + value); } @@ -96,12 +96,12 @@ public: return _currentChannel; } - void nextChannel() + void nextChannel() { _currentChannel++; } - void setEndOfCycle() + void setEndOfCycle() { _currentChannel = -1; } @@ -111,7 +111,7 @@ public: return (_currentChannel == -1); } - ServoTimerSequence timerId() const + ServoTimerSequence timerId() const { return ServoTimerSequence_Timer0; } @@ -221,7 +221,3 @@ private: }; #endif - - - - diff --git a/libraries/esp8266/examples/CheckFlashConfig/CheckFlashConfig.ino b/libraries/esp8266/examples/CheckFlashConfig/CheckFlashConfig.ino new file mode 100644 index 000000000..c8ba8d244 --- /dev/null +++ b/libraries/esp8266/examples/CheckFlashConfig/CheckFlashConfig.ino @@ -0,0 +1,32 @@ +/* + ESP8266 CheckFlashConfig by Markus Sattler + + This sketch tests if the EEPROM settings of the IDE match to the Hardware + + */ + +void setup(void) { + Serial.begin(115200); +} + +void loop() { + + uint32_t realSize = ESP.getFlashChipRealSize(); + uint32_t ideSize = ESP.getFlashChipSize(); + FlashMode_t ideMode = ESP.getFlashChipMode(); + + Serial.printf("Flash real id: %08X\n", ESP.getFlashChipId()); + Serial.printf("Flash real size: %u\n\n", realSize); + + Serial.printf("Flash ide size: %u\n", ideSize); + Serial.printf("Flash ide speed: %u\n", ESP.getFlashChipSpeed()); + Serial.printf("Flash ide mode: %s\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN")); + + if(ideSize != realSize) { + Serial.println("Flash Chip configuration wrong!\n"); + } else { + Serial.println("Flash Chip configuration ok.\n"); + } + + delay(5000); +}