1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Merge pull request #2 from esp8266/esp8266

Esp8266
This commit is contained in:
Me No Dev 2015-06-08 22:10:39 +03:00
commit 09c88adb18
22 changed files with 667 additions and 142 deletions

View File

@ -184,23 +184,51 @@ 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.
#### 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. 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)
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.
You need to put ESP8266 into bootloader mode before uploading code.
#### Power Supply ####
For stable use of the ESP8266 a power supply with 3V3 and >= 250mA is required.
* Note
- using Power from USB to Serial is may unstable, they not deliver enough current.
#### Serial Adapter ####
There are many different USB to Serial adapters / boards.
* Note
- for full upload management you need RTS and DTR
- the chip need to have 3V3 TTL (5V may damage the chip)
- not all board have all pins of the ICs as breakout (check before order)
- CTS and DSR are not useful for upload (they are Inputs)
* Working ICs
- FT232RL
- CP2102
- may others (drop a comment)
#### Minimal hardware Setup for Bootloading and usage ####
ESPxx Hardware
@ -221,26 +249,43 @@ ESPxx Hardware
- Reset is also named RSBT or REST (adding PullUp improves the stability of the Module)
- GPIO2 is alternative TX for the boot loader mode
ESP01 example:
![ESP01 connect](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP01_connect.jpg)
###### esp to Serial
![ESP to Serial](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_to_serial.png)
#### Minimal hardware Setup for Bootloading only ####
ESPxx Hardware
| PIN | Resistor | Serial Adapter |
| ------------- | -------- | -------------- |
| VCC | | VCC (3.3V) |
| GND | | GND |
| TX or GPIO2 | | RX |
| RX | | TX |
| GPIO0 | | GND |
| PIN | Resistor | Serial Adapter |
| ------------- | -------- | --------------- |
| VCC | | VCC (3.3V) |
| GND | | GND |
| TX or GPIO2 | | RX |
| RX | | TX |
| GPIO0 | | GND |
| Reset | | RTS* |
| GPIO15 | PullDown | |
| CH_PD | PullUp | |
| GPIO15 | PullDown | |
| CH_PD | PullUp | |
* Note
- if no RTS is used a manual power toggle is needed
#### Minimal hardware Setup for running only ####
ESPxx Hardware
| PIN | Resistor | Power supply |
| ------------- | -------- | --------------- |
| VCC | | VCC (3.3V) |
| GND | | GND |
| GPIO0 | PullUp | |
| GPIO15 | PullDown | |
| CH_PD | PullUp | |
###### minimal
![ESP min](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_min.png)
###### improved stability
![ESP improved stability](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_improved_stability.png)
### Issues and support ###

View File

@ -1,4 +1,4 @@
XTENSA_TOOCHAIN ?=
XTENSA_TOOLCHAIN ?=
BIN_DIR := ./
TARGET_DIR := ./
@ -6,14 +6,15 @@ TARGET_DIR := ./
TARGET_OBJ_FILES := \
eboot.o \
eboot_command.o \
flash.o \
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

View File

@ -9,9 +9,8 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#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) {

Binary file not shown.

View File

@ -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;
}

View File

@ -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
@ -23,7 +30,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

49
bootloaders/eboot/flash.c Normal file
View File

@ -0,0 +1,49 @@
/* 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 <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#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;
}

View File

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

View File

@ -19,6 +19,9 @@
*/
#include "Arduino.h"
#include "flash_utils.h"
#include "eboot_command.h"
#include <memory>
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);
@ -295,7 +301,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);
@ -315,4 +321,123 @@ bool EspClass::eraseESPconfig(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*) &section_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<uint8_t> 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
}

View File

@ -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 eraseESPconfig(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));

View File

@ -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 <stddef.h>
#include <stdbool.h>
#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;
}

View File

@ -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 <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#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;
}

View File

@ -0,0 +1,36 @@
#ifndef EBOOT_COMMAND_H
#define EBOOT_COMMAND_H
#include <stdint.h>
#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

View File

