diff --git a/.gitignore b/.gitignore index 6245c1dd7..b86a8611d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,9 @@ avr-toolchain-*.zip /hardware/tools/esp8266/utils/ /hardware/tools/esp8266/xtensa-lx106-elf /hardware/tools/esp8266/esptool.exe +/hardware/esp8266com/esp8266/tools/xtensa* +/hardware/esp8266com/esp8266/tools/esptool* +/hardware/esp8266com/esp8266/tools/utils /hardware/tools/avr/ /hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/ /hardware/tools/bossac.exe @@ -72,4 +75,3 @@ nbproject build/macosx/esptool-*-osx.zip build/macosx/dist/osx-xtensa-lx106-elf.tgz -/hardware/esp8266com/esp8266/tools diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 2b58b79d1..d264690a9 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -45,13 +45,22 @@ typedef enum { #define cli() ets_intr_lock() // IRQ Disable #define sei() ets_intr_unlock() // IRQ Enable -enum WakeMode { - WAKE_RF_DEFAULT = 0, // RF_CAL or not after deep-sleep wake up, depends on init data byte 108. - WAKE_RFCAL = 1, // RF_CAL after deep-sleep wake up, there will be large current. - WAKE_NO_RFCAL = 2, // no RF_CAL after deep-sleep wake up, there will only be small current. - WAKE_RF_DISABLED = 4 // disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current. +enum RFMode { + RF_DEFAULT = 0, // RF_CAL or not after deep-sleep wake up, depends on init data byte 108. + RF_CAL = 1, // RF_CAL after deep-sleep wake up, there will be large current. + RF_NO_CAL = 2, // no RF_CAL after deep-sleep wake up, there will only be small current. + RF_DISABLED = 4 // disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current. }; +#define RF_MODE(mode) extern "C" int __get_rf_mode() { return mode; } + +// compatibility definitions +#define WakeMode RFMode +#define WAKE_RF_DEFAULT RF_DEFAULT +#define WAKE_RFCAL RF_CAL +#define WAKE_NO_RFCAL RF_NO_CAL +#define WAKE_RF_DISABLED RF_DISABLED + typedef enum { FM_QIO = 0x00, FM_QOUT = 0x01, @@ -72,7 +81,7 @@ class EspClass { void wdtDisable(); void wdtFeed(); - void deepSleep(uint32_t time_us, WakeMode mode = WAKE_RF_DEFAULT); + void deepSleep(uint32_t time_us, RFMode mode = RF_DEFAULT); void reset(); void restart(); diff --git a/cores/esp8266/abi.cpp b/cores/esp8266/abi.cpp index b863997a3..91e999a0c 100644 --- a/cores/esp8266/abi.cpp +++ b/cores/esp8266/abi.cpp @@ -58,6 +58,14 @@ namespace std { void __throw_bad_function_call() { abort(); } + +void __throw_length_error(char const*) { + abort(); +} + +void __throw_bad_alloc() { + abort(); +} } // TODO: rebuild windows toolchain to make this unnecessary: diff --git a/cores/esp8266/cont.S b/cores/esp8266/cont.S index 0ec47a0a7..4c8514246 100644 --- a/cores/esp8266/cont.S +++ b/cores/esp8266/cont.S @@ -106,7 +106,7 @@ cont_resume: cont_norm: /* calculate pointer to cont_ctx.struct_start from sp */ - l32i a2, a1, 8 + l32i a2, a1, 4 /* sp <- cont_ctx.sp_ret */ l32i a1, a2, 4 diff --git a/cores/esp8266/cont.h b/cores/esp8266/cont.h index 529237742..5da60f497 100644 --- a/cores/esp8266/cont.h +++ b/cores/esp8266/cont.h @@ -33,6 +33,8 @@ typedef struct cont_ { unsigned* sp_yield; unsigned* stack_end; + unsigned unused1; + unsigned unused2; unsigned stack_guard1; unsigned stack[CONT_STACKSIZE / 4]; diff --git a/cores/esp8266/cont_util.c b/cores/esp8266/cont_util.c index fcb6f024c..590cd36ad 100644 --- a/cores/esp8266/cont_util.c +++ b/cores/esp8266/cont_util.c @@ -25,7 +25,7 @@ void cont_init(cont_t* cont) { cont->stack_guard1 = CONT_STACKGUARD; cont->stack_guard2 = CONT_STACKGUARD; - cont->stack_end = cont->stack + (sizeof(cont->stack) / 4 - 1); + cont->stack_end = cont->stack + (sizeof(cont->stack) / 4); cont->struct_start = (unsigned*) cont; } diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 350567906..dcf5631ea 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -59,7 +59,7 @@ void preloop_update_frequency() { extern void (*__init_array_start)(void); extern void (*__init_array_end)(void); -static cont_t g_cont; +cont_t g_cont __attribute__ ((aligned (16))); static os_event_t g_loop_queue[LOOP_QUEUE_SIZE]; static uint32_t g_micros_at_task_start; @@ -114,31 +114,17 @@ static void do_global_ctors(void) { } void init_done() { + system_set_os_print(1); do_global_ctors(); esp_schedule(); } -extern "C" { -void user_rf_pre_init() { - -} -} - extern "C" { void user_init(void) { struct rst_info *rtc_info_ptr = system_get_rst_info(); memcpy((void *) &resetInfo, (void *) rtc_info_ptr, sizeof(resetInfo)); - os_printf("Last reset reason: 0x%02X\n", resetInfo.reason); - - - if(resetInfo.reason == REASON_WDT_RST || resetInfo.reason == REASON_EXCEPTION_RST || resetInfo.reason == REASON_SOFT_WDT_RST) { - if(resetInfo.reason == REASON_EXCEPTION_RST) { - os_printf("Fatal exception (%d):\n", resetInfo.exccause); - } - os_printf("epc1=0x%08x, epc2=0x%08x, epc3=0x%08x, excvaddr=0x%08x, depc=0x%08x\n", resetInfo.epc1, resetInfo.epc2, resetInfo.epc3, resetInfo.excvaddr, resetInfo.depc); - } uart_div_modify(0, UART_CLK_FREQ / (115200)); diff --git a/cores/esp8266/core_esp8266_phy.c b/cores/esp8266/core_esp8266_phy.c new file mode 100644 index 000000000..2ac33a8a6 --- /dev/null +++ b/cores/esp8266/core_esp8266_phy.c @@ -0,0 +1,248 @@ +/* + phy.c - ESP8266 PHY initialization data + + 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 + +static uint8_t phy_init_data[128] = +{ + [0] = 5, // Reserved, do not change + [1] = 0, // Reserved, do not change + [2] = 4, // Reserved, do not change + [3] = 2, // Reserved, do not change + [4] = 5, // Reserved, do not change + [5] = 5, // Reserved, do not change + [6] = 5, // Reserved, do not change + [7] = 2, // Reserved, do not change + [8] = 5, // Reserved, do not change + [9] = 0, // Reserved, do not change + [10] = 4, // Reserved, do not change + [11] = 5, // Reserved, do not change + [12] = 5, // Reserved, do not change + [13] = 4, // Reserved, do not change + [14] = 5, // Reserved, do not change + [15] = 5, // Reserved, do not change + [16] = 4, // Reserved, do not change + [17] = -2, // Reserved, do not change + [18] = -3, // Reserved, do not change + [19] = -1, // Reserved, do not change + [20] = -16, // Reserved, do not change + [21] = -16, // Reserved, do not change + [22] = -16, // Reserved, do not change + [23] = -32, // Reserved, do not change + [24] = -32, // Reserved, do not change + [25] = -32, // Reserved, do not change + + [26] = 225, // spur_freq_cfg, spur_freq=spur_freq_cfg/spur_freq_cfg_div + [27] = 10, // spur_freq_cfg_div + // each bit for 1 channel, 1 to select the spur_freq if in band, else 40 + [28] = 0, // spur_freq_en_h + [29] = 0, // spur_freq_en_l + + [30] = 0xf8, // Reserved, do not change + [31] = 0, // Reserved, do not change + [32] = 0xf8, // Reserved, do not change + [33] = 0xf8, // Reserved, do not change + + [34] = 82, // target_power_qdb_0, 82 means target power is 82/4=20.5dbm + [35] = 78, // target_power_qdb_1, 78 means target power is 78/4=19.5dbm + [36] = 74, // target_power_qdb_2, 74 means target power is 74/4=18.5dbm + [37] = 68, // target_power_qdb_3, 68 means target power is 68/4=17dbm + [38] = 64, // target_power_qdb_4, 64 means target power is 64/4=16dbm + [39] = 56, // target_power_qdb_5, 56 means target power is 56/4=14dbm + + [40] = 0, // target_power_index_mcs0 + [41] = 0, // target_power_index_mcs1 + [42] = 1, // target_power_index_mcs2 + [43] = 1, // target_power_index_mcs3 + [44] = 2, // target_power_index_mcs4 + [45] = 3, // target_power_index_mcs5 + [46] = 4, // target_power_index_mcs6 + [47] = 5, // target_power_index_mcs7 + + // crystal_26m_en + // 0: 40MHz + // 1: 26MHz + // 2: 24MHz + [48] = 1, + + + + // sdio_configure + // 0: Auto by pin strapping + // 1: SDIO dataoutput is at negative edges (SDIO V1.1) + // 2: SDIO dataoutput is at positive edges (SDIO V2.0) + [50] = 0, + + // bt_configure + // 0: None,no bluetooth + // 1: GPIO0 -> WLAN_ACTIVE/ANT_SEL_WIFI + // MTMS -> BT_ACTIVE + // MTCK -> BT_PRIORITY + // U0RXD -> ANT_SEL_BT + // 2: None, have bluetooth + // 3: GPIO0 -> WLAN_ACTIVE/ANT_SEL_WIFI + // MTMS -> BT_PRIORITY + // MTCK -> BT_ACTIVE + // U0RXD -> ANT_SEL_BT + [51] = 0, + + // bt_protocol + // 0: WiFi-BT are not enabled. Antenna is for WiFi + // 1: WiFi-BT are not enabled. Antenna is for BT + // 2: WiFi-BT 2-wire are enabled, (only use BT_ACTIVE), independent ant + // 3: WiFi-BT 3-wire are enabled, (when BT_ACTIVE = 0, BT_PRIORITY must be 0), independent ant + // 4: WiFi-BT 2-wire are enabled, (only use BT_ACTIVE), share ant + // 5: WiFi-BT 3-wire are enabled, (when BT_ACTIVE = 0, BT_PRIORITY must be 0), share ant + [52] = 0, + + // dual_ant_configure + // 0: None + // 1: dual_ant (antenna diversity for WiFi-only): GPIO0 + U0RXD + // 2: T/R switch for External PA/LNA: GPIO0 is high and U0RXD is low during Tx + // 3: T/R switch for External PA/LNA: GPIO0 is low and U0RXD is high during Tx + [53] = 0, + + [54] = 2, // Reserved, do not change + + // share_xtal + // This option is to share crystal clock for BT + // The state of Crystal during sleeping + // 0: Off + // 1: Forcely On + // 2: Automatically On according to XPD_DCDC + // 3: Automatically On according to GPIO2 + [55] = 0, + + [64] = 225, // spur_freq_cfg_2, spur_freq_2=spur_freq_cfg_2/spur_freq_cfg_div_2 + [65] = 10, // spur_freq_cfg_div_2 + [66] = 0, // spur_freq_en_h_2 + [67] = 0, // spur_freq_en_l_2 + [68] = 0, // spur_freq_cfg_msb + [69] = 0, // spur_freq_cfg_2_msb + [70] = 0, // spur_freq_cfg_3_low + [71] = 0, // spur_freq_cfg_3_high + [72] = 0, // spur_freq_cfg_4_low + [73] = 0, // spur_freq_cfg_4_high + + [74] = 1, // Reserved, do not change + [75] = 0x93, // Reserved, do not change + [76] = 0x43, // Reserved, do not change + [77] = 0x00, // Reserved, do not change + + // low_power_en + // 0: disable low power mode + // 1: enable low power mode + [93] = 0, + + // lp_rf_stg10 + // the attenuation of RF gain stage 0 and 1, + // 0xf: 0db, + // 0xe: -2.5db, + // 0xd: -6db, + // 0x9: -8.5db, + // 0xc: -11.5db, + // 0x8: -14db, + // 0x4: -17.5, + // 0x0: -23 + [94] = 0x0f, + + + // lp_bb_att_ext + // the attenuation of BB gain, + // 0: 0db, + // 1: -0.25db, + // 2: -0.5db, + // 3: -0.75db, + // 4: -1db, + // 5: -1.25db, + // 6: -1.5db, + // 7: -1.75db, + // 8: -2db + // max valve is 24(-6db) + [95] = 0, + + // pwr_ind_11b_en + // 0: 11b power is same as mcs0 and 6m + // 1: enable 11b power different with ofdm + [96] = 0, + + // pwr_ind_11b_0 + // 1m, 2m power index [0~5] + [97] = 0, + + // pwr_ind_11b_1 + // 5.5m, 11m power index [0~5] + [98] = 0, + + // vdd33_const + // the voltage of PA_VDD + // x=0xff: it can measure VDD33, + // 18<=x<=36: use input voltage, + // the value is voltage*10, 33 is 3.3V, 30 is 3.0V, + // x<18 or x>36: default voltage is 3.3V + [107] = 33, + + // disable RF calibration for certain number of times + [108] = 0, + + // freq_correct_en + // bit[0]:0->do not correct frequency offset, 1->correct frequency offset. + // bit[1]:0->bbpll is 168M, it can correct + and - frequency offset, 1->bbpll is 160M, it only can correct + frequency offset + // bit[2]:0->auto measure frequency offset and correct it, 1->use 113 byte force_freq_offset to correct frequency offset. + // 0: do not correct frequency offset. + // 1: auto measure frequency offset and correct it, bbpll is 168M, it can correct + and - frequency offset. + // 3: auto measure frequency offset and correct it, bbpll is 160M, it only can correct + frequency offset. + // 5: use 113 byte force_freq_offset to correct frequency offset, bbpll is 168M, it can correct + and - frequency offset. + // 7: use 113 byte force_freq_offset to correct frequency offset, bbpll is 160M , it only can correct + frequency offset. + [112] = 0, + + // force_freq_offset + // signed, unit is 8kHz + [113] = 0, +}; + +extern int __real_register_chipv6_phy(uint8_t* init_data); +extern int __wrap_register_chipv6_phy(uint8_t* unused) { + return __real_register_chipv6_phy(phy_init_data); +} + + +void user_rf_pre_init() { + // *((volatile uint32_t*) 0x60000710) = 0; + + volatile uint32_t* rtc_reg = (volatile uint32_t*) 0x60001000; + rtc_reg[30] = 0; + + system_set_os_print(0); +} + +extern int __get_rf_mode() __attribute__((weak)); +extern int __get_rf_mode() +{ + return 0; // default mode +} + + + + diff --git a/cores/esp8266/core_esp8266_postmortem.c b/cores/esp8266/core_esp8266_postmortem.c new file mode 100644 index 000000000..2d749108a --- /dev/null +++ b/cores/esp8266/core_esp8266_postmortem.c @@ -0,0 +1,130 @@ +/* + postmortem.c - output of debug info on sketch crash + 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 "ets_sys.h" +#include "user_interface.h" +#include "esp8266_peri.h" +#include "cont.h" + +extern void __real_system_restart_local(); +extern cont_t g_cont; + +static void uart0_write_char_d(char c); +static void print_stack(uint32_t start, uint32_t end); +static void print_pcs(uint32_t start, uint32_t end); + +void __wrap_system_restart_local() { + register uint32_t sp asm("a1"); + + struct rst_info rst_info = {0}; + system_rtc_mem_read(0, &rst_info, sizeof(rst_info)); + if (rst_info.reason != REASON_SOFT_WDT_RST && + rst_info.reason != REASON_EXCEPTION_RST && + rst_info.reason != REASON_WDT_RST) + { + return; + } + + ets_install_putc1(&uart0_write_char_d); + + if (rst_info.reason == REASON_EXCEPTION_RST) { + ets_printf("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n", + rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc); + } + + uint32_t cont_stack_start = (uint32_t) &(g_cont.stack); + uint32_t cont_stack_end = (uint32_t) g_cont.stack_end; + uint32_t stack_end; + + // amount of stack taken by interrupt or exception handler + // and everything up to __wrap_system_restart_local + // (determined empirically, might break) + uint32_t offset = 0; + if (rst_info.reason == REASON_SOFT_WDT_RST) { + offset = 0x1b0; + } + else if (rst_info.reason == REASON_EXCEPTION_RST) { + offset = 0x1a0; + } + else if (rst_info.reason == REASON_WDT_RST) { + offset = 0x10; + } + + if (sp > cont_stack_start && sp < cont_stack_end) { + ets_printf("\nctx: cont \n"); + stack_end = cont_stack_end; + } + else { + ets_printf("\nctx: sys \n"); + stack_end = 0x3fffffb0; + // it's actually 0x3ffffff0, but the stuff below ets_run + // is likely not really relevant to the crash + } + + ets_printf("sp: %08x end: %08x offset: %04x\n", sp, stack_end, offset); + + // print_pcs(sp + offset, stack_end); + print_stack(sp + offset, stack_end); + delayMicroseconds(10000); + __real_system_restart_local(); +} + + +static void print_stack(uint32_t start, uint32_t end) { + ets_printf("\n>>>stack>>>\n"); + for (uint32_t pos = start; pos < end; pos += 0x10) { + uint32_t* values = (uint32_t*)(pos); + + // rough indicator: stack frames usually have SP saved as the second word + bool looksLikeStackFrame = (values[2] == pos + 0x10); + + ets_printf("%08x: %08x %08x %08x %08x %c\n", + pos, values[0], values[1], values[2], values[3], (looksLikeStackFrame)?'<':' '); + } + ets_printf("<<>>pc>>>\n"); + for (uint32_t pos = start; pos < end; pos += 16, ++n) { + uint32_t* sf = (uint32_t*) pos; + + uint32_t pc_ret = sf[3]; + uint32_t sp_ret = sf[2]; + if (pc_ret < 0x40000000 || pc_ret > 0x40f00000 || sp_ret != pos + 16) + continue; + ets_printf("%08x\n", pc_ret); + } + ets_printf("<<> USTXC) & 0xff) >= 0x7e) { } + + if (c == '\n') { + USF(0) = '\r'; + } + USF(0) = c; +} diff --git a/cores/esp8266/debug.h b/cores/esp8266/debug.h index cf0830d3e..7bdc247bd 100644 --- a/cores/esp8266/debug.h +++ b/cores/esp8266/debug.h @@ -5,7 +5,10 @@ // #define DEBUGV(...) ets_printf(__VA_ARGS__) #define DEBUGV(...) +#ifdef __cplusplus void hexdump(uint8_t *mem, uint32_t len, uint8_t cols = 16); - +#else +void hexdump(uint8_t *mem, uint32_t len, uint8_t cols); +#endif #endif//ARD_DEBUG_H diff --git a/cores/esp8266/libc_replacements.c b/cores/esp8266/libc_replacements.c index 39ee925a4..67ed0dbef 100644 --- a/cores/esp8266/libc_replacements.c +++ b/cores/esp8266/libc_replacements.c @@ -36,6 +36,7 @@ #include "osapi.h" #include "mem.h" #include "user_interface.h" +#include "debug.h" void* malloc(size_t size) { size = ((size + 3) & ~((size_t)0x3)); @@ -471,75 +472,7 @@ int isblank(int c) { static int errno_var = 0; int* ICACHE_FLASH_ATTR __errno(void) { - os_printf("__errno is called last error: %d (not current)\n", errno_var); + DEBUGV("__errno is called last error: %d (not current)\n", errno_var); return &errno_var; } -// ########################################################################## -// __ieee754 functions -// ########################################################################## - -double ICACHE_FLASH_ATTR __ieee754_sinh(double x) { - return sinh(x); -} - -double ICACHE_FLASH_ATTR __ieee754_hypot(double x, double y) { - return hypot(x, y); -} - -float ICACHE_FLASH_ATTR __ieee754_hypotf(float x, float y) { - return hypotf(x, y); -} - -float ICACHE_FLASH_ATTR __ieee754_logf(float x) { - return logf(x); -} - -double ICACHE_FLASH_ATTR __ieee754_log10(double x) { - return log10(x); -} - -double ICACHE_FLASH_ATTR __ieee754_exp(double x) { - return exp(x); -} - -double ICACHE_FLASH_ATTR __ieee754_cosh(double x) { - return cosh(x); -} - -float ICACHE_FLASH_ATTR __ieee754_expf(float x) { - return expf(x); -} - -float ICACHE_FLASH_ATTR __ieee754_log10f(float x) { - return log10f(x); -} - -double ICACHE_FLASH_ATTR __ieee754_atan2(double x, double y) { - return atan2(x, y); -} - -float ICACHE_FLASH_ATTR __ieee754_sqrtf(float x) { - return sqrtf(x); -} - -float ICACHE_FLASH_ATTR __ieee754_sinhf(float x) { - return sinhf(x); -} - -double ICACHE_FLASH_ATTR __ieee754_log(double x) { - return log(x); -} - -double ICACHE_FLASH_ATTR __ieee754_sqrt(double x) { - return sqrt(x); -} - -float ICACHE_FLASH_ATTR __ieee754_coshf(float x) { - return coshf(x); -} - -float ICACHE_FLASH_ATTR __ieee754_atan2f(float x, float y) { - return atan2f(x, y); -} - diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 5c94ee818..df067f0c9 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -140,11 +140,10 @@ void ESP8266WebServer::send(int code, const char* content_type, String content) content_type = "text/html"; sendHeader("Content-Type", content_type, true); - if (_contentLength != CONTENT_LENGTH_UNKNOWN) { - size_t length = (_contentLength == CONTENT_LENGTH_NOT_SET) ? - content.length() : _contentLength; - String lengthStr(length); - sendHeader("Content-Length", lengthStr.c_str()); + if (_contentLength != CONTENT_LENGTH_UNKNOWN && _contentLength != CONTENT_LENGTH_NOT_SET) { + sendHeader("Content-Length", String(_contentLength).c_str()); + } else if(content.length() > 0){ + sendHeader("Content-Length", String(content.length()).c_str()); } sendHeader("Connection", "close"); sendHeader("Access-Control-Allow-Origin", "*"); diff --git a/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino b/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino index 9bd390064..1a1130747 100644 --- a/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino +++ b/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino @@ -55,9 +55,6 @@ void setup() { /* You can remove the password parameter if you want the AP to be open. */ WiFi.softAP(ssid, password); - while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } - - Serial.println("done"); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/libraries/ESP8266WiFi/src/WiFiUdp.cpp index 8e304abbb..80b005556 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -124,9 +124,10 @@ int WiFiUDP::available() { /* Release any resources being used by this WiFiUDP instance */ void WiFiUDP::stop() { - if (_ctx) + if (_ctx) { _ctx->disconnect(); - _ctx->unref(); + _ctx->unref(); + } _ctx = 0; } @@ -271,6 +272,7 @@ uint16_t WiFiUDP::localPort() void WiFiUDP::stopAll() { for (WiFiUDP* it = _s_first; it; it = it->_next) { + DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first); it->stop(); } } diff --git a/libraries/ESP8266WiFi/src/include/slist.h b/libraries/ESP8266WiFi/src/include/slist.h index 4ce42de6c..3ea09cd48 100644 --- a/libraries/ESP8266WiFi/src/include/slist.h +++ b/libraries/ESP8266WiFi/src/include/slist.h @@ -9,19 +9,21 @@ public: protected: static void _add(T* self) { + DEBUGV("%s %08x %08x\n", __func__, (uint32_t) self, (uint32_t) _s_first); T* tmp = _s_first; _s_first = self; self->_next = tmp; } static void _remove(T* self) { + DEBUGV("%s %08x %08x\n", __func__, (uint32_t) self, (uint32_t) _s_first); if (_s_first == self) { _s_first = self->_next; self->_next = 0; return; } - for (T* prev = _s_first; prev->_next; _s_first = _s_first->_next) { + for (T* prev = _s_first; prev->_next; prev = prev->_next) { if (prev->_next == self) { prev->_next = self->_next; self->_next = 0; diff --git a/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino b/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino new file mode 100644 index 000000000..0423c20cf --- /dev/null +++ b/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino @@ -0,0 +1,44 @@ +#include +#include + +/* Create the mesh node object */ +ESP8266WiFiMesh mesh_node = ESP8266WiFiMesh(ESP.getChipId(), manageRequest); + +/** + * Callback for when other nodes send you data + * + * @request The string received from another node in the mesh + * @returns The string to send back to the other node + */ +String manageRequest(String request) +{ + /* Print out received message */ + Serial.print("received: "); + Serial.println(request); + + /* return a string to send back */ + return String("Hello world response."); +} + +void setup() +{ + Serial.begin(115200); + delay(10); + + Serial.println(); + Serial.println(); + Serial.println("Setting up mesh node..."); + + /* Initialise the mesh node */ + mesh_node.begin(); +} + +void loop() +{ + /* Accept any incoming connections */ + mesh_node.acceptRequest(); + + /* Scan for other nodes and send them a message */ + mesh_node.attemptScan("Hello world request."); + delay(1000); +} diff --git a/libraries/ESP8266WiFiMesh/keywords.txt b/libraries/ESP8266WiFiMesh/keywords.txt new file mode 100644 index 000000000..14657d805 --- /dev/null +++ b/libraries/ESP8266WiFiMesh/keywords.txt @@ -0,0 +1,23 @@ +####################################### +# Syntax Coloring Map For ESP8266WiFiMesh +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +ESP8266WiFiMesh KEYWORD3 + +####################################### +# Datatypes (KEYWORD1) +####################################### + +ESP8266WiFiMesh KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +attemptScan KEYWORD2 +acceptRequest KEYWORD2 diff --git a/libraries/ESP8266WiFiMesh/library.properties b/libraries/ESP8266WiFiMesh/library.properties new file mode 100644 index 000000000..dc6ba9a4d --- /dev/null +++ b/libraries/ESP8266WiFiMesh/library.properties @@ -0,0 +1,9 @@ +name=ESP8266WiFiMesh +version=1.0 +author=Julian Fell +maintainer= +sentence=Mesh network library +paragraph=The library sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. +category=Communication +url= +architectures=esp8266 diff --git a/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp new file mode 100644 index 000000000..97ec0954b --- /dev/null +++ b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp @@ -0,0 +1,168 @@ +/* + ESP8266WiFiMesh.cpp - Mesh network node + Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information + is passed in both directions, but it is up to the user what the data sent is and how it is dealt with. + + Copyright (c) 2015 Julian Fell. All rights 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 +*/ + +#include +#include +#include +#include + +#include "ESP8266WiFiMesh.h" + +#define SSID_PREFIX "Mesh_Node" +#define SERVER_IP_ADDR "192.168.4.1" +#define SERVER_PORT 4011 + +ESP8266WiFiMesh::ESP8266WiFiMesh(uint32_t chip_id, std::function handler) +: _server(SERVER_PORT) +{ + _chip_id = chip_id; + _ssid = String( String( SSID_PREFIX ) + String( _chip_id ) ); + _ssid_prefix = String( SSID_PREFIX ); + _handler = handler; +} + +void ESP8266WiFiMesh::begin() +{ + WiFi.mode(WIFI_AP_STA); + WiFi.softAP( _ssid.c_str() ); + _server.begin(); +} + +/** + * Wait for a WiFiClient to connect + * + * @returns: True if the client is ready, false otherwise. + * + */ +bool ESP8266WiFiMesh::waitForClient(WiFiClient curr_client, int max_wait) +{ + int wait = max_wait; + while(curr_client.connected() && !curr_client.available() && wait--) + delay(3); + + /* Return false if the client isn't ready to communicate */ + if (WiFi.status() == WL_DISCONNECTED || !curr_client.connected()) + return false; + + return true; +} + +/** + * Send the supplied message then read back the other node's response + * and pass that to the user-supplied handler. + * + * @target_ssid The name of the AP the other node has set up. + * @message The string to send to the node. + * @returns: True if the exchange was a succes, false otherwise. + * + */ +bool ESP8266WiFiMesh::exchangeInfo(String message, WiFiClient curr_client) +{ + curr_client.println( message.c_str() ); + + if (!waitForClient(curr_client, 1000)) + return false; + + String response = curr_client.readStringUntil('\r'); + curr_client.readStringUntil('\n'); + + if (response.length() <= 2) + return false; + + /* Pass data to user callback */ + _handler(response); + return true; +} + +/** + * Connect to the AP at ssid, send them a message then disconnect. + * + * @target_ssid The name of the AP the other node has set up. + * @message The string to send to the node. + * + */ +void WiFiMesh::connectToNode(String target_ssid, String message) +{ + WiFiClient curr_client; + WiFi.begin( target_ssid.c_str() ); + + int wait = 1500; + while((WiFi.status() == WL_DISCONNECTED) && wait--) + delay(3); + + /* If the connection timed out */ + if (WiFi.status() != 3) + return; + + /* Connect to the node's server */ + if (!curr_client.connect(SERVER_IP_ADDR, SERVER_PORT)) + return; + + if (!exchangeInfo(message, curr_client)) + return; + + curr_client.stop(); + WiFi.disconnect(); +} + +void ESP8266WiFiMesh::attemptScan(String message) +{ + /* Scan for APs */ + int n = WiFi.scanNetworks(); + + for (int i = 0; i < n; ++i) { + String current_ssid = WiFi.SSID(i); + int index = current_ssid.indexOf( _ssid_prefix ); + uint32_t target_chip_id = (current_ssid.substring(index + _ssid_prefix.length())).toInt(); + + /* Connect to any _suitable_ APs which contain _ssid_prefix */ + if (index >= 0 && (target_chip_id < _chip_id)) { + + WiFi.mode(WIFI_STA); + delay(100); + connectToNode(current_ssid, message); + WiFi.mode(WIFI_AP_STA); + delay(100); + } + } +} + +void ESP8266WiFiMesh::acceptRequest() +{ + while (true) { + _client = _server.available(); + if (!_client) + break; + + if (!waitForClient(_client, 1500)) { + continue; + } + + /* Read in request and pass it to the supplied handler */ + String request = _client.readStringUntil('\r'); + _client.readStringUntil('\n'); + + String response = _handler(request); + + /* Send the response back to the client */ + if (_client.connected()) + _client.println(response); + } +} \ No newline at end of file diff --git a/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h new file mode 100644 index 000000000..dd959731b --- /dev/null +++ b/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h @@ -0,0 +1,75 @@ +/* + ESP8266WiFiMesh.h - Mesh network node + Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information + is passed in both directions, but it is up to the user what the data sent is and how it is dealt with. + + Copyright (c) 2015 Julian Fell. All rights 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 __WIFIMESH_H__ +#define __WIFIMESH_H__ + +#include +#include +#include + +class ESP8266WiFiMesh { + +private: + String _ssid; + String _ssid_prefix; + uint32_t _chip_id; + + std::function _handler; + + WiFiServer _server; + WiFiClient _client; + + void connectToNode(String target_ssid, String message); + bool exchangeInfo(String message, WiFiClient curr_client); + bool waitForClient(WiFiClient curr_client, int max_wait); + +public: + + /** + * WiFiMesh Constructor method. Creates a WiFi Mesh Node, ready to be initialised. + * + * @chip_id A unique identifier number for the node. + * @handler The callback handler for dealing with received messages. Takes a string as an argument which + * is the string received from another node and returns the string to send back. + * + */ + ESP8266WiFiMesh(uint32_t chip_id, std::function handler); + + /** + * Initialises the node. + */ + void begin(); + + /** + * Scan for other nodes, and exchange the chosen message with any that are found. + * + * @message The message to send to all other nodes. + * + */ + void attemptScan(String message); + + /** + * If any clients are connected, accept their requests and call the hander function for each one. + */ + void acceptRequest(); +}; + +#endif diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index a21e44f89..d6d3becec 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -78,12 +78,12 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(const char * host, uint16_t port, if(current_version[0] != 0x00) { req += "\r\n" - "x-ESP8266-version: "; + "x-ESP8266-version: "; req += current_version; } req += "\r\n" - "\r\n"; + "\r\n"; tcp.write(req.c_str(), req.length()); diff --git a/platform.txt b/platform.txt index fe41377ee..bf3b930b5 100644 --- a/platform.txt +++ b/platform.txt @@ -16,17 +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 -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=c99 -pedantic +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.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD -compiler.c.elf.flags=-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}" +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.cmd=xtensa-lx106-elf-gcc compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -pedantic +compiler.cpp.flags=-c -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD compiler.as.cmd=xtensa-lx106-elf-as diff --git a/tools/sdk/include/ets_sys.h b/tools/sdk/include/ets_sys.h index c21826cbd..2aaa3321a 100644 --- a/tools/sdk/include/ets_sys.h +++ b/tools/sdk/include/ets_sys.h @@ -39,6 +39,7 @@ typedef struct _ETSTIMER_ { typedef void (*int_handler_t)(void*); +#define ETS_SLC_INUM 1 #define ETS_SPI_INUM 2 #define ETS_GPIO_INUM 4 #define ETS_UART_INUM 5 @@ -54,6 +55,12 @@ typedef void (*int_handler_t)(void*); #define ETS_INTR_UNLOCK() \ ets_intr_unlock() +#define ETS_INTR_ENABLE(inum) \ + ets_isr_unmask((1<