From 5ed4257e84c67b069f4c29e7105ff7c4ef1593ab Mon Sep 17 00:00:00 2001 From: Makuna Date: Tue, 2 Jun 2015 15:59:22 -0700 Subject: [PATCH 01/10] Include Servo Library in Readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 008ddcd3e..d3af79de9 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,11 @@ Allows the sketch to respond to multicast DNS queries for domain names like "foo Currently the library only works on STA interface, AP interface is not supported. See attached example and library README file for details. +#### Servor #### + +This library exposes the ability to control RC(hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servos counts above 12 will use Timer1 and features that use it will be effected. +While many RC servo motors will accept the 3.3v IO data pin from a esp8266, most will not be able to run off 3.3v and will require another power source that matches their specifications. Make sure to connect the grounds between the esp8266 and the servo motor power supply. + #### Other libraries (not included with the IDE) Libraries that don't rely on low-level access to AVR registers should work well. Here are a few libraries that were verified to work: From 41cc6d72fec01d9d347daa3cf8281a4d086dcab4 Mon Sep 17 00:00:00 2001 From: Makuna Date: Tue, 2 Jun 2015 16:00:51 -0700 Subject: [PATCH 02/10] edits --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3af79de9..8928e14c8 100644 --- a/README.md +++ b/README.md @@ -184,9 +184,9 @@ Allows the sketch to respond to multicast DNS queries for domain names like "foo Currently the library only works on STA interface, AP interface is not supported. See attached example and library README file for details. -#### Servor #### +#### Servo #### -This library exposes the ability to control RC(hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servos counts above 12 will use Timer1 and features that use it will be effected. +This library exposes the ability to control RC (hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servo counts above 12 will use Timer1 and features that use it will be effected. While many RC servo motors will accept the 3.3v IO data pin from a esp8266, most will not be able to run off 3.3v and will require another power source that matches their specifications. Make sure to connect the grounds between the esp8266 and the servo motor power supply. #### Other libraries (not included with the IDE) From 149f619d9735815a120d96b22b5eb106d871bd22 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 3 Jun 2015 22:23:19 +0300 Subject: [PATCH 03/10] double --- hardware/esp8266com/esp8266/cores/esp8266/esp8266_peri.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/esp8266_peri.h b/hardware/esp8266com/esp8266/cores/esp8266/esp8266_peri.h index d7723c3ad..996185ddc 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/esp8266_peri.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/esp8266_peri.h @@ -284,7 +284,7 @@ extern uint8_t esp8266_gpioToFn[16]; //SPI_READY #define SPIRDY ESP8266_DREG(0x0C) -#define SPIBUSY 9 //wait SPI idle +#define SPI_BUSY 9 //wait SPI idle //SPI0 Registers (SPI0 is used for the flash) #define SPI0CMD ESP8266_REG(0x200) From 58f42fe44fc6efeeba7fa864f5861ec033910e2d Mon Sep 17 00:00:00 2001 From: chad cormier roussel Date: Wed, 3 Jun 2015 15:29:25 -0400 Subject: [PATCH 04/10] Add function overload to config to include DNS Disable DHCP if using static IP With dhcp disabled, I noticed about 50% less conncection time --- .../libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 26 ++++++++++++++++++- .../libraries/ESP8266WiFi/src/ESP8266WiFi.h | 13 ++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 0f97e48a1..2ba6eda66 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -40,6 +40,7 @@ extern "C" void esp_yield(); ESP8266WiFiClass::ESP8266WiFiClass() : _useApMode(false) , _useClientMode(false) +, _useStaticIp(false) { } @@ -100,7 +101,8 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t ch wifi_set_channel(channel); } - wifi_station_dhcpc_start(); + if(!_useStaticIp) + wifi_station_dhcpc_start(); return status(); } @@ -112,6 +114,8 @@ uint8_t ESP8266WiFiClass::waitForConnectResult(){ return status(); } + +// You will have to set the DNS-Server manually later since this will not enable DHCP void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { struct ip_info info; @@ -121,6 +125,26 @@ void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress s wifi_station_dhcpc_stop(); wifi_set_ip_info(STATION_IF, &info); + + _useStaticIp = true; +} + +void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns) +{ + struct ip_info info; + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + + wifi_station_dhcpc_stop(); + wifi_set_ip_info(STATION_IF, &info); + + // Set DNS-Server + ip_addr_t d; + d.addr = static_cast(dns); + dns_setserver(0,&d); + + _useStaticIp = true; } int ESP8266WiFiClass::disconnect() diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h index 64563ad7e..5591343ab 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -75,7 +75,6 @@ public: */ void softAP(const char* ssid, const char* passphrase, int channel = 1); - /* Change Ip configuration settings disabling the dhcp client * * param local_ip: Static ip configuration @@ -84,6 +83,15 @@ public: */ void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); + /* Change Ip configuration settings disabling the dhcp client + * + * param local_ip: Static ip configuration + * param gateway: Static gateway configuration + * param subnet: Static Subnet mask + * param dns: Defined DNS + */ + void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns); + /* Configure access point * * param local_ip: access point IP @@ -310,7 +318,8 @@ protected: bool _useApMode; bool _useClientMode; - + bool _useStaticIp; + static size_t _scanCount; static void* _scanResult; From fa6917fb13f41e771d15d0c2a95f6529db7dd670 Mon Sep 17 00:00:00 2001 From: Dario Di Maio Date: Thu, 4 Jun 2015 16:51:52 +0200 Subject: [PATCH 05/10] Update README.md --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 174b078ed..1004502e1 100644 --- a/README.md +++ b/README.md @@ -193,14 +193,15 @@ While many RC servo motors will accept the 3.3v IO data pin from a esp8266, most Libraries that don't rely on low-level access to AVR registers should work well. Here are a few libraries that were verified to work: -- [aREST](https://github.com/marcoschwartz/aREST) REST API handler library. -- [PubSubClient](https://github.com/Imroy/pubsubclient) MQTT library by @Imroy. -- [DHT11](https://github.com/adafruit/DHT-sensor-library) - initialize DHT as follows: ```DHT dht(DHTPIN, DHTTYPE, 15);``` -- [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library.git) -- [NeoPixelBus](https://github.com/Makuna/NeoPixelBus) - Arduino NeoPixel library compatible with esp8266. -- [RTC](https://github.com/Makuna/Rtc) - Arduino Library for Ds1307 & Ds3231 compatible with esp8266. -- [Blynk](https://github.com/blynkkk/blynk-library) - easy IoT framework for Makers (check out the [Kickstarter page](http://tiny.cc/blynk-kick)). - [arduinoWebSockets](https://github.com/Links2004/arduinoWebSockets) - WebSocket Server and Client compatible with esp8266 (RFC6455) +- [aREST](https://github.com/marcoschwartz/aREST) REST API handler library. +- [Blynk](https://github.com/blynkkk/blynk-library) - easy IoT framework for Makers (check out the [Kickstarter page](http://tiny.cc/blynk-kick)). +- [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library.git) +- [DHT11](https://github.com/adafruit/DHT-sensor-library) - initialize DHT as follows: ```DHT dht(DHTPIN, DHTTYPE, 15);``` +- [NeoPixelBus](https://github.com/Makuna/NeoPixelBus) - Arduino NeoPixel library compatible with esp8266. +- [PubSubClient](https://github.com/Imroy/pubsubclient) MQTT library by @Imroy. +- [RTC](https://github.com/Makuna/Rtc) - Arduino Library for Ds1307 & Ds3231 compatible with esp8266. +- [Souliss, Smart Home](https://github.com/souliss/souliss) - Framework for Smart Home based on Arduino, Android and openHAB. #### Upload via serial port #### Pick the correct serial port. From 45c27c6686abad021ca184d1f20dc0f9505da788 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:04:10 +0300 Subject: [PATCH 06/10] Fix typo --- .../esp8266com/esp8266/bootloaders/eboot/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile b/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile index cd9e14143..1364ac0d0 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile @@ -1,4 +1,4 @@ -XTENSA_TOOCHAIN ?= +XTENSA_TOOLCHAIN ?= BIN_DIR := ./ TARGET_DIR := ./ @@ -9,11 +9,11 @@ TARGET_OBJ_FILES := \ TARGET_OBJ_PATHS := $(addprefix $(TARGET_DIR)/,$(TARGET_OBJ_FILES)) -CC := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-gcc -CXX := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-g++ -AR := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-ar -LD := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-gcc -OBJDUMP := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-objdump +CC := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-gcc +CXX := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-g++ +AR := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-ar +LD := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-gcc +OBJDUMP := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-objdump CFLAGS += -std=gnu99 From 1b8cbe7fc544c3ac5a5ddf9c7177e4a0ec390f35 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:08:53 +0300 Subject: [PATCH 07/10] Clean up eboot --- .../esp8266/bootloaders/eboot/Makefile | 1 + .../esp8266/bootloaders/eboot/eboot.c | 57 +++++------------- .../esp8266/bootloaders/eboot/eboot.elf | Bin 9816 -> 11233 bytes .../esp8266/bootloaders/eboot/eboot_command.c | 26 ++++++-- .../esp8266/bootloaders/eboot/eboot_command.h | 5 +- .../esp8266/bootloaders/eboot/flash.c | 42 +++++++++++++ .../bootloaders/eboot/{eboot.h => flash.h} | 9 ++- 7 files changed, 88 insertions(+), 52 deletions(-) create mode 100644 hardware/esp8266com/esp8266/bootloaders/eboot/flash.c rename hardware/esp8266com/esp8266/bootloaders/eboot/{eboot.h => flash.h} (90%) diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile b/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile index 1364ac0d0..0872ee35f 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/Makefile @@ -6,6 +6,7 @@ TARGET_DIR := ./ TARGET_OBJ_FILES := \ eboot.o \ eboot_command.o \ + flash.o \ TARGET_OBJ_PATHS := $(addprefix $(TARGET_DIR)/,$(TARGET_OBJ_FILES)) diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.c b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.c index b3193e299..0b74fcdf0 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.c +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.c @@ -9,9 +9,8 @@ #include #include #include -#include "eboot.h" +#include "flash.h" #include "eboot_command.h" -extern void* flashchip; #define SWRST do { (*((volatile uint32_t*) 0x60000700)) |= 0x80000000; } while(0); @@ -73,53 +72,21 @@ int load_app_from_flash_raw(const uint32_t flash_addr) -int erase(const uint32_t start, const uint32_t size) -{ - if (start & (FLASH_SECTOR_SIZE - 1) != 0) { - return 1; - } - - const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; - uint32_t current_sector = start / FLASH_SECTOR_SIZE; - uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; - const uint32_t end = current_sector + sector_count; - - for (; current_sector < end && (current_sector & (sectors_per_block-1)); - ++current_sector, --sector_count) { - if (SPIEraseSector(current_sector)) { - return 2; - } - } - - for (;current_sector + sectors_per_block <= end; - current_sector += sectors_per_block, - sector_count -= sectors_per_block) { - if (SPIEraseBlock(current_sector / sectors_per_block)) { - return 3; - } - } - - for (; current_sector < end; - ++current_sector, --sector_count) { - if (SPIEraseSector(current_sector)) { - return 4; - } - } - - return 0; -} - int copy_raw(const uint32_t src_addr, const uint32_t dst_addr, const uint32_t size) { + ets_putc('\n'); + ets_putc('c'); + ets_putc('p'); + ets_putc('\n'); // require regions to be aligned if (src_addr & 0xfff != 0 || dst_addr & 0xfff != 0) { return 1; } - if (erase(dst_addr, size)) { + if (SPIEraseAreaEx(dst_addr, size)) { return 2; } @@ -153,17 +120,25 @@ void main() int res = 9; struct eboot_command cmd; - eboot_command_read(&cmd); + if (eboot_command_read(&cmd)) { + cmd.action = ACTION_LOAD_APP; + cmd.args[0] = 0; + ets_putc('e'); + } else { + ets_putc('@'); + } + eboot_command_clear(); if (cmd.action == ACTION_COPY_RAW) { res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2]); if (res == 0) { cmd.action = ACTION_LOAD_APP; + cmd.args[0] = cmd.args[1]; } } if (cmd.action == ACTION_LOAD_APP) { - res = load_app_from_flash_raw(0); + res = load_app_from_flash_raw(cmd.args[0]); } if (res) { diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.elf b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.elf index 0637a05253c2b3f61f91954695e5fd4b116cadc6..97e25c14616a9f6e768711b46c6cafa6f62df21e 100755 GIT binary patch literal 11233 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 diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.c b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.c index 1e9cbed2c..648039e48 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.c +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.c @@ -28,7 +28,7 @@ uint32_t eboot_command_calculate_crc32(const struct eboot_command* cmd) offsetof(struct eboot_command, crc32)); } -void eboot_command_read(struct eboot_command* cmd) +int eboot_command_read(struct eboot_command* cmd) { const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); uint32_t* dst = (uint32_t *) cmd; @@ -39,9 +39,27 @@ void eboot_command_read(struct eboot_command* cmd) uint32_t crc32 = eboot_command_calculate_crc32(cmd); if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || cmd->crc32 != crc32) { - - cmd->action = ACTION_LOAD_APP; - cmd->args[0] = 0; + return 1; + } + + return 0; +} + +void eboot_command_write(struct eboot_command* cmd) +{ + cmd->magic = EBOOT_MAGIC; + cmd->crc32 = eboot_command_calculate_crc32(cmd); + + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + const uint32_t* src = (const uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + RTC_MEM[i] = src[i]; } } +void eboot_command_clear() +{ + RTC_MEM[offsetof(struct eboot_command, magic) / sizeof(uint32_t)] = 0; + RTC_MEM[offsetof(struct eboot_command, crc32) / sizeof(uint32_t)] = 0; +} + diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h index aa0fc11bb..cf40c135d 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h @@ -23,7 +23,8 @@ struct eboot_command { }; -void eboot_command_read(struct eboot_command* cmd); - +int eboot_command_read(struct eboot_command* cmd); +void eboot_command_write(struct eboot_command* cmd); +void eboot_command_clear(); #endif //EBOOT_COMMAND_H diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c b/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c new file mode 100644 index 000000000..6f95a472d --- /dev/null +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include "flash.h" + + +int SPIEraseAreaEx(const uint32_t start, const uint32_t size) +{ + if (start & (FLASH_SECTOR_SIZE - 1) != 0) { + return 1; + } + + const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; + uint32_t current_sector = start / FLASH_SECTOR_SIZE; + uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; + const uint32_t end = current_sector + sector_count; + + for (; current_sector < end && (current_sector & (sectors_per_block-1)); + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 2; + } + } + + for (;current_sector + sectors_per_block <= end; + current_sector += sectors_per_block, + sector_count -= sectors_per_block) { + if (SPIEraseBlock(current_sector / sectors_per_block)) { + return 3; + } + } + + for (; current_sector < end; + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 4; + } + } + + return 0; +} + diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.h b/hardware/esp8266com/esp8266/bootloaders/eboot/flash.h similarity index 90% rename from hardware/esp8266com/esp8266/bootloaders/eboot/eboot.h rename to hardware/esp8266com/esp8266/bootloaders/eboot/flash.h index 973c616a8..ea8b65c1f 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot.h +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/flash.h @@ -5,15 +5,14 @@ * 3-clause BSD license to be found in the LICENSE file. */ -#ifndef EBOOT_H -#define EBOOT_H - +#ifndef FLASH_H +#define FLASH_H int SPIEraseBlock(uint32_t block); int SPIEraseSector(uint32_t sector); int SPIRead(uint32_t addr, void *dest, size_t size); int SPIWrite(uint32_t addr, void *src, size_t size); - +int SPIEraseAreaEx(const uint32_t start, const uint32_t size); #define FLASH_SECTOR_SIZE 0x1000 #define FLASH_BLOCK_SIZE 0x10000 @@ -41,4 +40,4 @@ typedef struct { -#endif //EBOOT_H +#endif //FLASH_H From 4e3455b2169beea47d791dd9dc3f8839961bd92e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:19:47 +0300 Subject: [PATCH 08/10] rename EspClass::eraseESPconfig to eraseConfig --- hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp | 2 +- hardware/esp8266com/esp8266/cores/esp8266/Esp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp b/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp index 946a8b375..419cb889a 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp @@ -295,7 +295,7 @@ struct rst_info * EspClass::getResetInfoPtr(void) { return &resetInfo; } -bool EspClass::eraseESPconfig(void) { +bool EspClass::eraseConfig(void) { bool ret = true; size_t cfgAddr = (ESP.getFlashChipSize() - 0x4000); size_t cfgSize = (8*1024); diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Esp.h b/hardware/esp8266com/esp8266/cores/esp8266/Esp.h index 9411dc5f0..ecb80da07 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Esp.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Esp.h @@ -101,7 +101,7 @@ class EspClass { String getResetInfo(void); struct rst_info * getResetInfoPtr(void); - bool eraseESPconfig(void); + bool eraseConfig(void); inline uint32_t getCycleCount(void); }; From 28b4e0b24f8003232b5c96e58aa8787aca45cdf4 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:29:15 +0300 Subject: [PATCH 09/10] Add some headers --- .../esp8266com/esp8266/bootloaders/eboot/eboot_command.h | 7 +++++++ hardware/esp8266com/esp8266/bootloaders/eboot/flash.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h index cf40c135d..ba9c889a2 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/eboot_command.h @@ -1,3 +1,10 @@ +/* Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + * This file is part of eboot bootloader. + * + * Redistribution and use is permitted according to the conditions of the + * 3-clause BSD license to be found in the LICENSE file. + */ + #ifndef EBOOT_COMMAND_H #define EBOOT_COMMAND_H diff --git a/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c b/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c index 6f95a472d..f90e25b34 100644 --- a/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c +++ b/hardware/esp8266com/esp8266/bootloaders/eboot/flash.c @@ -1,3 +1,10 @@ +/* Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + * This file is part of eboot bootloader. + * + * Redistribution and use is permitted according to the conditions of the + * 3-clause BSD license to be found in the LICENSE file. + */ + #include #include #include From 004078262e2ca8ba92e6af99bea53d1af2519578 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 13:48:00 +0300 Subject: [PATCH 10/10] Add function to update sketch from Stream --- .../esp8266com/esp8266/cores/esp8266/Esp.cpp | 125 ++++++++++++++++++ .../esp8266com/esp8266/cores/esp8266/Esp.h | 48 ++++--- .../esp8266/core_esp8266_eboot_command.c | 88 ++++++++++++ .../cores/esp8266/core_esp8266_flash_utils.c | 64 +++++++++ .../esp8266/cores/esp8266/eboot_command.h | 36 +++++ .../esp8266/cores/esp8266/flash_utils.h | 63 +++++++++ 6 files changed, 402 insertions(+), 22 deletions(-) create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/eboot_command.h create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/flash_utils.h diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp b/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp index 419cb889a..73367683a 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp @@ -19,6 +19,9 @@ */ #include "Arduino.h" +#include "flash_utils.h" +#include "eboot_command.h" +#include extern "C" { #include "user_interface.h" @@ -26,6 +29,9 @@ extern "C" { extern struct rst_info resetInfo; } + +// #define DEBUG_SERIAL Serial + //extern "C" void ets_wdt_init(uint32_t val); extern "C" void ets_wdt_enable(void); extern "C" void ets_wdt_disable(void); @@ -315,4 +321,123 @@ bool EspClass::eraseConfig(void) { return ret; } +uint32_t EspClass::getSketchSize() { + static uint32_t result = 0; + if (result) + return result; + + image_header_t image_header; + uint32_t pos = APP_START_OFFSET; + if (spi_flash_read(pos, (uint32_t*) &image_header, sizeof(image_header))) { + return 0; + } + pos += sizeof(image_header); +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("num_segments=%u\r\n", image_header.num_segments); +#endif + for (uint32_t section_index = 0; + section_index < image_header.num_segments; + ++section_index) + { + section_header_t section_header = {0}; + if (spi_flash_read(pos, (uint32_t*) §ion_header, sizeof(section_header))) { + return 0; + } + pos += sizeof(section_header); + pos += section_header.size; +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("section=%u size=%u pos=%u\r\n", section_index, section_header.size, pos); +#endif + } + result = pos; + return result; +} + +extern "C" uint32_t _SPIFFS_start; + +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; + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd); +#endif + return freeSpaceEnd - freeSpaceStart; +} + +bool EspClass::updateSketch(Stream& in, uint32_t size) { + + if (size > getFreeSketchSpace()) + return false; + + uint32_t usedSize = getSketchSize(); + uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); + uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("erase @0x%x size=0x%x\r\n", freeSpaceStart, roundedSize); +#endif + + noInterrupts(); + int rc = SPIEraseAreaEx(freeSpaceStart, roundedSize); + interrupts(); + if (rc) + return false; + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("erase done"); +#endif + + uint32_t addr = freeSpaceStart; + uint32_t left = size; + + const uint32_t bufferSize = FLASH_SECTOR_SIZE; + std::unique_ptr buffer(new uint8_t[bufferSize]); + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("writing"); +#endif + while (left > 0) { + size_t willRead = (left < bufferSize) ? left : bufferSize; + size_t rd = in.readBytes(buffer.get(), willRead); + if (rd != willRead) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("stream read failed"); +#endif + return false; + } + + noInterrupts(); + rc = SPIWrite(addr, buffer.get(), willRead); + interrupts(); + if (rc) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("write failed"); +#endif + return false; + } + + addr += willRead; + left -= willRead; +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print("."); +#endif + } + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("\r\nrestarting"); +#endif + eboot_command ebcmd; + ebcmd.action = ACTION_COPY_RAW; + ebcmd.args[0] = freeSpaceStart; + ebcmd.args[1] = 0x00000; + ebcmd.args[2] = size; + eboot_command_write(&ebcmd); + + ESP.restart(); + return true; // never happens +} diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Esp.h b/hardware/esp8266com/esp8266/cores/esp8266/Esp.h index ecb80da07..2b58b79d1 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Esp.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Esp.h @@ -69,44 +69,48 @@ class EspClass { // note: setting the timeout value is not implemented at the moment void wdtEnable(WDTO_t timeout_ms = WDTO_0MS); - void wdtDisable(void); - void wdtFeed(void); + void wdtDisable(); + void wdtFeed(); void deepSleep(uint32_t time_us, WakeMode mode = WAKE_RF_DEFAULT); - void reset(void); - void restart(void); + void reset(); + void restart(); - uint16_t getVcc(void); - uint32_t getFreeHeap(void); + uint16_t getVcc(); + uint32_t getFreeHeap(); - uint32_t getChipId(void); + uint32_t getChipId(); - const char * getSdkVersion(void); + const char * getSdkVersion(); - uint8_t getBootVersion(void); - uint8_t getBootMode(void); + uint8_t getBootVersion(); + uint8_t getBootMode(); - uint8_t getCpuFreqMHz(void); + uint8_t getCpuFreqMHz(); - uint32_t getFlashChipId(void); + uint32_t getFlashChipId(); //gets the actual chip size based on the flash id - uint32_t getFlashChipRealSize(void); + uint32_t getFlashChipRealSize(); //gets the size of the flash as set by the compiler - uint32_t getFlashChipSize(void); - uint32_t getFlashChipSpeed(void); - FlashMode_t getFlashChipMode(void); - uint32_t getFlashChipSizeByChipId(void); + uint32_t getFlashChipSize(); + uint32_t getFlashChipSpeed(); + FlashMode_t getFlashChipMode(); + uint32_t getFlashChipSizeByChipId(); - String getResetInfo(void); - struct rst_info * getResetInfoPtr(void); + uint32_t getSketchSize(); + uint32_t getFreeSketchSpace(); + bool updateSketch(Stream& in, uint32_t size); - bool eraseConfig(void); + String getResetInfo(); + struct rst_info * getResetInfoPtr(); - inline uint32_t getCycleCount(void); + bool eraseConfig(); + + inline uint32_t getCycleCount(); }; -uint32_t EspClass::getCycleCount(void) +uint32_t EspClass::getCycleCount() { uint32_t ccount; __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); diff --git a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c new file mode 100644 index 000000000..60c92bf18 --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c @@ -0,0 +1,88 @@ +/* + core_esp8266_eboot_command.c - interface to the eboot bootloader + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +#include +#include "eboot_command.h" + +uint32_t crc_update(uint32_t crc, const uint8_t *data, size_t length) +{ + uint32_t i; + bool bit; + uint8_t c; + + while (length--) { + c = *data++; + for (i = 0x80; i > 0; i >>= 1) { + bit = crc & 0x80000000; + if (c & i) { + bit = !bit; + } + crc <<= 1; + if (bit) { + crc ^= 0x04c11db7; + } + } + } + return crc; +} + +uint32_t eboot_command_calculate_crc32(const struct eboot_command* cmd) +{ + return crc_update(0xffffffff, (const uint8_t*) cmd, + offsetof(struct eboot_command, crc32)); +} + +int eboot_command_read(struct eboot_command* cmd) +{ + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + uint32_t* dst = (uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + dst[i] = RTC_MEM[i]; + } + + uint32_t crc32 = eboot_command_calculate_crc32(cmd); + if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || + cmd->crc32 != crc32) { + return 1; + } + + return 0; +} + +void eboot_command_write(struct eboot_command* cmd) +{ + cmd->magic = EBOOT_MAGIC; + cmd->crc32 = eboot_command_calculate_crc32(cmd); + + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + const uint32_t* src = (const uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + RTC_MEM[i] = src[i]; + } +} + +void eboot_command_clear() +{ + RTC_MEM[offsetof(struct eboot_command, magic) / sizeof(uint32_t)] = 0; + RTC_MEM[offsetof(struct eboot_command, crc32) / sizeof(uint32_t)] = 0; +} + diff --git a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c new file mode 100644 index 000000000..6f8a34f41 --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c @@ -0,0 +1,64 @@ +/* + core_esp8266_flash_utils.c - flash and binary image helpers + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +#include +#include +#include "flash_utils.h" + + +int SPIEraseAreaEx(const uint32_t start, const uint32_t size) +{ + if (start & (FLASH_SECTOR_SIZE - 1) != 0) { + return 1; + } + + const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; + uint32_t current_sector = start / FLASH_SECTOR_SIZE; + uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; + const uint32_t end = current_sector + sector_count; + + for (; current_sector < end && (current_sector & (sectors_per_block-1)); + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 2; + } + } + + for (;current_sector + sectors_per_block <= end; + current_sector += sectors_per_block, + sector_count -= sectors_per_block) { + if (SPIEraseBlock(current_sector / sectors_per_block)) { + return 3; + } + } + + for (; current_sector < end; + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 4; + } + } + + return 0; +} + diff --git a/hardware/esp8266com/esp8266/cores/esp8266/eboot_command.h b/hardware/esp8266com/esp8266/cores/esp8266/eboot_command.h new file mode 100644 index 000000000..3d854afba --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/eboot_command.h @@ -0,0 +1,36 @@ +#ifndef EBOOT_COMMAND_H +#define EBOOT_COMMAND_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTC_MEM ((volatile uint32_t*)0x60001200) + +enum action_t { + ACTION_COPY_RAW = 0x00000001, + ACTION_LOAD_APP = 0xffffffff +}; + +#define EBOOT_MAGIC 0xeb001000 +#define EBOOT_MAGIC_MASK 0xfffff000 + +struct eboot_command { + uint32_t magic; + enum action_t action; + uint32_t args[29]; + uint32_t crc32; +}; + + +int eboot_command_read(struct eboot_command* cmd); +void eboot_command_write(struct eboot_command* cmd); +void eboot_command_clear(); + +#ifdef __cplusplus +} +#endif + +#endif //EBOOT_COMMAND_H diff --git a/hardware/esp8266com/esp8266/cores/esp8266/flash_utils.h b/hardware/esp8266com/esp8266/cores/esp8266/flash_utils.h new file mode 100644 index 000000000..4e5f2120b --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/flash_utils.h @@ -0,0 +1,63 @@ +/* + flash_utils.h - Flash access function and data structures + Copyright (c) 2015 Ivan Grokhotkov. 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 FLASH_UTILS_H +#define FLASH_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +int SPIEraseBlock(uint32_t block); +int SPIEraseSector(uint32_t sector); +int SPIRead(uint32_t addr, void *dest, size_t size); +int SPIWrite(uint32_t addr, void *src, size_t size); +int SPIEraseAreaEx(const uint32_t start, const uint32_t size); + +#define FLASH_SECTOR_SIZE 0x1000 +#define FLASH_BLOCK_SIZE 0x10000 +#define APP_START_OFFSET 0x1000 + +typedef struct { + unsigned char magic; + unsigned char num_segments; + + /* SPI Flash Interface (0 = QIO, 1 = QOUT, 2 = DIO, 0x3 = DOUT) */ + unsigned char flash_mode; + + /* High four bits: 0 = 512K, 1 = 256K, 2 = 1M, 3 = 2M, 4 = 4M, + Low four bits: 0 = 40MHz, 1= 26MHz, 2 = 20MHz, 0xf = 80MHz */ + unsigned char flash_size_freq; + + uint32_t entry; +} image_header_t; + + +typedef struct { + uint32_t address; + uint32_t size; +} section_header_t; + +#ifdef __cplusplus +} +#endif + + +#endif //FLASH_UTILS_H