1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-25 20:02:37 +03:00

Merge pull request #7 from esp8266/esp8266

pull master
This commit is contained in:
Me No Dev 2015-10-08 03:42:34 +03:00
commit 212e189e59
28 changed files with 890 additions and 285 deletions

View File

@ -25,20 +25,20 @@
#define CONT_STACKGUARD 0xfeefeffe
void cont_init(cont_t* cont) {
void ICACHE_RAM_ATTR cont_init(cont_t* cont) {
cont->stack_guard1 = CONT_STACKGUARD;
cont->stack_guard2 = CONT_STACKGUARD;
cont->stack_end = cont->stack + (sizeof(cont->stack) / 4);
cont->struct_start = (unsigned*) cont;
}
int cont_check(cont_t* cont) {
int ICACHE_RAM_ATTR cont_check(cont_t* cont) {
if(cont->stack_guard1 != CONT_STACKGUARD || cont->stack_guard2 != CONT_STACKGUARD) return 1;
return 0;
}
bool cont_can_yield(cont_t* cont) {
bool ICACHE_RAM_ATTR cont_can_yield(cont_t* cont) {
return !ETS_INTR_WITHINISR() &&
cont->pc_ret != 0 && cont->pc_yield == 0;
}

View File

@ -129,8 +129,12 @@ static void do_global_ctors(void) {
(*p)();
}
extern "C" void __gdb_init() {}
extern "C" void gdb_init(void) __attribute__ ((weak, alias("__gdb_init")));
void init_done() {
system_set_os_print(1);
gdb_init();
do_global_ctors();
esp_schedule();
}

View File

@ -31,7 +31,7 @@ extern void __real_system_restart_local();
extern cont_t g_cont;
static void uart_write_char_d(char c);
void uart_write_char_d(char c);
static void uart0_write_char_d(char c);
static void uart1_write_char_d(char c);
static void print_stack(uint32_t start, uint32_t end);
@ -133,8 +133,8 @@ void uart_write_char_d(char c) {
uart1_write_char_d(c);
}
void uart0_write_char_d(char c) {
while (((USS(0) >> USTXC) & 0xff) >= 0x7e) { }
static void uart0_write_char_d(char c) {
while (((USS(0) >> USTXC) & 0xff)) { }
if (c == '\n') {
USF(0) = '\r';
@ -142,7 +142,7 @@ void uart0_write_char_d(char c) {
USF(0) = c;
}
void uart1_write_char_d(char c) {
static void uart1_write_char_d(char c) {
while (((USS(1) >> USTXC) & 0xff) >= 0x7e) { }
if (c == '\n') {

View File

@ -1,9 +1,9 @@
/*
/*
timer.c - Timer1 library for esp8266
Copyright (c) 2015 Hristo Gochkov. 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
@ -29,13 +29,13 @@
static volatile timercallback timer1_user_cb = NULL;
void timer1_isr_handler(void *para){
void ICACHE_RAM_ATTR timer1_isr_handler(void *para){
if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable
T1I = 0;
if (timer1_user_cb) {
// to make ISR compatible to Arduino AVR model where interrupts are disabled
// we disable them before we call the client ISR
uint32_t savedPS = xt_rsil(15); // stop other interrupts
uint32_t savedPS = xt_rsil(15); // stop other interrupts
timer1_user_cb();
xt_wsr_ps(savedPS);
}
@ -61,7 +61,7 @@ void timer1_enable(uint8_t divider, uint8_t int_type, uint8_t reload){
T1I = 0;
}
void timer1_write(uint32_t ticks){
void ICACHE_RAM_ATTR timer1_write(uint32_t ticks){
T1L = ((ticks)& 0x7FFFFF);
if ((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable
}
@ -76,7 +76,7 @@ void timer1_disable(){
static volatile timercallback timer0_user_cb = NULL;
void timer0_isr_handler(void* para){
void ICACHE_RAM_ATTR timer0_isr_handler(void* para){
if (timer0_user_cb) {
// to make ISR compatible to Arduino AVR model where interrupts are disabled
// we disable them before we call the client ISR
@ -99,6 +99,3 @@ void timer0_detachInterrupt() {
timer0_user_cb = NULL;
ETS_CCOMPARE0_DISABLE();
}

View File

@ -1,9 +1,9 @@
/*
/*
pwm.c - analogWrite implementation for esp8266
Copyright (c) 2015 Hristo Gochkov. 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
@ -88,7 +88,7 @@ void prep_pwm_steps(){
ETS_FRC1_INTR_ENABLE();
}
void pwm_timer_isr(){
void ICACHE_RAM_ATTR pwm_timer_isr(){
static uint8_t current_step = 0;
static uint8_t stepcount = 0;
static uint16_t steps[17];

View File

@ -39,25 +39,25 @@
#include "user_interface.h"
#include "debug.h"
void* malloc(size_t size) {
void* ICACHE_RAM_ATTR malloc(size_t size) {
size = ((size + 3) & ~((size_t)0x3));
return os_malloc(size);
}
void free(void* ptr) {
void ICACHE_RAM_ATTR free(void* ptr) {
os_free(ptr);
}
void* realloc(void* ptr, size_t size) {
void* ICACHE_RAM_ATTR realloc(void* ptr, size_t size) {
size = ((size + 3) & ~((size_t)0x3));
return os_realloc(ptr, size);
}
int puts(const char * str) {
int ICACHE_RAM_ATTR puts(const char * str) {
return os_printf("%s", str);
}
int printf(const char* format, ...) {
int ICACHE_RAM_ATTR printf(const char* format, ...) {
int ret;
va_list arglist;
va_start(arglist, format);
@ -66,7 +66,7 @@ int printf(const char* format, ...) {
return ret;
}
int sprintf(char* buffer, const char* format, ...) {
int ICACHE_RAM_ATTR sprintf(char* buffer, const char* format, ...) {
int ret;
va_list arglist;
va_start(arglist, format);
@ -75,7 +75,7 @@ int sprintf(char* buffer, const char* format, ...) {
return ret;
}
int snprintf(char* buffer, size_t size, const char* format, ...) {
int ICACHE_RAM_ATTR snprintf(char* buffer, size_t size, const char* format, ...) {
int ret;
va_list arglist;
va_start(arglist, format);
@ -84,22 +84,22 @@ int snprintf(char* buffer, size_t size, const char* format, ...) {
return ret;
}
int vprintf(const char * format, va_list arg) {
int ICACHE_RAM_ATTR vprintf(const char * format, va_list arg) {
return ets_vprintf(format, arg);
}
int vsnprintf(char * buffer, size_t size, const char * format, va_list arg) {
int ICACHE_RAM_ATTR vsnprintf(char * buffer, size_t size, const char * format, va_list arg) {
return ets_vsnprintf(buffer, size, format, arg);
}
size_t ICACHE_FLASH_ATTR strnlen(const char *s, size_t len) {
size_t strnlen(const char *s, size_t len) {
// there is no ets_strnlen
const char *cp;
for (cp = s; len != 0 && *cp != '\0'; cp++, len--);
return (size_t)(cp - s);
}
char* ICACHE_FLASH_ATTR strchr(const char * str, int character) {
char* strchr(const char * str, int character) {
while(1) {
if(*str == 0x00) {
return NULL;
@ -111,7 +111,7 @@ char* ICACHE_FLASH_ATTR strchr(const char * str, int character) {
}
}
char * ICACHE_FLASH_ATTR strrchr(const char * str, int character) {
char* strrchr(const char * str, int character) {
char * ret = NULL;
while(1) {
if(*str == 0x00) {
@ -124,11 +124,11 @@ char * ICACHE_FLASH_ATTR strrchr(const char * str, int character) {
}
}
char* ICACHE_FLASH_ATTR strcat(char * dest, const char * src) {
char* strcat(char * dest, const char * src) {
return strncat(dest, src, strlen(src));
}
char* ICACHE_FLASH_ATTR strncat(char * dest, const char * src, size_t n) {
char* strncat(char * dest, const char * src, size_t n) {
size_t i;
size_t offset = strlen(dest);
for(i = 0; i < n && src[i]; i++) {
@ -138,7 +138,7 @@ char* ICACHE_FLASH_ATTR strncat(char * dest, const char * src, size_t n) {
return dest;
}
char* ICACHE_FLASH_ATTR strtok_r(char* s, const char* delim, char** last) {
char* strtok_r(char* s, const char* delim, char** last) {
const char* spanp;
char* tok;
char c;
@ -193,13 +193,13 @@ cont:
// NOTREACHED EVER
}
char* ICACHE_FLASH_ATTR strtok(char* s, const char* delim) {
char* strtok(char* s, const char* delim) {
static char* last;
return (strtok_r(s, delim, &last));
}
int ICACHE_FLASH_ATTR strcasecmp(const char * str1, const char * str2) {
int strcasecmp(const char * str1, const char * str2) {
int d = 0;
while(1) {
int c1 = tolower(*str1++);
@ -211,7 +211,7 @@ int ICACHE_FLASH_ATTR strcasecmp(const char * str1, const char * str2) {
return d;
}
char* ICACHE_FLASH_ATTR strdup(const char *str) {
char* strdup(const char *str) {
size_t len = strlen(str) + 1;
char *cstr = malloc(len);
if(cstr) {
@ -222,7 +222,7 @@ char* ICACHE_FLASH_ATTR strdup(const char *str) {
// based on Source:
// https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93
double ICACHE_FLASH_ATTR strtod(const char* str, char** endptr) {
double strtod(const char* str, char** endptr) {
double result = 0.0;
double factor = 1.0;
bool decimals = false;
@ -388,7 +388,7 @@ int isblank(int c) {
static int errno_var = 0;
int* ICACHE_FLASH_ATTR __errno(void) {
int* __errno(void) {
// DEBUGV("__errno is called last error: %d (not current)\n", errno_var);
return &errno_var;
}
@ -440,7 +440,7 @@ time_t mktime(struct tm *timp) {
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
size_t ICACHE_FLASH_ATTR strlcpy(char* dst, const char* src, size_t size) {
size_t strlcpy(char* dst, const char* src, size_t size) {
const char *s = src;
size_t n = size;
@ -486,8 +486,8 @@ size_t ICACHE_FLASH_ATTR strlcpy(char* dst, const char* src, size_t size) {
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -505,134 +505,134 @@ size_t ICACHE_FLASH_ATTR strlcpy(char* dst, const char* src, size_t size) {
* SUCH DAMAGE.
*/
long ICACHE_FLASH_ATTR strtol(const char *nptr, char **endptr, int base) {
const unsigned char *s = (const unsigned char *)nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
long strtol(const char *nptr, char **endptr, int base) {
const unsigned char *s = (const unsigned char *)nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? (char *)s - 1 : nptr);
return (acc);
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? (char *)s - 1 : nptr);
return (acc);
}
unsigned long ICACHE_FLASH_ATTR strtoul(const char *nptr, char **endptr, int base)
unsigned long strtoul(const char *nptr, char **endptr, int base)
{
const unsigned char *s = (const unsigned char *)nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
const unsigned char *s = (const unsigned char *)nptr;
unsigned long acc;
int c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? (char *)s - 1 : nptr);
return (acc);
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? (char *)s - 1 : nptr);
return (acc);
}

View File

@ -73,7 +73,7 @@ void handleWifi() {
Serial.println("scan done");
if (n > 0) {
for (int i = 0; i < n; i++) {
server.sendContent(String() + "\r\n<tr><td>SSID " + String(WiFi.SSID(i)) + String((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":" *") + " (" + WiFi.RSSI(i) + ")</td></tr>");
server.sendContent(String() + "\r\n<tr><td>SSID " + WiFi.SSID(i) + String((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":" *") + " (" + WiFi.RSSI(i) + ")</td></tr>");
}
} else {
server.sendContent(String() + "<tr><td>No WLAN found</td></tr>");

View File

@ -0,0 +1,43 @@
/*
To upload through terminal you can use: curl -F "image=@firmware.bin" esp8266-webupdate.local/update
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
const char* host = "esp8266-webupdate";
const char* ssid = "........";
const char* password = "........";
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
void setup(void){
Serial.begin(115200);
Serial.println();
Serial.println("Booting Sketch...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
while(WiFi.waitForConnectResult() != WL_CONNECTED){
WiFi.begin(ssid, password);
Serial.println("WiFi failed, retrying.");
}
MDNS.begin(host);
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);
}
void loop(void){
httpServer.handleClient();
delay(1);
}

View File

@ -0,0 +1,20 @@
#######################################
# Syntax Coloring Map For HTTPUpdateServer
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
ESP8266HTTPUpdateServer KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
setup KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,9 @@
name=ESP8266HTTPUpdateServer
version=1.0
author=Ivan Grokhotkov, Miguel Ángel Ajo
maintainer=Ivan Grokhtkov <ivan@esp8266.com>
sentence=Simple HTTP Update server based on the ESP8266WebServer
paragraph=The library accepts HTTP post requests to the /update url, and updates the ESP8266 firmware.
category=Communication
url=
architectures=esp8266

View File

@ -0,0 +1,75 @@
#include <Arduino.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include "ESP8266HTTPUpdateServer.h"
const char* ESP8266HTTPUpdateServer::_serverIndex =
R"(<html><body><form method='POST' action='/update' enctype='multipart/form-data'>
<input type='file' name='update'>
<input type='submit' value='Update'>
</form>
</body></html>)";
ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
{
_serial_output = serial_debug;
_server = NULL;
}
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server)
{
_server = server;
// handler for the /update form page
_server->on("/update", HTTP_GET, [&](){
_server->sendHeader("Connection", "close");
_server->sendHeader("Access-Control-Allow-Origin", "*");
_server->send(200, "text/html", _serverIndex);
});
// handler for the /update form POST (once file upload finishes)
_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();
});
// handler for the file upload, get's the sketch bytes, and writes
// them through the Update object.
_server->onFileUpload([&](){
if(_server->uri() != "/update") return;
HTTPUpload& upload = _server->upload();
if(upload.status == UPLOAD_FILE_START){
if (_serial_output)
Serial.setDebugOutput(true);
WiFiUDP::stopAll();
if (_serial_output)
Serial.printf("Update: %s\n", upload.filename.c_str());
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if(!Update.begin(maxSketchSpace)){//start with max available size
if (_serial_output) Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_WRITE){
if (_serial_output) Serial.printf(".");
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
if (_serial_output) Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_END){
if(Update.end(true)){ //true to set the size to the current progress
if (_serial_output) Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
if (_serial_output) Update.printError(Serial);
}
if (_serial_output) Serial.setDebugOutput(false);
} else if(upload.status == UPLOAD_FILE_ABORTED){
Update.end();
if (_serial_output) Serial.println("Update was aborted");
}
yield();
});
}

View File

@ -0,0 +1,18 @@
#ifndef __HTTP_UPDATE_SERVER_H
#define __HTTP_UPDATE_SERVER_H
class ESP8266WebServer;
class ESP8266HTTPUpdateServer
{
private:
bool _serial_output;
ESP8266WebServer *_server;
static const char *_serverIndex;
public:
ESP8266HTTPUpdateServer(bool serial_debug=false);
void setup(ESP8266WebServer *server=NULL);
};
#endif

View File

@ -16,6 +16,7 @@ HTTPMethod KEYWORD1
begin KEYWORD2
handleClient KEYWORD2
on KEYWORD2
addHandler KEYWORD2
uri KEYWORD2
method KEYWORD2
client KEYWORD2

View File

@ -26,7 +26,7 @@
#include "WiFiClient.h"
#include "ESP8266WebServer.h"
#include "FS.h"
#include "detail/RequestHandler.h"
#include "detail/RequestHandlersImpl.h"
// #define DEBUG
#define DEBUG_OUTPUT Serial
@ -45,7 +45,7 @@ ESP8266WebServer::~ESP8266WebServer() {
return;
RequestHandler* handler = _firstHandler;
while (handler) {
RequestHandler* next = handler->next;
RequestHandler* next = handler->next();
delete handler;
handler = next;
}
@ -63,13 +63,17 @@ void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::
_addRequestHandler(new FunctionRequestHandler(fn, uri, method));
}
void ESP8266WebServer::addHandler(RequestHandler* handler) {
_addRequestHandler(handler);
}
void ESP8266WebServer::_addRequestHandler(RequestHandler* handler) {
if (!_lastHandler) {
_firstHandler = handler;
_lastHandler = handler;
}
else {
_lastHandler->next = handler;
_lastHandler->next(handler);
_lastHandler = handler;
}
}
@ -293,7 +297,7 @@ void ESP8266WebServer::onNotFound(THandlerFunction fn) {
void ESP8266WebServer::_handleRequest() {
RequestHandler* handler;
for (handler = _firstHandler; handler; handler = handler->next) {
for (handler = _firstHandler; handler; handler = handler->next()) {
if (handler->handle(*this, _currentMethod, _currentUri))
break;
}

View File

@ -27,7 +27,8 @@
#include <functional>
enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END };
enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
UPLOAD_FILE_ABORTED };
#define HTTP_DOWNLOAD_UNIT_SIZE 1460
#define HTTP_UPLOAD_BUFLEN 2048
@ -37,7 +38,9 @@ enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END };
#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
#define CONTENT_LENGTH_NOT_SET ((size_t) -2)
class RequestHandler;
class ESP8266WebServer;
#include "detail/RequestHandler.h"
namespace fs {
class FS;
@ -65,6 +68,7 @@ public:
typedef std::function<void(void)> THandlerFunction;
void on(const char* uri, THandlerFunction handler);
void on(const char* uri, HTTPMethod method, THandlerFunction fn);
void addHandler(RequestHandler* handler);
void serveStatic(const char* uri, fs::FS& fs, const char* path);
void onNotFound(THandlerFunction fn); //called when handler is not assigned
void onFileUpload(THandlerFunction fn); //handle file uploads
@ -116,6 +120,7 @@ protected:
void _parseArguments(String data);
static const char* _responseCodeToString(int code);
bool _parseForm(WiFiClient& client, String boundary, uint32_t len);
bool _parseFormUploadAborted();
void _uploadWriteByte(uint8_t b);
uint8_t _uploadReadByte(WiFiClient& client);
void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);

View File

@ -274,7 +274,7 @@ void ESP8266WebServer::_uploadWriteByte(uint8_t b){
uint8_t ESP8266WebServer::_uploadReadByte(WiFiClient& client){
int res = client.read();
if(res == -1){
while(!client.available())
while(!client.available() && client.connected())
yield();
res = client.read();
}
@ -387,13 +387,16 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
uint8_t argByte = _uploadReadByte(client);
readfile:
while(argByte != 0x0D){
if (!client.connected()) return _parseFormUploadAborted();
_uploadWriteByte(argByte);
argByte = _uploadReadByte(client);
}
argByte = _uploadReadByte(client);
if (!client.connected()) return _parseFormUploadAborted();
if (argByte == 0x0A){
argByte = _uploadReadByte(client);
if (!client.connected()) return _parseFormUploadAborted();
if ((char)argByte != '-'){
//continue reading the file
_uploadWriteByte(0x0D);
@ -401,6 +404,7 @@ readfile:
goto readfile;
} else {
argByte = _uploadReadByte(client);
if (!client.connected()) return _parseFormUploadAborted();
if ((char)argByte != '-'){
//continue reading the file
_uploadWriteByte(0x0D);
@ -481,3 +485,9 @@ readfile:
#endif
return false;
}
bool ESP8266WebServer::_parseFormUploadAborted(){
_currentUpload.status = UPLOAD_FILE_ABORTED;
if (_fileUploadHandler) _fileUploadHandler();
return false;
}

View File

@ -3,109 +3,13 @@
class RequestHandler {
public:
RequestHandler(const char* uri, HTTPMethod method)
: _uri(uri)
, _method(method)
, next(NULL)
{
}
virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) { return false; }
virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) = 0;
RequestHandler* next() { return _next; }
void next(RequestHandler* r) { _next = r; }
RequestHandler* next;
protected:
String _uri;
HTTPMethod _method;
};
class FunctionRequestHandler : public RequestHandler {
typedef RequestHandler base;
public:
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method)
: _fn(fn)
, base(uri, method)
{
}
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
if (_method != HTTP_ANY && _method != requestMethod)
return false;
if (requestUri != _uri)
return false;
_fn();
return true;
}
protected:
ESP8266WebServer::THandlerFunction _fn;
};
class StaticRequestHandler : public RequestHandler {
typedef RequestHandler base;
public:
StaticRequestHandler(FS& fs, const char* path, const char* uri)
: _fs(fs)
, base(uri, HTTP_GET)
, _path(path)
{
_isFile = fs.exists(path);
DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d\r\n", path, uri, _isFile);
_baseUriLength = _uri.length();
}
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
if (requestMethod != _method)
return false;
DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
if (!requestUri.startsWith(_uri))
return false;
String path(_path);
if (!_isFile) {
// Base URI doesn't point to a file. Append whatever follows this
// URI in request to get the file path.
path += requestUri.substring(_baseUriLength);
}
else if (requestUri != _uri) {
// Base URI points to a file but request doesn't match this URI exactly
return false;
}
DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
File f = _fs.open(path, "r");
if (!f)
return false;
server.streamFile(f, getContentType(path));
return true;
}
static String getContentType(const String& path) {
if (path.endsWith(".html")) return "text/html";
else if (path.endsWith(".htm")) return "text/html";
else if (path.endsWith(".css")) return "text/css";
else if (path.endsWith(".txt")) return "text/plain";
else if (path.endsWith(".js")) return "application/javascript";
else if (path.endsWith(".png")) return "image/png";
else if (path.endsWith(".gif")) return "image/gif";
else if (path.endsWith(".jpg")) return "image/jpeg";
else if (path.endsWith(".ico")) return "image/x-icon";
else if (path.endsWith(".xml")) return "text/xml";
else if (path.endsWith(".pdf")) return "application/pdf";
else if (path.endsWith(".zip")) return "application/zip";
return "text/plain";
}
protected:
FS _fs;
String _path;
bool _isFile;
size_t _baseUriLength;
private:
RequestHandler* _next = nullptr;
};
#endif //REQUESTHANDLER_H

View File

@ -0,0 +1,95 @@
#ifndef REQUESTHANDLERSIMPL_H
#define REQUESTHANDLERSIMPL_H
#include "RequestHandler.h"
class FunctionRequestHandler : public RequestHandler {
public:
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method)
: _fn(fn)
, _uri(uri)
, _method(method)
{
}
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
if (_method != HTTP_ANY && _method != requestMethod)
return false;
if (requestUri != _uri)
return false;
_fn();
return true;
}
protected:
String _uri;
HTTPMethod _method;
ESP8266WebServer::THandlerFunction _fn;
};
class StaticRequestHandler : public RequestHandler {
public:
StaticRequestHandler(FS& fs, const char* path, const char* uri)
: _fs(fs)
, _uri(uri)
, _path(path)
{
_isFile = fs.exists(path);
DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d\r\n", path, uri, _isFile);
_baseUriLength = _uri.length();
}
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
if (requestMethod != HTTP_GET)
return false;
DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
if (!requestUri.startsWith(_uri))
return false;
String path(_path);
if (!_isFile) {
// Base URI doesn't point to a file. Append whatever follows this
// URI in request to get the file path.
path += requestUri.substring(_baseUriLength);
}
else if (requestUri != _uri) {
// Base URI points to a file but request doesn't match this URI exactly
return false;
}
DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
File f = _fs.open(path, "r");
if (!f)
return false;
server.streamFile(f, getContentType(path));
return true;
}
static String getContentType(const String& path) {
if (path.endsWith(".html")) return "text/html";
else if (path.endsWith(".htm")) return "text/html";
else if (path.endsWith(".css")) return "text/css";
else if (path.endsWith(".txt")) return "text/plain";
else if (path.endsWith(".js")) return "application/javascript";
else if (path.endsWith(".png")) return "image/png";
else if (path.endsWith(".gif")) return "image/gif";
else if (path.endsWith(".jpg")) return "image/jpeg";
else if (path.endsWith(".ico")) return "image/x-icon";
else if (path.endsWith(".xml")) return "text/xml";
else if (path.endsWith(".pdf")) return "application/pdf";
else if (path.endsWith(".zip")) return "application/zip";
return "text/plain";
}
protected:
FS _fs;
String _uri;
String _path;
bool _isFile;
size_t _baseUriLength;
};
#endif //REQUESTHANDLERSIMPL_H

View File

@ -536,13 +536,13 @@ void * ESP8266WiFiClass::_getScanInfoByIndex(int i)
return reinterpret_cast<bss_info*>(ESP8266WiFiClass::_scanResult) + i;
}
const char* ESP8266WiFiClass::SSID(uint8_t i)
String ESP8266WiFiClass::SSID(uint8_t i)
{
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
if (!it)
return 0;
return "";
return reinterpret_cast<const char*>(it->ssid);
return String(reinterpret_cast<const char*>(it->ssid));
}
uint8_t * ESP8266WiFiClass::BSSID(uint8_t i)

View File

@ -239,7 +239,7 @@ public:
*
* return: ssid string of the specified item on the networks scanned list
*/
const char* SSID(uint8_t networkItem);
String SSID(uint8_t networkItem);
/*
* Return the encryption type of the networks discovered during the scanNetworks

View File

@ -51,7 +51,7 @@ public:
protected:
int _connectSSL();
SSLContext* _ssl;
SSLContext* _ssl = nullptr;
};
#endif //wificlientsecure_h

View File

@ -0,0 +1,49 @@
## Using GDB stub
- Add `#include <GDBStub.h>` to the sketch
- Upload the sketch
- Redirect serial port to TCP port:
```
tcp_serial_redirect.py -p /dev/tty.SLAB_USBtoUART -b 115200 --spy -P 9980 --rts=0 --dtr=0
```
Change port and baud rate as necessary. This command requires python and pyserial.
- Observe serial output:
```
nc localhost 9980
```
- When crash happens, `Trap %d: pc=%p va=%p` line will appear in serial output.
- Close nc and start gdb:
```
xtensa-lx106-elf-gdb /path/to/Sketch.cpp.elf -ex "target remote :9980"
```
- Use gdb to inspect program state at the point of an exception.
## Tips and tricks
- To halt the target when software WDT fires, add
```
((int*)0) = 0;
```
at the top of `__wrap_system_restart_local` in core_esp8266_postmortem.c.
## License
GDB Server stub by Marko Mikulicic was taken from Cesanta's smart.js
https://github.com/cesanta/smart.js
Copyright (c) 2013-2014 Cesanta Software Limited
All rights reserved
This software is dual-licensed: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation. For the terms of this
license, see <http://www.gnu.org/licenses>.
You are free to use this software under the terms of the GNU General
Public License, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
Alternatively, you can license this software under a commercial
license, as set out in <https://www.cesanta.com/license>.

View File

@ -0,0 +1,9 @@
name=GDBStub
version=0.1
author=Marko Mikulicic (Cesanta)
maintainer=Ivan Grokhotkov <ivan@esp8266.com>
sentence=GDB server stub from Cesanta's Smart.js
paragraph=GDB server stub helps debug crashes when JTAG isn't an option.
category=Uncategorized
url=https://github.com/cesanta/smart.js
architectures=esp8266

View File

@ -0,0 +1,355 @@
/* GDB Server stub by Marko Mikulicic (Cesanta)
Copyright (c) 2013-2014 Cesanta Software Limited
All rights reserved
This software is dual-licensed: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation. For the terms of this
license, see <http://www.gnu.org/licenses>.
You are free to use this software under the terms of the GNU General
Public License, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
Alternatively, you can license this software under a commercial
license, as set out in <https://www.cesanta.com/license>.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "ets_sys.h"
#include "user_interface.h"
#include "esp8266_peri.h"
#include "xtensa/corebits.h"
#include "xtensa/specreg.h"
#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)
#define RSR(sr) \
({ \
uint32_t r; \
asm volatile("rsr %0,"__stringify(sr) : "=a"(r)); \
r; \
})
/*
* the saved registers begin at a fixed position in the xtos
* low-level exception handler. I don't know if 0x100 it's just an
* artifact of the actual xtos build ESP8266EX is using (although this nice
* round number looks deliberate). The exception handler is burned on rom
* so it should work on future SDK updates, but not necessarily on future
* revisions of the chip.
*/
#define V7_GDB_SP_OFFSET 0x100
/*
* Addresses in this range are guaranteed to be readable without faulting.
* Contains ranges that are unmapped but innocuous.
*
* Putative ESP8266 memory map at:
* https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map
*/
#define ESP_LOWER_VALID_ADDRESS 0x20000000
#define ESP_UPPER_VALID_ADDRESS 0x60000000
/*
* Constructed by xtos.
*
* There is a UserFrame structure in
* ./esp_iot_rtos_sdk/extra_include/xtensa/xtruntime-frames.h
*/
struct xtos_saved_regs {
uint32_t pc; /* instruction causing the trap */
uint32_t ps;
uint32_t sar;
uint32_t vpri; /* current xtos virtual priority */
uint32_t a0; /* when __XTENSA_CALL0_ABI__ is true */
uint32_t a[16]; /* a2 - a15 */
};
/*
* Register file in the format lx106 gdb port expects it.
*
* Inspired by gdb/regformats/reg-xtensa.dat from
* https://github.com/jcmvbkbc/crosstool-NG/blob/lx106-g%2B%2B/overlays/xtensa_lx106.tar
*/
struct regfile {
uint32_t a[16];
uint32_t pc;
uint32_t sar;
uint32_t litbase;
uint32_t sr176;
uint32_t sr208;
uint32_t ps;
};
#define printf ets_printf
extern void uart_write_char_d(char c);
/* TODO(mkm): not sure if gdb guarantees lowercase hex digits */
#define fromhex(c) \
(((c) &0x40) ? ((c) &0x20 ? (c) - 'a' + 10 : (c) - 'A' + 10) : (c) - '0')
#define hexdigit(n) (((n) < 10) ? '0' + (n) : 'a' + ((n) -10))
static struct regfile regs = {0};
static uint8_t gdb_send_checksum;
int gdb_read_uart() {
static char buf[512];
static char pos = 0;
if (pos == 0) {
size_t rx_count;
while ((rx_count = (USS(0) >> USRXC) & 0xff)>0 && pos < sizeof(buf)) {
buf[pos++] = U0F;
}
}
if (pos == 0) {
return -1;
}
return buf[--pos];
}
uint8_t read_unaligned_byte(uint8_t *addr) {
uint32_t *base = (uint32_t *) ((uintptr_t) addr & ~0x3);
uint32_t word;
word = *base;
return (uint8_t)(word >> 8 * ((uintptr_t) addr & 0x3));
}
void gdb_nack() {
printf("-");
}
void gdb_ack() {
printf("+");
}
void gdb_begin_packet() {
printf("$");
gdb_send_checksum = 0;
}
void gdb_end_packet() {
printf("#%c%c", hexdigit(gdb_send_checksum >> 4),
hexdigit(gdb_send_checksum & 0xF));
}
void gdb_putchar(char ch) {
gdb_send_checksum += (uint8_t) ch;
printf("%c", ch);
}
/* output a string while computing the checksum */
void gdb_putstr(char *str) {
while (*str) gdb_putchar(*str++);
}
void gdb_putbyte(uint8_t val) {
gdb_putchar(hexdigit(val >> 4));
gdb_putchar(hexdigit(val & 0xF));
}
/* 32-bit integer in native byte order */
void gdb_putint(uint32_t val) {
int i;
uint8_t *v = (uint8_t *) &val;
for (i = 0; i < 4; i++) {
gdb_putbyte(v[i]);
}
}
/* send a gdb packet with checksum */
void gdb_send_packet(char *str) {
gdb_begin_packet();
gdb_putstr(str);
gdb_end_packet();
}
uint8_t gdb_read_unaligned(uint8_t *addr) {
if (addr < (uint8_t *) ESP_LOWER_VALID_ADDRESS ||
addr >= (uint8_t *) ESP_UPPER_VALID_ADDRESS) {
return 0;
}
return read_unaligned_byte(addr);
}
/*
* Handles the GDB server protocol.
* We currently support only the simple command set.
*
* Data is exchanged in packets like `$Cxxxxx#cc`
* where `C` is a single letter command name, `xxxx` is some data payload,
* and `cc` is a two digit hex checksum of the packet body.
* Replies follow the same structure except that they lack the command symbol.
*
* For a more complete description of the protocol, see
* https://sourceware.org/gdb/current/onlinedocs/gdb/Remote-Protocol.html
*/
void gdb_handle_char(int ch) {
static enum {
GDB_JUNK,
GDB_DATA,
GDB_CHECKSUM,
GDB_CHECKSUM2
} state = GDB_JUNK;
static char data[128];
static int pos = 0;
static uint8_t checksum;
switch (state) {
case GDB_JUNK:
if (ch == '$') {
checksum = 0;
state = GDB_DATA;
}
break;
case GDB_DATA:
if (ch == '#') {
state = GDB_CHECKSUM;
break;
}
/* ignore too long commands, by acking and sending empty response */
if (pos > sizeof(data)) {
state = GDB_JUNK;
gdb_ack();
gdb_send_packet("");
break;
}
checksum += (uint8_t) ch;
data[pos++] = ch;
break;
case GDB_CHECKSUM:
if (fromhex(ch) != (checksum >> 4)) {
gdb_nack();
state = GDB_JUNK;
} else {
state = GDB_CHECKSUM2;
}
break;
case GDB_CHECKSUM2:
state = GDB_JUNK;
if (fromhex(ch) != (checksum & 0xF)) {
gdb_nack();
pos = 0;
break;
}
gdb_ack();
/* process commands */
switch (data[0]) {
case '?':
/* stop status */
gdb_send_packet("S09"); /* TRAP */
break;
case 'm': {
/* read memory */
int i;
uint32_t addr = 0;
uint32_t num = 0;
for (i = 1; i < pos && data[i] != ','; i++) {
addr <<= 4;
addr |= fromhex(data[i]);
}
for (i++; i < pos; i++) {
num <<= 4;
num |= fromhex(data[i]); /* should be decimal */
}
gdb_begin_packet();
for (i = 0; i < num; i++) {
gdb_putbyte(gdb_read_unaligned(((uint8_t *) addr) + i));
}
gdb_end_packet();
break;
}
case 'g': {
/* dump registers */
int i;
gdb_begin_packet();
for (i = 0; i < sizeof(regs); i++) {
gdb_putbyte(((uint8_t *) &regs)[i]);
}
gdb_end_packet();
break;
}
default:
gdb_send_packet("");
break;
}
pos = 0;
break;
}
}
/* The user should detach and let gdb do the talkin' */
void gdb_server() {
printf("waiting for gdb\n");
/*
* polling since we cannot wait for interrupts inside
* an interrupt handler of unknown level.
*
* Interrupts disabled so that the user (or v7 prompt)
* uart interrupt handler doesn't interfere.
*/
xthal_set_intenable(0);
for (;;) {
int ch = gdb_read_uart();
if (ch != -1) gdb_handle_char(ch);
}
}
/*
* xtos low level exception handler (in rom)
* populates an xtos_regs structure with (most) registers
* present at the time of the exception and passes it to the
* high-level handler.
*
* Note that the a1 (sp) register is clobbered (bug? necessity?),
* however the original stack pointer can be inferred from the address
* of the saved registers area, since the exception handler uses the same
* user stack. This might be different in other execution modes on the
* quite variegated xtensa platform family, but that's how it works on ESP8266.
*/
void ICACHE_RAM_ATTR gdb_exception_handler(struct xtos_saved_regs *frame) {
ESP8266_REG(0x900) &= 0x7e; // Disable WDT
int i;
uint32_t cause = RSR(EXCCAUSE);
uint32_t vaddr = RSR(EXCVADDR);
memcpy(&regs.a[2], frame->a, sizeof(frame->a));
regs.a[0] = frame->a0;
regs.a[1] = (uint32_t) frame + V7_GDB_SP_OFFSET;
regs.pc = frame->pc;
regs.sar = frame->sar;
regs.ps = frame->ps;
regs.litbase = RSR(LITBASE);
U0IE = 0;
ets_install_putc1(&uart_write_char_d);
printf("\nTrap %d: pc=%p va=%p\n", cause, frame->pc, vaddr);
gdb_server();
_ResetVector();
}
void gdb_init() {
char causes[] = {EXCCAUSE_ILLEGAL, EXCCAUSE_INSTR_ERROR,
EXCCAUSE_LOAD_STORE_ERROR, EXCCAUSE_DIVIDE_BY_ZERO,
EXCCAUSE_UNALIGNED, EXCCAUSE_INSTR_PROHIBITED,
EXCCAUSE_LOAD_PROHIBITED, EXCCAUSE_STORE_PROHIBITED};
int i;
for (i = 0; i < (int) sizeof(causes); i++) {
_xtos_set_exception_handler(causes[i], gdb_exception_handler);
}
}

View File

@ -0,0 +1,6 @@
#ifndef GDBSTUB_H
#define GDBSTUB_H
// this header is intentionally left blank
#endif //GDBSTUB_H

View File

@ -16,18 +16,18 @@ compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include"
compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99
compiler.c.flags=-c -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections
compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD
compiler.c.elf.flags=-g -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}" -Wl,-wrap,system_restart_local -Wl,-wrap,register_chipv6_phy
compiler.c.elf.flags=-g -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,register_chipv6_phy
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig -lwps -lcrypto -laxtls
compiler.cpp.cmd=xtensa-lx106-elf-g++
compiler.cpp.flags=-c -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD
compiler.cpp.flags=-c -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections
compiler.as.cmd=xtensa-lx106-elf-as

View File

@ -67,7 +67,7 @@ typedef enum {
#ifdef ICACHE_FLASH
#define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text")))
#define ICACHE_RAM_ATTR __attribute__((section(".text")))
#define ICACHE_RAM_ATTR __attribute__((section(".iram.text")))
#define ICACHE_RODATA_ATTR __attribute__((section(".irom.text")))
#else
#define ICACHE_FLASH_ATTR

View File

@ -150,12 +150,11 @@ SECTIONS
.irom0.text : ALIGN(4)
{
_irom0_text_start = ABSOLUTE(.);
*core_esp8266_*.o(.literal*, .text*)
*spiffs*.o(.literal*, .text*)
*.c.o(.literal*, .text*)
*.cpp.o(.literal*, .text*)
*libm.a:(.literal .text .literal.* .text.*)
*libsmartconfig.a:(.literal .text .literal.* .text.*)
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text .irom.text.*)
_irom0_text_end = ABSOLUTE(.);
_flash_code_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr
@ -192,6 +191,8 @@ SECTIONS
*(.init.literal)
*(.init)
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*.cpp.o(.iram.text)
*.c.o(.iram.text)
*(.fini.literal)
*(.fini)
*(.gnu.version)