@ -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)

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
doc/ESP_min.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
doc/ESP_to_serial.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -40,11 +40,15 @@ extern "C" void esp_yield();
ESP8266WiFiClass::ESP8266WiFiClass()
: _useApMode(false)
, _useClientMode(false)
, _useStaticIp(false)
{
}
void ESP8266WiFiClass::mode(WiFiMode m)
{
if(wifi_get_opmode() == (uint8)m) {
return;
}
ETS_UART_INTR_DISABLE();
wifi_set_opmode(m);
ETS_UART_INTR_ENABLE();
@ -100,7 +104,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 +117,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 +128,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<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet);
wifi_station_dhcpc_stop();
wifi_set_ip_info(STATION_IF, &info);
// Set DNS-Server
ip_addr_t d;
d.addr = static_cast<uint32_t>(dns);
dns_setserver(0,&d);
_useStaticIp = true;
}
int ESP8266WiFiClass::disconnect()
@ -333,10 +360,14 @@ void ESP8266WiFiClass::_scanDone(void* result, int status)
int8_t ESP8266WiFiClass::scanNetworks()
{
if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled
{
if(_useApMode) {
// turn on AP+STA mode
mode(WIFI_AP_STA);
} else {
// turn on STA mode
mode(WIFI_STA);
}
int status = wifi_station_get_connect_status();
if (status != STATION_GOT_IP && status != STATION_IDLE)
{
@ -508,9 +539,12 @@ void ESP8266WiFiClass::beginSmartConfig()
if (_smartConfigStarted)
return;
if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled
{
if(_useApMode) {
// turn on AP+STA mode
mode(WIFI_AP_STA);
} else {
// turn on STA mode
mode(WIFI_STA);
}
_smartConfigStarted = true;

View File

@ -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;

View File

@ -72,7 +72,6 @@ wl_status_t ESP8266WiFiMulti::run(void) {
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan);
bool known = false;
for(uint32_t x = 0; x < APlist.size(); x++) {
WifiAPlist_t entry = APlist[x];
@ -152,7 +151,17 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
WifiAPlist_t newAP;
newAP.ssid = (char*) malloc(strlen(ssid));
if(!ssid || strlen(ssid) > 31) {
// fail SSID to long or missing!
return false;
}
if(passphrase && strlen(passphrase) > 63) {
// fail passphrase to long!
return false;
}
newAP.ssid = (char*) malloc((strlen(ssid) + 1));
if(!newAP.ssid) {
return false;
@ -161,16 +170,14 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
strcpy(newAP.ssid, ssid);
if(passphrase && *passphrase != 0x00) {
newAP.passphrase = (char*) malloc(strlen(passphrase));
newAP.passphrase = (char*) malloc((strlen(passphrase) + 1));
if(!newAP.passphrase) {
free(newAP.ssid);
return false;
}
strcpy(newAP.passphrase, passphrase);
}
if(!newAP.passphrase) {
free(newAP.ssid);
return false;
}
strcpy(newAP.passphrase, passphrase);
APlist.push_back(newAP);
return true;
}

View File

@ -42,30 +42,30 @@ extern "C"
uint16_t WiFiClient::_localPort = 0;
ICACHE_FLASH_ATTR WiFiClient::WiFiClient()
WiFiClient::WiFiClient()
: _client(0)
{
}
ICACHE_FLASH_ATTR WiFiClient::WiFiClient(ClientContext* client) : _client(client)
WiFiClient::WiFiClient(ClientContext* client) : _client(client)
{
_client->ref();
}
ICACHE_FLASH_ATTR WiFiClient::~WiFiClient()
WiFiClient::~WiFiClient()
{
if (_client)
_client->unref();
}
ICACHE_FLASH_ATTR WiFiClient::WiFiClient(const WiFiClient& other)
WiFiClient::WiFiClient(const WiFiClient& other)
{
_client = other._client;
if (_client)
_client->ref();
}
WiFiClient& ICACHE_FLASH_ATTR WiFiClient::operator=(const WiFiClient& other)
WiFiClient& WiFiClient::operator=(const WiFiClient& other)
{
if (_client)
_client->unref();
@ -76,7 +76,7 @@ WiFiClient& ICACHE_FLASH_ATTR WiFiClient::operator=(const WiFiClient& other)
}
int ICACHE_FLASH_ATTR WiFiClient::connect(const char* host, uint16_t port)
int WiFiClient::connect(const char* host, uint16_t port)
{
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr))
@ -86,7 +86,7 @@ int ICACHE_FLASH_ATTR WiFiClient::connect(const char* host, uint16_t port)
return 0;
}
int ICACHE_FLASH_ATTR WiFiClient::connect(IPAddress ip, uint16_t port)
int WiFiClient::connect(IPAddress ip, uint16_t port)
{
if (_client)
stop();
@ -114,7 +114,7 @@ int ICACHE_FLASH_ATTR WiFiClient::connect(IPAddress ip, uint16_t port)
return 0;
}
int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err)
int8_t WiFiClient::_connected(void* pcb, int8_t err)
{
tcp_pcb* tpcb = reinterpret_cast<tcp_pcb*>(pcb);
_client = new ClientContext(tpcb, 0, 0);
@ -123,31 +123,31 @@ int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err)
return ERR_OK;
}
void ICACHE_FLASH_ATTR WiFiClient::_err(int8_t err)
void WiFiClient::_err(int8_t err)
{
DEBUGV(":err %d\r\n", err);
esp_schedule();
}
void ICACHE_FLASH_ATTR WiFiClient::setNoDelay(bool nodelay) {
void WiFiClient::setNoDelay(bool nodelay) {
if (!_client)
return;
_client->setNoDelay(nodelay);
}
bool ICACHE_FLASH_ATTR WiFiClient::getNoDelay() {
bool WiFiClient::getNoDelay() {
if (!_client)
return false;
return _client->getNoDelay();
}
size_t ICACHE_FLASH_ATTR WiFiClient::write(uint8_t b)
size_t WiFiClient::write(uint8_t b)
{
return write(&b, 1);
}
size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size)
size_t WiFiClient::write(const uint8_t *buf, size_t size)
{
if (!_client || !size)
{
@ -159,7 +159,7 @@ size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size)
extern "C" uint32_t esp_micros_at_task_start();
int ICACHE_FLASH_ATTR WiFiClient::available()
int WiFiClient::available()
{
static uint32_t lastPollTime = 0;
if (!_client)
@ -174,7 +174,7 @@ int ICACHE_FLASH_ATTR WiFiClient::available()
return result;
}
int ICACHE_FLASH_ATTR WiFiClient::read()
int WiFiClient::read()
{
if (!available())
return -1;
@ -183,12 +183,12 @@ int ICACHE_FLASH_ATTR WiFiClient::read()
}
int ICACHE_FLASH_ATTR WiFiClient::read(uint8_t* buf, size_t size)
int WiFiClient::read(uint8_t* buf, size_t size)
{
return (int) _client->read(reinterpret_cast<char*>(buf), size);
}
int ICACHE_FLASH_ATTR WiFiClient::peek()
int WiFiClient::peek()
{
if (!available())
return -1;
@ -196,13 +196,13 @@ int ICACHE_FLASH_ATTR WiFiClient::peek()
return _client->peek();
}
void ICACHE_FLASH_ATTR WiFiClient::flush()
void WiFiClient::flush()
{
if (_client)
_client->flush();
}
void ICACHE_FLASH_ATTR WiFiClient::stop()
void WiFiClient::stop()
{
if (!_client)
return;
@ -211,7 +211,7 @@ void ICACHE_FLASH_ATTR WiFiClient::stop()
_client = 0;
}
uint8_t ICACHE_FLASH_ATTR WiFiClient::connected()
uint8_t WiFiClient::connected()
{
if (!_client)
return 0;
@ -219,14 +219,14 @@ uint8_t ICACHE_FLASH_ATTR WiFiClient::connected()
return _client->state() == ESTABLISHED || available();
}
uint8_t ICACHE_FLASH_ATTR WiFiClient::status()
uint8_t WiFiClient::status()
{
if (!_client)
return CLOSED;
return _client->state();
}
ICACHE_FLASH_ATTR WiFiClient::operator bool()
WiFiClient::operator bool()
{
return _client != 0;
}
@ -247,12 +247,12 @@ uint16_t WiFiClient::remotePort()
return _client->getRemotePort();
}
int8_t ICACHE_FLASH_ATTR WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
int8_t WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
{
return reinterpret_cast<WiFiClient*>(arg)->_connected(tpcb, err);
}
void ICACHE_FLASH_ATTR WiFiClient::_s_err(void* arg, int8_t err)
void WiFiClient::_s_err(void* arg, int8_t err)
{
reinterpret_cast<WiFiClient*>(arg)->_err(err);
}