From 2ecbf1d584a89370b9bcc2fa8a53414bed3522d2 Mon Sep 17 00:00:00 2001
From: Alex Stewart <Alexander.Stewart@consensuscorp.com>
Date: Sat, 10 Oct 2015 21:56:11 -0700
Subject: [PATCH 1/9] First batch of opensdk additions

Replacements for:
    libmain/misc.o
    libmain/os_cpu_a.o
    libmain/spi_flash.o
    libmain/timers.o
    libmain/uart.o
    libmain/xtensa_context.o
---
 core/include/esp/rom.h           |  17 ++-
 core/include/esp/spi_regs.h      |  30 +++--
 core/include/flashchip.h         |  39 +++++++
 core/include/xtensa_ops.h        |  13 ++-
 include/espressif/spi_flash.h    |  23 +---
 include/etstimer.h               |  39 +++++++
 opensdk/component.mk             |  11 ++
 opensdk/libmain/misc.c           |  59 ++++++++++
 opensdk/libmain/os_cpu_a.c       | 121 ++++++++++++++++++++
 opensdk/libmain/spi_flash.c      | 183 +++++++++++++++++++++++++++++++
 opensdk/libmain/timers.c         |  89 +++++++++++++++
 opensdk/libmain/uart.c           |  17 +++
 opensdk/libmain/xtensa_context.S |  41 +++++++
 parameters.mk                    |   4 +-
 14 files changed, 642 insertions(+), 44 deletions(-)
 create mode 100644 core/include/flashchip.h
 create mode 100644 include/etstimer.h
 create mode 100644 opensdk/component.mk
 create mode 100644 opensdk/libmain/misc.c
 create mode 100644 opensdk/libmain/os_cpu_a.c
 create mode 100644 opensdk/libmain/spi_flash.c
 create mode 100644 opensdk/libmain/timers.c
 create mode 100644 opensdk/libmain/uart.c
 create mode 100644 opensdk/libmain/xtensa_context.S

diff --git a/core/include/esp/rom.h b/core/include/esp/rom.h
index c2f8759..5c41e46 100644
--- a/core/include/esp/rom.h
+++ b/core/include/esp/rom.h
@@ -5,7 +5,9 @@
  */
 #ifndef _ESP_ROM_H
 #define _ESP_ROM_H
-#include <stdint.h>
+
+#include "esp/types.h"
+#include "flashchip.h"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -21,8 +23,19 @@ void Cache_Read_Disable(void);
  */
 void Cache_Read_Enable(uint32_t odd_even, uint32_t mb_count, uint32_t no_idea);
 
+/* Low-level SPI flash read/write routines */
+int Enable_QMode(sdk_flashchip_t *chip);
+int Disable_QMode(sdk_flashchip_t *chip);
+int SPI_page_program(sdk_flashchip_t *chip, uint32_t dest_addr, uint32_t *src_addr, uint32_t size);
+int SPI_read_data(sdk_flashchip_t *chip, uint32_t src_addr, uint32_t *dest_addr, uint32_t size);
+int SPI_write_enable(sdk_flashchip_t *chip);
+int SPI_sector_erase(sdk_flashchip_t *chip, uint32_t addr);
+int SPI_read_status(sdk_flashchip_t *chip, uint32_t *status);
+int SPI_write_status(sdk_flashchip_t *chip, uint32_t status);
+int Wait_SPI_Idle(sdk_flashchip_t *chip);
+
 #ifdef	__cplusplus
 }
 #endif
 
-#endif
+#endif /* _ESP_ROM_H */
diff --git a/core/include/esp/spi_regs.h b/core/include/esp/spi_regs.h
index 37eb113..83b61af 100644
--- a/core/include/esp/spi_regs.h
+++ b/core/include/esp/spi_regs.h
@@ -46,22 +46,7 @@ struct SPI_REGS {
     uint32_t volatile SLAVE1;       // 0x34
     uint32_t volatile SLAVE2;       // 0x38
     uint32_t volatile SLAVE3;       // 0x3c
-    uint32_t volatile W0;           // 0x40
-    uint32_t volatile W1;           // 0x44
-    uint32_t volatile W2;           // 0x48
-    uint32_t volatile W3;           // 0x4c
-    uint32_t volatile W4;           // 0x50
-    uint32_t volatile W5;           // 0x54
-    uint32_t volatile W6;           // 0x58
-    uint32_t volatile W7;           // 0x5c
-    uint32_t volatile W8;           // 0x60
-    uint32_t volatile W9;           // 0x64
-    uint32_t volatile W10;          // 0x68
-    uint32_t volatile W11;          // 0x6c
-    uint32_t volatile W12;          // 0x70
-    uint32_t volatile W13;          // 0x74
-    uint32_t volatile W14;          // 0x78
-    uint32_t volatile W15;          // 0x7c
+    uint32_t volatile W[16];        // 0x40 - 0x7c
     uint32_t volatile _unused[28];  // 0x80 - 0xec
     uint32_t volatile EXT0;         // 0xf0
     uint32_t volatile EXT1;         // 0xf4
@@ -73,6 +58,19 @@ _Static_assert(sizeof(struct SPI_REGS) == 0x100, "SPI_REGS is the wrong size");
 
 /* Details for CMD register */
 
+#define SPI_CMD_READ                       BIT(31)
+#define SPI_CMD_WRITE_ENABLE               BIT(30)
+#define SPI_CMD_WRITE_DISABLE              BIT(29)
+#define SPI_CMD_READ_ID                    BIT(28)
+#define SPI_CMD_READ_SR                    BIT(27)
+#define SPI_CMD_WRITE_SR                   BIT(26)
+#define SPI_CMD_PP                         BIT(25)
+#define SPI_CMD_SE                         BIT(24)
+#define SPI_CMD_BE                         BIT(23)
+#define SPI_CMD_CE                         BIT(22)
+#define SPI_CMD_DP                         BIT(21)
+#define SPI_CMD_RES                        BIT(20)
+#define SPI_CMD_HPM                        BIT(19)
 #define SPI_CMD_USR                        BIT(18)
 
 /* Details for CTRL0 register */
diff --git a/core/include/flashchip.h b/core/include/flashchip.h
new file mode 100644
index 0000000..c14d4a3
--- /dev/null
+++ b/core/include/flashchip.h
@@ -0,0 +1,39 @@
+/* flashchip.h
+ *
+ * sdk_flashchip_t structure used by the SDK and some bootrom routines
+ *
+ * This is in a separate include file because it's referenced by several other
+ * headers which are otherwise independent of each other.
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Alex Stewart and Angus Gratton
+ * BSD Licensed as described in the file LICENSE
+ */
+
+#ifndef _FLASHCHIP_H
+#define _FLASHCHIP_H
+
+/* SDK/bootrom uses this structure internally to account for flash size.
+
+   chip_size field is initialised during startup from the flash size
+   saved in the image header (on the first 8 bytes of SPI flash).
+
+   Other field are initialised to hardcoded values by the SDK.
+
+   ** NOTE: This structure is passed to some bootrom routines and is therefore
+   fixed.  Be very careful if you want to change it that you do not break
+   things. **
+
+   Based on RE work by @foogod at
+   http://esp8266-re.foogod.com/wiki/Flashchip_%28IoT_RTOS_SDK_0.9.9%29
+*/
+typedef struct {
+    uint32_t device_id;
+    uint32_t chip_size;   /* in bytes */
+    uint32_t block_size;  /* in bytes */
+    uint32_t sector_size; /* in bytes */
+    uint32_t page_size;   /* in bytes */
+    uint32_t status_mask;
+} sdk_flashchip_t;
+
+#endif /* _FLASHCHIP_H */
diff --git a/core/include/xtensa_ops.h b/core/include/xtensa_ops.h
index 52eba2a..6951869 100644
--- a/core/include/xtensa_ops.h
+++ b/core/include/xtensa_ops.h
@@ -11,9 +11,6 @@
 #ifndef _XTENSA_OPS_H
 #define _XTENSA_OPS_H
 
-// GCC macros for reading, writing, and exchanging Xtensa processor special
-// registers:
-
 /* Read stack pointer to variable.
  *
  * Note that the compiler will push a stack frame (minimum 16 bytes)
@@ -28,8 +25,18 @@
  */
 #define RETADDR(var) asm volatile ("mov %0, a0" : "=r" (var))
 
+// GCC macros for reading, writing, and exchanging Xtensa processor special
+// registers:
+
 #define RSR(var, reg) asm volatile ("rsr %0, " #reg : "=r" (var));
 #define WSR(var, reg) asm volatile ("wsr %0, " #reg : : "r" (var));
 #define XSR(var, reg) asm volatile ("xsr %0, " #reg : "+r" (var));
 
+// GCC macros for performing associated "*sync" opcodes
+
+#define ISYNC() asm volatile ( "isync" )
+#define RSYNC() asm volatile ( "rsync" )
+#define ESYNC() asm volatile ( "esync" )
+#define DSYNC() asm volatile ( "dsync" )
+
 #endif /* _XTENSA_OPS_H */
diff --git a/include/espressif/spi_flash.h b/include/espressif/spi_flash.h
index 44c8677..f08cda9 100644
--- a/include/espressif/spi_flash.h
+++ b/include/espressif/spi_flash.h
@@ -6,6 +6,8 @@
 #ifndef __SPI_FLASH_H__
 #define __SPI_FLASH_H__
 
+#include "flashchip.h"
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -44,29 +46,8 @@ sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, const void *src, uin
 */
 sdk_SpiFlashOpResult sdk_spi_flash_read(uint32_t src_addr, void *des, uint32_t size);
 
-
-/* SDK uses this structure internally to account for flash size.
-
-   chip_size field is initialised during startup from the flash size
-   saved in the image header (on the first 8 bytes of SPI flash).
-
-   Other field are initialised to hardcoded values by the SDK.
-
-   Based on RE work by @foogod at
-   http://esp8266-re.foogod.com/wiki/Flashchip_%28IoT_RTOS_SDK_0.9.9%29
-*/
-typedef struct {
-    uint32_t device_id;
-    uint32_t chip_size;   /* in bytes */
-    uint32_t block_size;  /* in bytes */
-    uint32_t sector_size; /* in bytes */
-    uint32_t page_size;   /* in bytes */
-    uint32_t status_mask;
-} sdk_flashchip_t;
-
 extern sdk_flashchip_t sdk_flashchip;
 
-
 #ifdef	__cplusplus
 }
 #endif
diff --git a/include/etstimer.h b/include/etstimer.h
new file mode 100644
index 0000000..bcc914a
--- /dev/null
+++ b/include/etstimer.h
@@ -0,0 +1,39 @@
+/* Structures and constants used by some SDK routines
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Superhouse Automation Pty Ltd
+ * BSD Licensed as described in the file LICENSE
+ */
+
+/* Note: The following definitions are normally found (in the non-RTOS SDK) in
+ * the ets_sys.h distributed by Espressif.  Unfortunately, they are not found
+ * anywhere in the RTOS SDK headers, and differ substantially from the non-RTOS
+ * versions, so the structures defined here had to be obtained by careful
+ * examination of the code found in the Espressif RTOS SDK.
+ */
+
+/* Note also: These cannot be included in esp8266/ets_sys.h, because it is
+ * included from FreeRTOS.h, creating an (unnecessary) circular dependency.
+ * They have therefore been put into their own header file instead.
+ */
+
+#ifndef _ETSTIMER_H
+#define _ETSTIMER_H
+
+#include "FreeRTOS.h"
+#include "timers.h"
+#include "esp/types.h"
+
+typedef void ETSTimerFunc(void *);
+
+typedef struct ETSTimer_st {
+    struct ETSTimer_st  *timer_next;
+    xTimerHandle timer_handle;
+    uint32_t _unknown;
+    uint32_t timer_ms;
+    ETSTimerFunc *timer_func;
+    bool timer_repeat;
+    void *timer_arg;
+} ETSTimer;
+
+#endif /* _ETSTIMER_H */
diff --git a/opensdk/component.mk b/opensdk/component.mk
new file mode 100644
index 0000000..26fa5ad
--- /dev/null
+++ b/opensdk/component.mk
@@ -0,0 +1,11 @@
+# Component makefile for "open sdk libs"
+
+# args for passing into compile rule generation
+opensdk_libmain_ROOT = $(opensdk_libmain_DEFAULT_ROOT)libmain
+opensdk_libmain_INC_DIR = 
+opensdk_libmain_SRC_DIR = $(opensdk_libmain_ROOT)
+opensdk_libmain_EXTRA_SRC_FILES = 
+
+opensdk_libmain_CFLAGS = $(CFLAGS)
+
+$(eval $(call component_compile_rules,opensdk_libmain))
diff --git a/opensdk/libmain/misc.c b/opensdk/libmain/misc.c
new file mode 100644
index 0000000..25a059d
--- /dev/null
+++ b/opensdk/libmain/misc.c
@@ -0,0 +1,59 @@
+#include "espressif/esp_misc.h"
+#include "esp/gpio_regs.h"
+#include "esp/rtc_regs.h"
+#include "sdk_internal.h"
+#include "xtensa/hal.h"
+
+static int cpu_freq = 80;
+
+void (*sdk__putc1)(char);
+
+int IRAM sdk_os_get_cpu_frequency(void) {
+    return cpu_freq;
+}
+
+void sdk_os_update_cpu_frequency(int freq) {
+    cpu_freq = freq;
+}
+
+void sdk_ets_update_cpu_frequency(int freq) __attribute__ (( alias ("sdk_os_update_cpu_frequency") ));
+
+void sdk_os_delay_us(uint16_t us) {
+    uint32_t start_ccount = xthal_get_ccount();
+    uint32_t delay_ccount = cpu_freq * us;
+    while (xthal_get_ccount() - start_ccount < delay_ccount) {}
+}
+
+void sdk_ets_delay_us(uint16_t us) __attribute__ (( alias ("sdk_os_delay_us") ));
+
+void sdk_os_install_putc1(void (*p)(char)) {
+    sdk__putc1 = p;
+}
+
+void sdk_os_putc(char c) {
+    sdk__putc1(c);
+}
+
+void sdk_gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask) {
+    GPIO.OUT_SET = set_mask;
+    GPIO.OUT_CLEAR = clear_mask;
+    GPIO.ENABLE_OUT_SET = enable_mask;
+    GPIO.ENABLE_OUT_CLEAR = disable_mask;
+}
+
+uint8_t sdk_rtc_get_reset_reason(void) {
+    uint8_t reason;
+
+    reason = FIELD2VAL(RTC_RESET_REASON1_CODE, RTC.RESET_REASON1);
+    if (reason == 5) {
+        if (FIELD2VAL(RTC_RESET_REASON2_CODE, RTC.RESET_REASON2) == 1) {
+            reason = 6;
+        } else {
+            if (FIELD2VAL(RTC_RESET_REASON2_CODE, RTC.RESET_REASON2) != 8) {
+                reason = 0;
+            }
+        }
+    }
+    RTC.RESET_REASON0 &= ~RTC_RESET_REASON0_SOMETHING;
+    return reason;
+}
diff --git a/opensdk/libmain/os_cpu_a.c b/opensdk/libmain/os_cpu_a.c
new file mode 100644
index 0000000..4841ebe
--- /dev/null
+++ b/opensdk/libmain/os_cpu_a.c
@@ -0,0 +1,121 @@
+#include "esp/types.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "xtensa_ops.h"
+#include "common_macros.h"
+
+// xPortSysTickHandle is defined in FreeRTOS/Source/portable/esp8266/port.c but
+// does not exist in any header files.
+void xPortSysTickHandle(void);
+
+/* The following "functions" manipulate the stack at a low level and thus cannot be coded directly in C */
+
+void IRAM vPortYield(void) {
+    asm("   wsr    a0, excsave1            \n\
+            addi   sp, sp, -80             \n\
+            s32i   a0, sp, 4               \n\
+            addi   a0, sp, 80              \n\
+            s32i   a0, sp, 16              \n\
+            rsr    a0, ps                  \n\
+            s32i   a0, sp, 8               \n\
+            rsr    a0, excsave1            \n\
+            s32i   a0, sp, 12              \n\
+            movi   a0, _xt_user_exit       \n\
+            s32i   a0, sp, 0               \n\
+            call0  sdk__xt_int_enter       \n\
+            call0  vPortEnterCritical      \n\
+            call0  vTaskSwitchContext      \n\
+            call0  vPortExitCritical       \n\
+            call0  sdk__xt_int_exit        \n\
+    ");
+}
+
+void IRAM sdk__xt_int_enter(void) {
+    asm("   s32i   a12, sp, 60             \n\
+            s32i   a13, sp, 64             \n\
+            mov    a12, a0                 \n\
+            call0  sdk__xt_context_save    \n\
+            movi   a0, pxCurrentTCB        \n\
+            l32i   a0, a0, 0               \n\
+            s32i   sp, a0, 0               \n\
+            mov    a0, a12                 \n\
+    ");
+}
+
+void IRAM sdk__xt_int_exit(void) {
+    asm("   s32i   a14, sp, 68             \n\
+            s32i   a15, sp, 72             \n\
+            movi   sp, pxCurrentTCB        \n\
+            l32i   sp, sp, 0               \n\
+            l32i   sp, sp, 0               \n\
+            movi   a14, pxCurrentTCB       \n\
+            l32i   a14, a14, 0             \n\
+            addi   a15, sp, 80             \n\
+            s32i   a15, a14, 0             \n\
+            call0  sdk__xt_context_restore \n\
+            l32i   a14, sp, 68             \n\
+            l32i   a15, sp, 72             \n\
+            l32i   a0, sp, 0               \n\
+    ");
+}
+
+void IRAM sdk__xt_timer_int(void) {
+    uint32_t trigger_ccount;
+    uint32_t current_ccount;
+    uint32_t ccount_interval = portTICK_RATE_MS * 80000; //FIXME
+
+    do {
+        RSR(trigger_ccount, ccompare0);
+        WSR(trigger_ccount + ccount_interval, ccompare0);
+        ESYNC();
+        xPortSysTickHandle();
+        ESYNC();
+        RSR(current_ccount, ccount);
+    } while (current_ccount - trigger_ccount > ccount_interval);
+}
+
+void IRAM sdk__xt_timer_int1(void) {
+    vTaskSwitchContext();
+}
+
+#define INTENABLE_CCOMPARE  BIT(6)
+
+void IRAM sdk__xt_tick_timer_init(void) {
+    uint32_t ints_enabled;
+    uint32_t current_ccount;
+    uint32_t ccount_interval = portTICK_RATE_MS * 80000; //FIXME
+
+    RSR(current_ccount, ccount);
+    WSR(current_ccount + ccount_interval, ccompare0);
+    ints_enabled = 0;
+    XSR(ints_enabled, intenable);
+    WSR(ints_enabled | INTENABLE_CCOMPARE, intenable);
+}
+
+void IRAM sdk__xt_isr_unmask(uint32_t mask) {
+    uint32_t ints_enabled;
+
+    ints_enabled = 0;
+    XSR(ints_enabled, intenable);
+    WSR(ints_enabled | mask, intenable);
+}
+
+void IRAM sdk__xt_isr_mask(uint32_t mask) {
+    uint32_t ints_enabled;
+
+    ints_enabled = 0;
+    XSR(ints_enabled, intenable);
+    WSR(ints_enabled & mask, intenable);
+}
+
+uint32_t IRAM sdk__xt_read_ints(void) {
+    uint32_t ints_enabled;
+
+    RSR(ints_enabled, intenable);
+    return ints_enabled;
+}
+
+void IRAM sdk__xt_clear_ints(uint32_t mask) {
+    WSR(mask, intclear);
+}
+
diff --git a/opensdk/libmain/spi_flash.c b/opensdk/libmain/spi_flash.c
new file mode 100644
index 0000000..2915c79
--- /dev/null
+++ b/opensdk/libmain/spi_flash.c
@@ -0,0 +1,183 @@
+#include "FreeRTOS.h"
+#include "common_macros.h"
+#include "esp/spi_regs.h"
+#include "esp/rom.h"
+#include "sdk_internal.h"
+#include "espressif/spi_flash.h"
+
+sdk_flashchip_t sdk_flashchip = {
+    0x001640ef,      // device_id
+    4 * 1024 * 1024, // chip_size
+    65536,           // block_size
+    4096,            // sector_size
+    256,             // page_size
+    0x0000ffff,      // status_mask
+};
+
+// NOTE: This routine appears to be completely unused in the SDK
+
+int IRAM sdk_SPIReadModeCnfig(uint32_t mode) {
+    uint32_t ctrl_bits;
+
+    SPI(0).CTRL0 &= ~(SPI_CTRL0_FASTRD_MODE | SPI_CTRL0_DOUT_MODE | SPI_CTRL0_QOUT_MODE | SPI_CTRL0_DIO_MODE | SPI_CTRL0_QIO_MODE);
+    if (mode == 0) {
+        ctrl_bits = SPI_CTRL0_FASTRD_MODE | SPI_CTRL0_QIO_MODE;
+    } else if (mode == 1) {
+        ctrl_bits = SPI_CTRL0_FASTRD_MODE | SPI_CTRL0_QOUT_MODE;
+    } else if (mode == 2) {
+        ctrl_bits = SPI_CTRL0_FASTRD_MODE | SPI_CTRL0_DIO_MODE;
+    } else if (mode == 3) {
+        ctrl_bits = SPI_CTRL0_FASTRD_MODE | SPI_CTRL0_DOUT_MODE;
+    } else if (mode == 4) {
+        ctrl_bits = SPI_CTRL0_FASTRD_MODE;
+    } else { 
+        ctrl_bits = 0;
+    }
+    if (mode == 0 || mode == 1) {
+        Enable_QMode(&sdk_flashchip);
+    } else {
+        Disable_QMode(&sdk_flashchip);
+    }
+    SPI(0).CTRL0 |= ctrl_bits;
+    return 0;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_SPIWrite(uint32_t des_addr, uint32_t *src_addr, uint32_t size) {
+    uint32_t first_page_portion;
+    uint32_t pos;
+    uint32_t full_pages;
+    uint32_t bytes_remaining;
+
+    if (des_addr + size <= sdk_flashchip.chip_size) {
+        first_page_portion = sdk_flashchip.page_size - (des_addr % sdk_flashchip.page_size);
+        if (size < first_page_portion) {
+            if (SPI_page_program(&sdk_flashchip, des_addr, src_addr, size)) {
+                return SPI_FLASH_RESULT_ERR;
+            } else {
+                return SPI_FLASH_RESULT_OK;
+            }
+        }
+    } else {
+       return SPI_FLASH_RESULT_ERR;
+    }
+    if (SPI_page_program(&sdk_flashchip, des_addr, src_addr, first_page_portion)) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    pos = first_page_portion;
+    bytes_remaining = size - first_page_portion;
+    full_pages = bytes_remaining / sdk_flashchip.page_size;
+    if (full_pages) {
+        for (int i = 0; i != full_pages; i++) {
+            if (SPI_page_program(&sdk_flashchip, des_addr + pos, src_addr + (pos / 4), sdk_flashchip.page_size)) {
+                return SPI_FLASH_RESULT_ERR;
+            }
+            pos += sdk_flashchip.page_size;
+        }
+        bytes_remaining = size - pos;
+    }
+    if (SPI_page_program(&sdk_flashchip, des_addr + pos, src_addr + (pos / 4), bytes_remaining)) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    return SPI_FLASH_RESULT_OK;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_SPIRead(uint32_t src_addr, uint32_t *des_addr, uint32_t size) {
+    if (SPI_read_data(&sdk_flashchip, src_addr, des_addr, size)) {
+        return SPI_FLASH_RESULT_ERR;
+    } else {
+        return SPI_FLASH_RESULT_OK;
+    }
+}
+
+sdk_SpiFlashOpResult IRAM sdk_SPIEraseSector(uint16_t sec) {
+    if (sec >= sdk_flashchip.chip_size / sdk_flashchip.sector_size) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    if (SPI_write_enable(&sdk_flashchip)) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    if (SPI_sector_erase(&sdk_flashchip, sdk_flashchip.sector_size * sec)) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    return SPI_FLASH_RESULT_OK;
+}
+
+uint32_t IRAM sdk_spi_flash_get_id(void) {
+    uint32_t result;
+
+    portENTER_CRITICAL();
+    Cache_Read_Disable();
+    Wait_SPI_Idle(&sdk_flashchip);
+    SPI(0).W[0] = 0;
+    SPI(0).CMD = SPI_CMD_READ_ID;
+    while (SPI(0).CMD != 0) {}
+    result = SPI(0).W[0] & 0x00ffffff;
+    Cache_Read_Enable(0, 0, 1);
+    portEXIT_CRITICAL();
+    return result;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_spi_flash_read_status(uint32_t *status) {
+    sdk_SpiFlashOpResult result;
+
+    portENTER_CRITICAL();
+    Cache_Read_Disable();
+    result = SPI_read_status(&sdk_flashchip, status);
+    Cache_Read_Enable(0, 0, 1);
+    portEXIT_CRITICAL();
+    return result;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_spi_flash_write_status(uint32_t status) {
+    sdk_SpiFlashOpResult result;
+
+    portENTER_CRITICAL();
+    Cache_Read_Disable();
+    result = SPI_write_status(&sdk_flashchip, status);
+    Cache_Read_Enable(0, 0, 1);
+    portEXIT_CRITICAL();
+    return result;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_spi_flash_erase_sector(uint16_t sec) {
+    sdk_SpiFlashOpResult result;
+
+    portENTER_CRITICAL();
+    Cache_Read_Disable();
+    result = sdk_SPIEraseSector(sec);
+    Cache_Read_Enable(0, 0, 1);
+    portEXIT_CRITICAL();
+    return result;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_spi_flash_write(uint32_t des_addr, uint32_t *src_addr, uint32_t size) {
+    sdk_SpiFlashOpResult result;
+
+    if (!src_addr) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    if (size & 3) {
+        size = (size & ~3) + 4;
+    }
+    portENTER_CRITICAL();
+    Cache_Read_Disable();
+    result = sdk_SPIWrite(des_addr, src_addr, size);
+    Cache_Read_Enable(0, 0, 1);
+    portEXIT_CRITICAL();
+    return result;
+}
+
+sdk_SpiFlashOpResult IRAM sdk_spi_flash_read(uint32_t src_addr, uint32_t *des_addr, uint32_t size) {
+    sdk_SpiFlashOpResult result;
+
+    if (!des_addr) {
+        return SPI_FLASH_RESULT_ERR;
+    }
+    portENTER_CRITICAL();
+    Cache_Read_Disable();
+    result = sdk_SPIRead(src_addr, des_addr, size);
+    Cache_Read_Enable(0, 0, 1);
+    portEXIT_CRITICAL();
+    return result;
+}
+
diff --git a/opensdk/libmain/timers.c b/opensdk/libmain/timers.c
new file mode 100644
index 0000000..1359fc1
--- /dev/null
+++ b/opensdk/libmain/timers.c
@@ -0,0 +1,89 @@
+#include "etstimer.h"
+
+struct timer_list_st {
+    struct timer_list_st *next;
+    ETSTimer *timer;
+};
+
+static struct timer_list_st *timer_list;
+static uint8_t armed_timer_count;
+
+void sdk_os_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg) {
+    struct timer_list_st *entry = 0;
+    struct timer_list_st *new_entry;
+    struct timer_list_st **tailptr;
+
+    if (timer_list) {
+        for (entry = timer_list; ; entry = entry->next) {
+            if (entry->timer == ptimer) {
+                if (ptimer->timer_arg == parg && ptimer->timer_func == pfunction) {
+                    return;
+                }
+                if (ptimer->timer_handle) {
+                    if (!xTimerDelete(ptimer->timer_handle, 50)) {
+                        printf("Timer Delete Failed\n");
+                    }
+                    armed_timer_count--;
+                }
+                ptimer->timer_func = pfunction;
+                ptimer->timer_arg = parg;
+                ptimer->timer_handle = 0;
+                ptimer->timer_ms = 0;
+                return;
+            }
+            if (!entry->next) {
+                break;
+            }
+        }
+    }
+    ptimer->timer_func = pfunction;
+    ptimer->timer_arg = parg;
+    ptimer->timer_handle = 0;
+    ptimer->timer_ms = 0;
+    new_entry = (struct timer_list_st *)pvPortMalloc(8);
+    new_entry->timer = ptimer;
+    new_entry->next = 0;
+    tailptr = &entry->next;
+    if (!timer_list) {
+        tailptr = &timer_list;
+    }
+    *tailptr = new_entry;
+}
+
+void sdk_os_timer_arm(ETSTimer *ptimer, uint32_t milliseconds, bool repeat_flag) {
+    if (!ptimer->timer_handle) {
+        ptimer->timer_repeat = repeat_flag;
+        ptimer->timer_ms = milliseconds;
+        ptimer->timer_handle = xTimerCreate(0, milliseconds/10, repeat_flag, ptimer->timer_arg, ptimer->timer_func);
+        armed_timer_count++;
+        if (!ptimer->timer_handle) {
+            //FIXME: should print an error? (original code doesn't)
+            return;
+        }
+    }
+    if (ptimer->timer_repeat != repeat_flag) {
+        ptimer->timer_repeat = repeat_flag;
+        // FIXME: This is wrong.  The original code is directly modifying
+        // internal FreeRTOS structures to try to change the uxAutoReload of an
+        // existing timer.  The correct way to do this is probably to use
+        // xTimerDelete and then xTimerCreate to recreate the timer with a
+        // different uxAutoReload setting.
+        ((uint32_t *)ptimer->timer_handle)[7] = repeat_flag;
+    }
+    if (ptimer->timer_ms != milliseconds) {
+        ptimer->timer_ms = milliseconds;
+        xTimerChangePeriod(ptimer->timer_handle, milliseconds/10, 10);
+    }
+    if (!xTimerStart(ptimer->timer_handle, 50)) {
+        printf("Timer Start Failed\n");
+    }
+}
+
+void sdk_os_timer_disarm(ETSTimer *ptimer) {
+    if (ptimer->timer_handle) {
+        if (!xTimerStop(ptimer->timer_handle, 50)) {
+            printf("Timer Stop Failed\n");
+        }
+    }
+}
+
diff --git a/opensdk/libmain/uart.c b/opensdk/libmain/uart.c
new file mode 100644
index 0000000..25ae961
--- /dev/null
+++ b/opensdk/libmain/uart.c
@@ -0,0 +1,17 @@
+#include "espressif/sdk_private.h"
+#include "esp/uart_regs.h"
+
+void sdk_uart_buff_switch(void) {
+    /* No-Op */
+}
+
+void sdk_uart_div_modify(uint32_t uart_no, uint32_t new_divisor) {
+    UART(uart_no).CLOCK_DIVIDER = new_divisor;
+    UART(uart_no).CONF0 |= (UART_CONF0_TXFIFO_RESET | UART_CONF0_RXFIFO_RESET);
+    UART(uart_no).CONF0 &= ~(UART_CONF0_TXFIFO_RESET | UART_CONF0_RXFIFO_RESET);
+}
+
+void sdk_Uart_Init(void) {
+    /* No-Op */
+}
+
diff --git a/opensdk/libmain/xtensa_context.S b/opensdk/libmain/xtensa_context.S
new file mode 100644
index 0000000..511877e
--- /dev/null
+++ b/opensdk/libmain/xtensa_context.S
@@ -0,0 +1,41 @@
+        .section .iram1.text, "ax", @progbits
+
+        .balign 4
+        .global sdk__xt_context_save
+        .type   sdk__xt_context_save, @function
+sdk__xt_context_save:
+
+        s32i    a2, sp, 20
+        s32i    a3, sp, 24
+        s32i    a4, sp, 28
+        s32i    a5, sp, 32
+        s32i    a6, sp, 36
+        s32i    a7, sp, 40
+        s32i    a8, sp, 44
+        s32i    a9, sp, 48
+        s32i    a10, sp, 52
+        s32i    a11, sp, 56
+        rsr     a3, sar
+        s32i    a3, sp, 76
+        ret
+
+        .balign 4
+        .global sdk__xt_context_restore
+        .type   sdk__xt_context_restore, @function
+sdk__xt_context_restore:
+        l32i    a3, sp, 76
+        l32i    a2, sp, 20
+        wsr     a3, sar
+        l32i    a3, sp, 24
+        l32i    a4, sp, 28
+        l32i    a5, sp, 32
+        l32i    a6, sp, 36
+        l32i    a7, sp, 40
+        l32i    a8, sp, 44
+        l32i    a9, sp, 48
+        l32i    a10, sp, 52
+        l32i    a11, sp, 56
+        l32i    a12, sp, 60
+        l32i    a13, sp, 64
+        ret
+
diff --git a/parameters.mk b/parameters.mk
index e750e83..f14a26b 100644
--- a/parameters.mk
+++ b/parameters.mk
@@ -60,7 +60,7 @@ OBJDUMP = $(CROSS)objdump
 
 # Source components to compile and link. Each of these are subdirectories
 # of the root, with a 'component.mk' file.
-COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core
+COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core opensdk
 
 # binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking.
 SDK_LIBS		?= main net80211 phy pp wpa
@@ -114,7 +114,7 @@ else ifeq ($(FLAVOR),sdklike)
     # the output of the compiler used to build the SDK libs (for comparison of
     # disassemblies when coding replacement routines).  It is not normally
     # intended to be used otherwise.
-    CFLAGS += -O2 -Os -fno-inline -fno-ipa-cp -fno-toplevel-reorder
+    CFLAGS += -O2 -Os -fno-inline -fno-ipa-cp -fno-toplevel-reorder -fno-caller-saves -fconserve-stack
     LDFLAGS += -O2
 else
     C_CXX_FLAGS += -g -O2

From eee4a3660cd7f52776b02685294dd88ce7712160 Mon Sep 17 00:00:00 2001
From: Alex Stewart <Alexander.Stewart@consensuscorp.com>
Date: Tue, 22 Mar 2016 16:26:53 -0700
Subject: [PATCH 2/9] Rename opensdk dir to open_esplibs

---
 {opensdk => open_esplibs}/component.mk             | 0
 {opensdk => open_esplibs}/libmain/misc.c           | 0
 {opensdk => open_esplibs}/libmain/os_cpu_a.c       | 0
 {opensdk => open_esplibs}/libmain/spi_flash.c      | 0
 {opensdk => open_esplibs}/libmain/timers.c         | 0
 {opensdk => open_esplibs}/libmain/uart.c           | 0
 {opensdk => open_esplibs}/libmain/xtensa_context.S | 0
 parameters.mk                                      | 2 +-
 8 files changed, 1 insertion(+), 1 deletion(-)
 rename {opensdk => open_esplibs}/component.mk (100%)
 rename {opensdk => open_esplibs}/libmain/misc.c (100%)
 rename {opensdk => open_esplibs}/libmain/os_cpu_a.c (100%)
 rename {opensdk => open_esplibs}/libmain/spi_flash.c (100%)
 rename {opensdk => open_esplibs}/libmain/timers.c (100%)
 rename {opensdk => open_esplibs}/libmain/uart.c (100%)
 rename {opensdk => open_esplibs}/libmain/xtensa_context.S (100%)

diff --git a/opensdk/component.mk b/open_esplibs/component.mk
similarity index 100%
rename from opensdk/component.mk
rename to open_esplibs/component.mk
diff --git a/opensdk/libmain/misc.c b/open_esplibs/libmain/misc.c
similarity index 100%
rename from opensdk/libmain/misc.c
rename to open_esplibs/libmain/misc.c
diff --git a/opensdk/libmain/os_cpu_a.c b/open_esplibs/libmain/os_cpu_a.c
similarity index 100%
rename from opensdk/libmain/os_cpu_a.c
rename to open_esplibs/libmain/os_cpu_a.c
diff --git a/opensdk/libmain/spi_flash.c b/open_esplibs/libmain/spi_flash.c
similarity index 100%
rename from opensdk/libmain/spi_flash.c
rename to open_esplibs/libmain/spi_flash.c
diff --git a/opensdk/libmain/timers.c b/open_esplibs/libmain/timers.c
similarity index 100%
rename from opensdk/libmain/timers.c
rename to open_esplibs/libmain/timers.c
diff --git a/opensdk/libmain/uart.c b/open_esplibs/libmain/uart.c
similarity index 100%
rename from opensdk/libmain/uart.c
rename to open_esplibs/libmain/uart.c
diff --git a/opensdk/libmain/xtensa_context.S b/open_esplibs/libmain/xtensa_context.S
similarity index 100%
rename from opensdk/libmain/xtensa_context.S
rename to open_esplibs/libmain/xtensa_context.S
diff --git a/parameters.mk b/parameters.mk
index f14a26b..8c6a8a3 100644
--- a/parameters.mk
+++ b/parameters.mk
@@ -60,7 +60,7 @@ OBJDUMP = $(CROSS)objdump
 
 # Source components to compile and link. Each of these are subdirectories
 # of the root, with a 'component.mk' file.
-COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core opensdk
+COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core open_esplibs
 
 # binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking.
 SDK_LIBS		?= main net80211 phy pp wpa

From 4d6fa0ccfa593ff9fbe0c789771a2309066b4e85 Mon Sep 17 00:00:00 2001
From: Alex Stewart <Alexander.Stewart@consensuscorp.com>
Date: Tue, 22 Mar 2016 17:11:18 -0700
Subject: [PATCH 3/9] Misc post-merge fixups

---
 core/esp_spi.c                | 6 +++---
 include/espressif/spi_flash.h | 8 ++++++--
 open_esplibs/libmain/timers.c | 1 +
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/core/esp_spi.c b/core/esp_spi.c
index c6c0546..7a8704c 100644
--- a/core/esp_spi.c
+++ b/core/esp_spi.c
@@ -178,7 +178,7 @@ static void _spi_buf_prepare(uint8_t bus, size_t len, spi_endianness_t e, spi_wo
     if (e == SPI_LITTLE_ENDIAN || word_size == SPI_32BIT) return;
 
     size_t count = word_size == SPI_16BIT ? (len + 1) / 2 : (len + 3) / 4;
-    uint32_t *data = (uint32_t *)&SPI(bus).W0;
+    uint32_t *data = (uint32_t *)SPI(bus).W;
     for (size_t i = 0; i < count; i ++)
     {
         data[i] = word_size == SPI_16BIT
@@ -193,14 +193,14 @@ static void _spi_buf_transfer(uint8_t bus, const void *out_data, void *in_data,
     _wait(bus);
     size_t bytes = len * (uint8_t)word_size;
     _set_size(bus, bytes);
-    memcpy((void *)&SPI(bus).W0, out_data, bytes);
+    memcpy((void *)SPI(bus).W, out_data, bytes);
     _spi_buf_prepare(bus, len, e, word_size);
     _start(bus);
     _wait(bus);
     if (in_data)
     {
         _spi_buf_prepare(bus, len, e, word_size);
-        memcpy(in_data, (void *)&SPI(bus).W0, bytes);
+        memcpy(in_data, (void *)SPI(bus).W, bytes);
     }
 }
 
diff --git a/include/espressif/spi_flash.h b/include/espressif/spi_flash.h
index f08cda9..61f8ae9 100644
--- a/include/espressif/spi_flash.h
+++ b/include/espressif/spi_flash.h
@@ -36,7 +36,7 @@ sdk_SpiFlashOpResult sdk_spi_flash_erase_sector(uint16_t sec);
    src is pointer to a buffer to read bytes from. Should be 4-byte aligned.
    size is length of buffer in bytes. Should be a multiple of 4.
 */
-sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, const void *src, uint32_t size);
+sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, uint32_t *src, uint32_t size);
 
 /* Read data from flash.
 
@@ -44,8 +44,12 @@ sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, const void *src, uin
    des is pointer to a buffer to read bytes into. Should be 4-byte aligned.
    size is number of bytes to read. Should be a multiple of 4.
 */
-sdk_SpiFlashOpResult sdk_spi_flash_read(uint32_t src_addr, void *des, uint32_t size);
+sdk_SpiFlashOpResult sdk_spi_flash_read(uint32_t src_addr, uint32_t *des, uint32_t size);
 
+/* SDK uses this structure internally to account for flash size.
+
+   See flashchip.h for more info.
+*/
 extern sdk_flashchip_t sdk_flashchip;
 
 #ifdef	__cplusplus
diff --git a/open_esplibs/libmain/timers.c b/open_esplibs/libmain/timers.c
index 1359fc1..1e2a920 100644
--- a/open_esplibs/libmain/timers.c
+++ b/open_esplibs/libmain/timers.c
@@ -1,4 +1,5 @@
 #include "etstimer.h"
+#include "stdio.h"
 
 struct timer_list_st {
     struct timer_list_st *next;

From 3e5af479bc1f02027db340d57870313d02425987 Mon Sep 17 00:00:00 2001
From: Alex Stewart <Alexander.Stewart@consensuscorp.com>
Date: Tue, 22 Mar 2016 17:43:07 -0700
Subject: [PATCH 4/9] Add conditional compilation for open_esplib code

---
 open_esplibs/component.mk             | 18 ++++++++------
 open_esplibs/include/open_esplibs.h   | 36 +++++++++++++++++++++++++++
 open_esplibs/libmain/misc.c           |  6 +++++
 open_esplibs/libmain/os_cpu_a.c       |  5 ++++
 open_esplibs/libmain/spi_flash.c      |  5 ++++
 open_esplibs/libmain/timers.c         |  5 ++++
 open_esplibs/libmain/uart.c           |  5 ++++
 open_esplibs/libmain/xtensa_context.S |  5 ++++
 8 files changed, 78 insertions(+), 7 deletions(-)
 create mode 100644 open_esplibs/include/open_esplibs.h

diff --git a/open_esplibs/component.mk b/open_esplibs/component.mk
index 26fa5ad..23c8b6a 100644
--- a/open_esplibs/component.mk
+++ b/open_esplibs/component.mk
@@ -1,11 +1,15 @@
-# Component makefile for "open sdk libs"
+# Component makefile for "open Espressif libs"
+
+INC_DIRS += $(open_esplibs_ROOT)include
+
+$(eval $(call component_compile_rules,open_esplibs))
 
 # args for passing into compile rule generation
-opensdk_libmain_ROOT = $(opensdk_libmain_DEFAULT_ROOT)libmain
-opensdk_libmain_INC_DIR = 
-opensdk_libmain_SRC_DIR = $(opensdk_libmain_ROOT)
-opensdk_libmain_EXTRA_SRC_FILES = 
+open_esplibs_libmain_ROOT = $(open_esplibs_libmain_DEFAULT_ROOT)libmain
+open_esplibs_libmain_INC_DIR = 
+open_esplibs_libmain_SRC_DIR = $(open_esplibs_libmain_ROOT)
+open_esplibs_libmain_EXTRA_SRC_FILES = 
 
-opensdk_libmain_CFLAGS = $(CFLAGS)
+open_esplibs_libmain_CFLAGS = $(CFLAGS)
 
-$(eval $(call component_compile_rules,opensdk_libmain))
+$(eval $(call component_compile_rules,open_esplibs_libmain))
diff --git a/open_esplibs/include/open_esplibs.h b/open_esplibs/include/open_esplibs.h
new file mode 100644
index 0000000..5443fef
--- /dev/null
+++ b/open_esplibs/include/open_esplibs.h
@@ -0,0 +1,36 @@
+#ifndef _OPEN_ESPLIBS_H
+#define _OPEN_ESPLIBS_H
+
+// This header includes conditional defines to control which bits of the
+// Open-Source libraries get built when building esp-open-rtos.  This can be
+// useful for quickly troubleshooting whether a bug is due to the
+// reimplementation of Espressif libraries, or something else.
+
+#ifndef OPEN_ESPLIBS
+#define OPEN_ESPLIBS 1
+#endif
+
+#ifndef OPEN_LIBMAIN
+#define OPEN_LIBMAIN (OPEN_ESPLIBS)
+#endif
+
+#ifndef OPEN_LIBMAIN_MISC
+#define OPEN_LIBMAIN_MISC (OPEN_LIBMAIN)
+#endif
+#ifndef OPEN_LIBMAIN_OS_CPU_A
+#define OPEN_LIBMAIN_OS_CPU_A (OPEN_LIBMAIN)
+#endif
+#ifndef OPEN_LIBMAIN_SPI_FLASH
+#define OPEN_LIBMAIN_SPI_FLASH (OPEN_LIBMAIN)
+#endif
+#ifndef OPEN_LIBMAIN_TIMERS
+#define OPEN_LIBMAIN_TIMERS (OPEN_LIBMAIN)
+#endif
+#ifndef OPEN_LIBMAIN_UART
+#define OPEN_LIBMAIN_UART (OPEN_LIBMAIN)
+#endif
+#ifndef OPEN_LIBMAIN_XTENSA_CONTEXT
+#define OPEN_LIBMAIN_XTENSA_CONTEXT (OPEN_LIBMAIN)
+#endif
+
+#endif /* _OPEN_ESPLIBS_H */
diff --git a/open_esplibs/libmain/misc.c b/open_esplibs/libmain/misc.c
index 25a059d..8029a38 100644
--- a/open_esplibs/libmain/misc.c
+++ b/open_esplibs/libmain/misc.c
@@ -1,3 +1,7 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_MISC
+// The contents of this file are only built if OPEN_LIBMAIN_MISC is set to true
+
 #include "espressif/esp_misc.h"
 #include "esp/gpio_regs.h"
 #include "esp/rtc_regs.h"
@@ -57,3 +61,5 @@ uint8_t sdk_rtc_get_reset_reason(void) {
     RTC.RESET_REASON0 &= ~RTC_RESET_REASON0_SOMETHING;
     return reason;
 }
+
+#endif /* OPEN_LIBMAIN_MISC */
diff --git a/open_esplibs/libmain/os_cpu_a.c b/open_esplibs/libmain/os_cpu_a.c
index 4841ebe..7908b6f 100644
--- a/open_esplibs/libmain/os_cpu_a.c
+++ b/open_esplibs/libmain/os_cpu_a.c
@@ -1,3 +1,7 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_OS_CPU_A
+// The contents of this file are only built if OPEN_LIBMAIN_OS_CPU_A is set to true
+
 #include "esp/types.h"
 #include "FreeRTOS.h"
 #include "task.h"
@@ -119,3 +123,4 @@ void IRAM sdk__xt_clear_ints(uint32_t mask) {
     WSR(mask, intclear);
 }
 
+#endif /* OPEN_LIBMAIN_OS_CPU_A */
diff --git a/open_esplibs/libmain/spi_flash.c b/open_esplibs/libmain/spi_flash.c
index 2915c79..ee2d2f4 100644
--- a/open_esplibs/libmain/spi_flash.c
+++ b/open_esplibs/libmain/spi_flash.c
@@ -1,3 +1,7 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_SPI_FLASH
+// The contents of this file are only built if OPEN_LIBMAIN_SPI_FLASH is set to true
+
 #include "FreeRTOS.h"
 #include "common_macros.h"
 #include "esp/spi_regs.h"
@@ -181,3 +185,4 @@ sdk_SpiFlashOpResult IRAM sdk_spi_flash_read(uint32_t src_addr, uint32_t *des_ad
     return result;
 }
 
+#endif /* OPEN_LIBMAIN_SPI_FLASH */
diff --git a/open_esplibs/libmain/timers.c b/open_esplibs/libmain/timers.c
index 1e2a920..d460088 100644
--- a/open_esplibs/libmain/timers.c
+++ b/open_esplibs/libmain/timers.c
@@ -1,3 +1,7 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_TIMERS
+// The contents of this file are only built if OPEN_LIBMAIN_TIMERS is set to true
+
 #include "etstimer.h"
 #include "stdio.h"
 
@@ -88,3 +92,4 @@ void sdk_os_timer_disarm(ETSTimer *ptimer) {
     }
 }
 
+#endif /* OPEN_LIBMAIN_TIMERS */
diff --git a/open_esplibs/libmain/uart.c b/open_esplibs/libmain/uart.c
index 25ae961..5ee2699 100644
--- a/open_esplibs/libmain/uart.c
+++ b/open_esplibs/libmain/uart.c
@@ -1,3 +1,7 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_UART
+// The contents of this file are only built if OPEN_LIBMAIN_UART is set to true
+
 #include "espressif/sdk_private.h"
 #include "esp/uart_regs.h"
 
@@ -15,3 +19,4 @@ void sdk_Uart_Init(void) {
     /* No-Op */
 }
 
+#endif /* OPEN_LIBMAIN_UART */
diff --git a/open_esplibs/libmain/xtensa_context.S b/open_esplibs/libmain/xtensa_context.S
index 511877e..139d5db 100644
--- a/open_esplibs/libmain/xtensa_context.S
+++ b/open_esplibs/libmain/xtensa_context.S
@@ -1,3 +1,7 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_XTENSA_CONTEXT
+// The contents of this file are only built if OPEN_LIBMAIN_XTENSA_CONTEXT is set to true
+
         .section .iram1.text, "ax", @progbits
 
         .balign 4
@@ -39,3 +43,4 @@ sdk__xt_context_restore:
         l32i    a13, sp, 64
         ret
 
+#endif /* OPEN_LIBMAIN_XTENSA_CONTEXT */

From 8c9a77efe877e3da39cd6b504c3de3fc5e9a421c Mon Sep 17 00:00:00 2001
From: Alex Stewart <Alexander.Stewart@consensuscorp.com>
Date: Tue, 5 Apr 2016 09:23:28 -0700
Subject: [PATCH 5/9] Added first half of RE'd user_interface.c

---
 core/app_main.c                            |   9 +-
 core/debug_dumps.c                         |   2 +-
 core/include/esp/dport_regs.h              |   4 +
 core/include/esp/rtc_regs.h                |   8 +-
 core/include/esp/sar_regs.h                |  39 ++
 core/include/sdk_internal.h                |  40 +-
 examples/http_get_mbedtls/Makefile         |   2 +-
 examples/pwm_test/Makefile                 |   2 +-
 examples/tls_server/Makefile               |   2 +-
 include/espressif/esp_misc.h               |   2 +
 include/espressif/esp_system.h             |   4 +-
 include/espressif/osapi.h                  |   8 +
 include/espressif/user_interface.h         |  27 +
 open_esplibs/include/esplibs/libmain.h     |  19 +
 open_esplibs/include/esplibs/libnet80211.h |  14 +
 open_esplibs/include/esplibs/libphy.h      |   8 +
 open_esplibs/include/esplibs/libpp.h       |  32 ++
 open_esplibs/include/open_esplibs.h        |   3 +
 open_esplibs/libmain/misc.c                |   2 +-
 open_esplibs/libmain/user_interface.c      | 548 +++++++++++++++++++++
 20 files changed, 745 insertions(+), 30 deletions(-)
 create mode 100644 core/include/esp/sar_regs.h
 create mode 100644 include/espressif/osapi.h
 create mode 100644 include/espressif/user_interface.h
 create mode 100644 open_esplibs/include/esplibs/libmain.h
 create mode 100644 open_esplibs/include/esplibs/libnet80211.h
 create mode 100644 open_esplibs/include/esplibs/libphy.h
 create mode 100644 open_esplibs/include/esplibs/libpp.h
 create mode 100644 open_esplibs/libmain/user_interface.c

diff --git a/core/app_main.c b/core/app_main.c
index ebf9e9a..ac74426 100644
--- a/core/app_main.c
+++ b/core/app_main.c
@@ -27,6 +27,7 @@
 #include "espressif/esp_common.h"
 #include "espressif/phy_info.h"
 #include "sdk_internal.h"
+#include "esplibs/libmain.h"
 
 /* This is not declared in any header file (but arguably should be) */
 
@@ -345,8 +346,8 @@ static __attribute__((noinline)) void user_start_phase2(void) {
     sdk_phy_info_t phy_info, default_phy_info;
 
     sdk_system_rtc_mem_read(0, &sdk_rst_if, sizeof(sdk_rst_if));
-    if (sdk_rst_if.version > 3) {
-        // Bad version number. Probably garbage.
+    if (sdk_rst_if.reason > 3) {
+        // Bad reason. Probably garbage.
         bzero(&sdk_rst_if, sizeof(sdk_rst_if));
     }
     buf = malloc(sizeof(sdk_rst_if));
@@ -357,8 +358,8 @@ static __attribute__((noinline)) void user_start_phase2(void) {
     get_otp_mac_address(sdk_info.sta_mac_addr);
     sdk_wifi_softap_cacl_mac(sdk_info.softap_mac_addr, sdk_info.sta_mac_addr);
     sdk_info._unknown0 = 0x0104a8c0;
-    sdk_info._unknown1 = 0x00ffffff;
-    sdk_info._unknown2 = 0x0104a8c0;
+    sdk_info._unknown4 = 0x00ffffff;
+    sdk_info._unknown8 = 0x0104a8c0;
     init_g_ic();
 
     read_saved_phy_info(&phy_info);
diff --git a/core/debug_dumps.c b/core/debug_dumps.c
index 7f1a1ca..c5af763 100644
--- a/core/debug_dumps.c
+++ b/core/debug_dumps.c
@@ -20,7 +20,7 @@
 #include "esp/rom.h"
 #include "esp/uart.h"
 #include "espressif/esp_common.h"
-#include "sdk_internal.h"
+#include "esplibs/libmain.h"
 
 /* Forward declarations */
 static void IRAM fatal_handler_prelude(void);
diff --git a/core/include/esp/dport_regs.h b/core/include/esp/dport_regs.h
index 87efca1..d04de2f 100644
--- a/core/include/esp/dport_regs.h
+++ b/core/include/esp/dport_regs.h
@@ -90,6 +90,10 @@ _Static_assert(sizeof(struct DPORT_REGS) == 0x60, "DPORT_REGS is the wrong size"
 
 /* Details for CLOCKGATE_WATCHDOG register */
 
+// Set and then cleared during sdk_system_restart_in_nmi().
+// Not sure what this does.  May be related to ESPSAR.UNKNOWN_48
+#define DPORT_CLOCKGATE_WATCHDOG_UNKNOWN_8  BIT(8)
+
 /* Comment found in pvvx/mp3_decode headers: "use clockgate_watchdog(flg) { if(flg) 0x3FF00018 &= 0x77; else 0x3FF00018 |= 8; }".  Not sure what this means or does. */
 
 #define DPORT_CLOCKGATE_WATCHDOG_DISABLE  BIT(3)
diff --git a/core/include/esp/rtc_regs.h b/core/include/esp/rtc_regs.h
index 4acb2a3..1798498 100644
--- a/core/include/esp/rtc_regs.h
+++ b/core/include/esp/rtc_regs.h
@@ -31,7 +31,8 @@ struct RTC_REGS {
     uint32_t volatile CTRL0;        // 0x00
     uint32_t volatile COUNTER_ALARM;    // 0x04
     uint32_t volatile RESET_REASON0;    // 0x08       //FIXME: need better name
-    uint32_t volatile _unknownc[2];     // 0x0c - 0x10
+    uint32_t volatile _unknownc;        // 0x0c
+    uint32_t volatile _unknown10;       // 0x10
     uint32_t volatile RESET_REASON1;    // 0x14       //FIXME: need better name
     uint32_t volatile RESET_REASON2;    // 0x18       //FIXME: need better name
     uint32_t volatile COUNTER;          // 0x1c
@@ -40,7 +41,10 @@ struct RTC_REGS {
     uint32_t volatile INT_ENABLE;       // 0x28
     uint32_t volatile _unknown2c;       // 0x2c
     uint32_t volatile SCRATCH[4];       // 0x30 - 3c
-    uint32_t volatile _unknown40[10];   // 0x40 - 0x64
+    uint32_t volatile _unknown40;       // 0x40
+    uint32_t volatile _unknown44;       // 0x44
+    uint32_t volatile _unknown48;       // 0x48
+    uint32_t volatile _unknown4c[7];    // 0x4c - 0x64
     uint32_t volatile GPIO_OUT;         // 0x68
     uint32_t volatile _unknown6c[2];    // 0x6c - 0x70
     uint32_t volatile GPIO_ENABLE;      // 0x74
diff --git a/core/include/esp/sar_regs.h b/core/include/esp/sar_regs.h
new file mode 100644
index 0000000..b0266b7
--- /dev/null
+++ b/core/include/esp/sar_regs.h
@@ -0,0 +1,39 @@
+/* esp/sar_regs.h
+ *
+ * ESP8266 register definitions for the "sar" region (0x3FF2xxx)
+ *
+ * The 0x60000D00 register region is referred to as "sar" by some old header
+ * files. Apparently referenced both by ROM I2C functions as well as ADC
+ * config/read functions.
+ *
+ * Not compatible with ESP SDK register access code.
+ */
+
+#ifndef _ESP_SAR_REGS_H
+#define _ESP_SAR_REGS_H
+
+#include "esp/types.h"
+#include "common_macros.h"
+
+#define SAR_BASE 0x60000d00
+// Unfortunately,
+// esp-open-sdk/xtensa-lx106-elf/xtensa-lx106-elf/sysroot/usr/include/xtensa/config/specreg.h
+// already has a "SAR" macro definition which would conflict with this, so
+// we'll use "ESPSAR" instead..
+#define ESPSAR (*(struct SAR_REGS *)(SAR_BASE))
+
+/* Note: This memory region is not currently well understood.  Pretty much all
+ * of the definitions here are from reverse-engineering the Espressif SDK code,
+ * many are just educated guesses, and almost certainly some are misleading or
+ * wrong.  If you can improve on any of this, please contribute!
+ */
+
+struct SAR_REGS {
+    uint32_t volatile _unknown0[18];   // 0x00 - 0x44
+    uint32_t volatile UNKNOWN_48;      // 0x48 : used by sdk_system_restart_in_nmi()
+} __attribute__ (( packed ));
+
+_Static_assert(sizeof(struct SAR_REGS) == 0x4c, "SAR_REGS is the wrong size");
+
+#endif /* _ESP_SAR_REGS_H */
+
diff --git a/core/include/sdk_internal.h b/core/include/sdk_internal.h
index b8233fd..4e3faa5 100644
--- a/core/include/sdk_internal.h
+++ b/core/include/sdk_internal.h
@@ -4,6 +4,7 @@
 #include "espressif/esp_wifi.h"
 #include "espressif/spi_flash.h"
 #include "espressif/phy_info.h"
+#include "etstimer.h"
 #include "lwip/netif.h"
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -13,31 +14,38 @@
 // 'info' is declared in app_main.o at .bss+0x4
 
 struct sdk_info_st {
-    uint32_t _unknown0;
-    uint32_t _unknown1;
-    uint32_t _unknown2;
-    uint8_t _unknown3[12];
-    uint8_t softap_mac_addr[6];
-    uint8_t sta_mac_addr[6];
+    uint32_t _unknown0;         // 0x00
+    uint32_t _unknown4;         // 0x04
+    uint32_t _unknown8;         // 0x08
+    ip_addr_t ipaddr;           // 0x0c
+    ip_addr_t netmask;          // 0x10
+    ip_addr_t gw;               // 0x14
+    uint8_t softap_mac_addr[6]; // 0x18
+    uint8_t sta_mac_addr[6];    // 0x1e
 };
 
 extern struct sdk_info_st sdk_info;
 
 // 'rst_if' is declared in user_interface.o at .bss+0xfc
-
-struct sdk_rst_if_st {
-    uint32_t version;
-    uint8_t _unknown[28];
-};
-
-extern struct sdk_rst_if_st sdk_rst_if;
+extern struct sdk_rst_info sdk_rst_if;
 
 // 'g_ic' is declared in libnet80211/ieee80211.o at .bss+0x0
 // See also: http://esp8266-re.foogod.com/wiki/G_ic_(IoT_RTOS_SDK_0.9.9)
 
 struct sdk_g_ic_netif_info {
-    struct netif *netif;
-    //TODO: rest of this structure is unknown.
+    struct netif *netif;     // 0x00
+    ETSTimer timer;          // 0x04 - 0x20
+    uint8_t _unknown20[28];  // 0x20 - 0x3c
+    uint32_t _unknown3c;     // 0x3c (referenced by sdk_wifi_station_disconnect)
+    uint8_t _unknown40[6];   // 0x40 - 0x46
+    uint8_t _unknown46[66];  // 0x46 - 0x88
+    struct sdk_netif_conninfo *_unknown88;  // 0x88
+    uint32_t _unknown8c;     // 0x8c
+    struct sdk_netif_conninfo *conninfo[6]; // 0x90 - 0xa8
+    uint8_t _unknowna8[16];  // 0xa8 - 0xb8
+    uint8_t _unknownb8;      // 0xb8 (referenced by sdk_wifi_station_connect / sdk_wifi_station_disconnect)
+    uint8_t _unknownb9;      // 0xb9 (referenced by sdk_wifi_station_connect / sdk_wifi_station_disconnect)
+    uint8_t connect_status;  // 0xba (referenced by sdk_system_station_got_ip_set / sdk_wifi_station_disconnect)
 };
 
 // This is the portion of g_ic which is not loaded/saved to the flash ROM, and
@@ -197,7 +205,6 @@ extern struct sdk_g_ic_st sdk_g_ic;
 ///////////////////////////////////////////////////////////////////////////////
 
 _Static_assert(sizeof(struct sdk_info_st) == 0x24, "info_st is the wrong size!");
-_Static_assert(sizeof(struct sdk_rst_if_st) == 0x20, "sdk_rst_if_st is the wrong size!");
 _Static_assert(sizeof(struct sdk_g_ic_volatile_st) == 0x1d8, "sdk_g_ic_volatile_st is the wrong size!");
 _Static_assert(sizeof(struct sdk_g_ic_saved_st) == 0x370, "sdk_g_ic_saved_st is the wrong size!");
 _Static_assert(sizeof(struct sdk_g_ic_st) == 0x548, "sdk_g_ic_st is the wrong size!");
@@ -221,7 +228,6 @@ void sdk_pp_soft_wdt_init(void);
 int sdk_register_chipv6_phy(sdk_phy_info_t *);
 void sdk_sleep_reset_analog_rtcreg_8266(void);
 uint32_t sdk_system_get_checksum(uint8_t *, uint32_t);
-void sdk_system_restart_in_nmi(void);
 void sdk_wDevEnableRx(void);
 void sdk_wDev_Initialize(void);
 void sdk_wifi_mode_set(uint8_t);
diff --git a/examples/http_get_mbedtls/Makefile b/examples/http_get_mbedtls/Makefile
index fc9a4fa..7e7a432 100644
--- a/examples/http_get_mbedtls/Makefile
+++ b/examples/http_get_mbedtls/Makefile
@@ -1,4 +1,4 @@
 PROGRAM=http_get_mbedtls
-COMPONENTS = FreeRTOS lwip core extras/mbedtls
+EXTRA_COMPONENTS = extras/mbedtls
 
 include ../../common.mk
diff --git a/examples/pwm_test/Makefile b/examples/pwm_test/Makefile
index 36ee7d0..574420d 100644
--- a/examples/pwm_test/Makefile
+++ b/examples/pwm_test/Makefile
@@ -1,4 +1,4 @@
 # Simple makefile for simple example
 PROGRAM=pwm_test
-COMPONENTS = FreeRTOS lwip core extras/pwm
+EXTRA_COMPONENTS = extras/pwm
 include ../../common.mk
diff --git a/examples/tls_server/Makefile b/examples/tls_server/Makefile
index 2c5ef2c..1070e91 100644
--- a/examples/tls_server/Makefile
+++ b/examples/tls_server/Makefile
@@ -1,4 +1,4 @@
 PROGRAM=tls_server
-COMPONENTS = FreeRTOS lwip core extras/mbedtls
+EXTRA_COMPONENTS = extras/mbedtls
 
 include ../../common.mk
diff --git a/include/espressif/esp_misc.h b/include/espressif/esp_misc.h
index 6490fa5..8427d60 100644
--- a/include/espressif/esp_misc.h
+++ b/include/espressif/esp_misc.h
@@ -27,6 +27,8 @@ void sdk_os_delay_us(uint16_t us);
 void sdk_os_install_putc1(void (*p)(char c));
 void sdk_os_putc(char c);
 
+void sdk_gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/include/espressif/esp_system.h b/include/espressif/esp_system.h
index 04af582..abeb26a 100644
--- a/include/espressif/esp_system.h
+++ b/include/espressif/esp_system.h
@@ -54,8 +54,8 @@ uint32_t sdk_system_get_chip_id(void);
 uint32_t sdk_system_rtc_clock_cali_proc(void);
 uint32_t sdk_system_get_rtc_time(void);
 
-bool sdk_system_rtc_mem_read(uint8_t src, void *dst, uint16_t n);
-bool sdk_system_rtc_mem_write(uint8_t dst, const void *src, uint16_t n);
+bool sdk_system_rtc_mem_read(uint32_t src_addr, void *des_addr, uint16_t save_size);
+bool sdk_system_rtc_mem_write(uint32_t des_addr, void *src_addr, uint16_t save_size);
 
 void sdk_system_uart_swap(void);
 void sdk_system_uart_de_swap(void);
diff --git a/include/espressif/osapi.h b/include/espressif/osapi.h
new file mode 100644
index 0000000..1c1808f
--- /dev/null
+++ b/include/espressif/osapi.h
@@ -0,0 +1,8 @@
+#ifndef _OSAPI_H_
+#define _OSAPI_H_
+
+void sdk_os_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg);
+void sdk_os_timer_arm(ETSTimer *ptimer, uint32_t milliseconds, bool repeat_flag);
+void sdk_os_timer_disarm(ETSTimer *ptimer);
+
+#endif
diff --git a/include/espressif/user_interface.h b/include/espressif/user_interface.h
new file mode 100644
index 0000000..223efba
--- /dev/null
+++ b/include/espressif/user_interface.h
@@ -0,0 +1,27 @@
+#ifndef __USER_INTERFACE_H__
+#define __USER_INTERFACE_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "espressif/esp_wifi.h"
+
+enum sdk_dhcp_status {
+    DHCP_STOPPED,
+    DHCP_STARTED
+};
+
+uint8_t sdk_system_get_boot_version(void);
+uint32_t sdk_system_get_userbin_addr(void);
+uint8_t sdk_system_get_boot_mode(void);
+bool sdk_system_restart_enhance(uint8_t bin_type, uint32_t bin_addr);
+bool sdk_system_upgrade_userbin_set(uint8_t userbin);
+uint8_t sdk_system_upgrade_userbin_check(void);
+bool sdk_system_upgrade_flag_set(uint8_t flag);
+uint8_t sdk_system_upgrade_flag_check(void);
+bool sdk_system_upgrade_reboot(void);
+bool sdk_wifi_station_dhcpc_start(void);
+bool sdk_wifi_station_dhcpc_stop(void);
+enum sdk_dhcp_status sdk_wifi_station_dhcpc_status(void);
+
+#endif
diff --git a/open_esplibs/include/esplibs/libmain.h b/open_esplibs/include/esplibs/libmain.h
new file mode 100644
index 0000000..dc36117
--- /dev/null
+++ b/open_esplibs/include/esplibs/libmain.h
@@ -0,0 +1,19 @@
+#ifndef _ESPLIBS_LIBMAIN_H
+#define _ESPLIBS_LIBMAIN_H
+
+#include "sdk_internal.h"
+
+// misc.c
+int sdk_os_get_cpu_frequency(void);
+void sdk_os_update_cpu_frequency(int freq);
+
+// user_interface.c
+void sdk_system_restart_in_nmi(void);
+int sdk_system_get_test_result(void);
+void sdk_wifi_param_save_protect(struct sdk_g_ic_saved_st *data);
+bool sdk_system_overclock(void);
+bool sdk_system_restoreclock(void);
+uint32_t sdk_system_relative_time(uint32_t reltime);
+
+#endif /* _ESPLIBS_LIBMAIN_H */
+
diff --git a/open_esplibs/include/esplibs/libnet80211.h b/open_esplibs/include/esplibs/libnet80211.h
new file mode 100644
index 0000000..12f5980
--- /dev/null
+++ b/open_esplibs/include/esplibs/libnet80211.h
@@ -0,0 +1,14 @@
+#ifndef _ESPLIBS_LIBNET80211_H
+#define _ESPLIBS_LIBNET80211_H
+
+// Defined in wl_cnx.o
+extern ETSTimer sdk_sta_con_timer;
+
+// Defined in ieee80211_sta.o: .irom0.text+0xcc4
+bool sdk_wifi_station_stop(void);
+
+// Defined in ieee80211_hostap.o: .irom0.text+0x1184
+bool sdk_wifi_softap_stop(void);
+
+#endif /* _ESPLIBS_LIBNET80211_H */
+
diff --git a/open_esplibs/include/esplibs/libphy.h b/open_esplibs/include/esplibs/libphy.h
new file mode 100644
index 0000000..92ec355
--- /dev/null
+++ b/open_esplibs/include/esplibs/libphy.h
@@ -0,0 +1,8 @@
+#ifndef _ESPLIBS_LIBPHY_H
+#define _ESPLIBS_LIBPHY_H
+
+// Defined in phy_chip_v6_ana.o: .irom0.text+0x12d8
+uint32_t sdk_test_tout(bool);
+
+#endif /* _ESPLIBS_LIBPHY_H */
+
diff --git a/open_esplibs/include/esplibs/libpp.h b/open_esplibs/include/esplibs/libpp.h
new file mode 100644
index 0000000..c2ed458
--- /dev/null
+++ b/open_esplibs/include/esplibs/libpp.h
@@ -0,0 +1,32 @@
+#ifndef _ESPLIBS_LIBPP_H
+#define _ESPLIBS_LIBPP_H
+
+// Located in wdev.o
+extern uint32_t sdk_WdevTimOffSet;
+
+// Defined in pp.o: .irom0.text+0xa08
+void sdk_ppRecycleRxPkt(void *);
+
+// Defined in pm.o: .irom0.text+0x74
+uint32_t sdk_pm_rtc_clock_cali_proc(void);
+
+// Defined in pm.o: .irom0.text+0xb8
+void sdk_pm_set_sleep_time(uint32_t);
+
+// Defined in pm.o: .irom0.text+0x1758
+uint8_t sdk_pm_is_waked(void);
+
+// Defined in pm.o: .irom0.text+0x1774
+bool sdk_pm_is_open(void);
+
+// Defined in pm.o: .irom0.text+0x19ac
+bool sdk_pm_post(int);
+
+// Defined in wdev.o: .irom0.text+0x450
+void sdk_wDev_MacTim1SetFunc(void (*func)(void));
+
+// Defined in wdev.o: .text+0x4a8
+void sdk_wDev_MacTim1Arm(uint32_t);
+
+#endif /* _ESPLIBS_LIBPP_H */
+
diff --git a/open_esplibs/include/open_esplibs.h b/open_esplibs/include/open_esplibs.h
index 5443fef..8db3127 100644
--- a/open_esplibs/include/open_esplibs.h
+++ b/open_esplibs/include/open_esplibs.h
@@ -32,5 +32,8 @@
 #ifndef OPEN_LIBMAIN_XTENSA_CONTEXT
 #define OPEN_LIBMAIN_XTENSA_CONTEXT (OPEN_LIBMAIN)
 #endif
+#ifndef OPEN_LIBMAIN_USER_INTERFACE
+#define OPEN_LIBMAIN_USER_INTERFACE (OPEN_LIBMAIN)
+#endif
 
 #endif /* _OPEN_ESPLIBS_H */
diff --git a/open_esplibs/libmain/misc.c b/open_esplibs/libmain/misc.c
index 8029a38..3c1cd02 100644
--- a/open_esplibs/libmain/misc.c
+++ b/open_esplibs/libmain/misc.c
@@ -58,7 +58,7 @@ uint8_t sdk_rtc_get_reset_reason(void) {
             }
         }
     }
-    RTC.RESET_REASON0 &= ~RTC_RESET_REASON0_SOMETHING;
+    RTC.RESET_REASON0 &= ~RTC_RESET_REASON0_BIT21;
     return reason;
 }
 
diff --git a/open_esplibs/libmain/user_interface.c b/open_esplibs/libmain/user_interface.c
new file mode 100644
index 0000000..1533594
--- /dev/null
+++ b/open_esplibs/libmain/user_interface.c
@@ -0,0 +1,548 @@
+#include "open_esplibs.h"
+#if OPEN_LIBMAIN_USER_INTERFACE
+// The contents of this file are only built if OPEN_LIBMAIN_USER_INTERFACE is set to true
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "string.h"
+
+#include "lwip/dhcp.h"
+
+#include "esp/types.h"
+#include "esp/rom.h"
+#include "esp/dport_regs.h"
+#include "esp/rtcmem_regs.h"
+#include "esp/iomux_regs.h"
+#include "esp/sar_regs.h"
+#include "esp/wdev_regs.h"
+
+#include "etstimer.h"
+#include "espressif/sdk_private.h"
+#include "espressif/esp_system.h"
+#include "espressif/esp_wifi.h"
+#include "espressif/esp_sta.h"
+#include "espressif/esp_softap.h"
+#include "espressif/esp_misc.h"
+#include "espressif/osapi.h"
+#include "espressif/user_interface.h"
+
+#include "sdk_internal.h"
+#include "esplibs/libmain.h"
+#include "esplibs/libpp.h"
+#include "esplibs/libphy.h"
+#include "esplibs/libnet80211.h"
+
+// Structure for the data contained in the last sector of Flash which contains
+// meta-info about the saved wifi param sectors.
+struct param_dir_st {
+    uint8_t current_sector;   // 0x00
+    uint32_t cksum_magic;     // 0x04
+    uint32_t save_count;      // 0x08
+    uint32_t cksum_len[2];    // 0x0c
+    uint32_t cksum_value[2];  // 0x14
+};
+_Static_assert(sizeof(struct param_dir_st) == 28, "param_dir_st is the wrong size");
+
+enum sdk_dhcp_status sdk_dhcpc_flag = DHCP_STARTED;
+bool sdk_cpu_overclock;
+struct sdk_rst_info sdk_rst_if;
+sdk_wifi_promiscuous_cb_t sdk_promiscuous_cb;
+
+static uint8_t _system_upgrade_flag; // Ldata009
+
+// Prototypes for static functions
+static bool _check_boot_version(void);
+static void _deep_sleep_phase2(void *timer_arg);
+static struct netif *_get_netif(uint32_t mode);
+
+// Linker-created values used by sdk_system_print_meminfo
+extern uint32_t _data_start, _data_end;
+extern uint32_t _rodata_start, _rodata_end;
+extern uint32_t _bss_start, _bss_end;
+extern uint32_t _heap_start;
+
+#define _rom_reset_vector ((void (*)(void))0x40000080)
+
+void IRAM sdk_system_restart_in_nmi(void) {
+    uint32_t buf[8];
+
+    sdk_system_rtc_mem_read(0, buf, 32);
+    if (buf[0] != 2) {
+        memset(buf, 0, 32);
+        buf[0] = 3;
+        sdk_system_rtc_mem_write(0, buf, 32);
+    }
+    if (!sdk_NMIIrqIsOn) {
+        portENTER_CRITICAL();
+        do {
+            DPORT.DPORT0 = SET_FIELD(DPORT.DPORT0, DPORT_DPORT0_FIELD0, 0);
+        } while (DPORT.DPORT0 & 1);
+    }
+    ESPSAR.UNKNOWN_48 |= 3;
+    DPORT.CLOCKGATE_WATCHDOG |= DPORT_CLOCKGATE_WATCHDOG_UNKNOWN_8;
+    ESPSAR.UNKNOWN_48 &= ~3;
+    DPORT.CLOCKGATE_WATCHDOG &= ~DPORT_CLOCKGATE_WATCHDOG_UNKNOWN_8;
+    Cache_Read_Disable();
+    DPORT.SPI_CACHE_RAM &= ~(DPORT_SPI_CACHE_RAM_BANK0 | DPORT_SPI_CACHE_RAM_BANK1);
+    // This calls directly to 0x40000080, the "reset" exception vector address.
+    _rom_reset_vector();
+}
+
+bool IRAM sdk_system_rtc_mem_write(uint32_t des_addr, void *src_addr, uint16_t save_size) {
+    uint32_t volatile *src_buf = (uint32_t *)src_addr;
+
+    if (des_addr > 191) {
+        return false;
+    }
+    if ((intptr_t)src_addr & 3) {
+        return false;
+    }
+    if ((768 - (des_addr * 4)) < save_size) {
+        return false;
+    }
+    if ((save_size & 3) != 0) {
+        save_size = (save_size & ~3) + 4;
+    }
+    for (uint8_t i = 0; i < (save_size >> 2); i++) {
+        RTCMEM_SYSTEM[i] = src_buf[i];
+    }
+    return true;
+}
+
+bool IRAM sdk_system_rtc_mem_read(uint32_t src_addr, void *des_addr, uint16_t save_size) {
+    uint32_t volatile *src_buf = (uint32_t *)src_addr;
+
+    if (src_addr > 191) {
+        return false;
+    }
+    if ((intptr_t)des_addr & 3) {
+        return false;
+    }
+    if ((768 - (src_addr * 4)) < save_size) {
+        return false;
+    }
+    if ((save_size & 3) != 0) {
+        save_size = (save_size & ~3) + 4;
+    }
+    for (uint8_t i = 0; i < (save_size >> 2); i++) {
+        src_buf[i] = RTCMEM_SYSTEM[i];
+    }
+    return true;
+}
+
+void sdk_system_pp_recycle_rx_pkt(void *eb) {
+        sdk_ppRecycleRxPkt(eb);
+}
+
+uint16_t sdk_system_adc_read(void) {
+        return sdk_test_tout(false);
+}
+
+void sdk_system_restart(void) {
+    if (sdk_wifi_get_opmode() != 2) {
+        sdk_wifi_station_stop();
+    }
+    if (sdk_wifi_get_opmode() != 1) {
+        sdk_wifi_softap_stop();
+    }
+    vTaskDelay(6);
+    IOMUX_GPIO12 |= IOMUX_PIN_PULLUP;
+    sdk_wDev_MacTim1SetFunc(sdk_system_restart_in_nmi);
+    sdk_wDev_MacTim1Arm(3);
+}
+
+void sdk_system_restore(void) {
+    struct sdk_g_ic_saved_st *buf;
+
+    buf = malloc(sizeof(struct sdk_g_ic_saved_st));
+    memset(buf, 0xff, sizeof(struct sdk_g_ic_saved_st));
+    memcpy(buf, &sdk_g_ic.s, 8);
+    sdk_wifi_param_save_protect(buf);
+    free(buf);
+}
+
+uint8_t sdk_system_get_boot_version(void) {
+    return sdk_g_ic.s.boot_info & 0x1f;
+}
+
+static bool _check_boot_version(void) {
+    uint8_t ver = sdk_system_get_boot_version();
+    if (ver < 3 || ver == 31) {
+        printf("failed: need boot >= 1.3\n");
+        return false;
+    }
+    return true;
+}
+
+int sdk_system_get_test_result(void) {
+    if (_check_boot_version()) {
+        return (sdk_g_ic.s.boot_info >> 5) & 1;
+    } else {
+        return -1;
+    }
+}
+
+uint32_t sdk_system_get_userbin_addr(void) {
+    uint8_t buf[8];
+    uint16_t unknown_var = 0; //FIXME: read but never written?
+    uint32_t addr;
+    uint32_t flash_size_code;
+
+    if (!(sdk_g_ic.s.boot_info >> 7)) {
+        if (sdk_g_ic.s._unknown1d8 & 0x4) {
+            addr = sdk_g_ic.s.user1_addr[0] | (sdk_g_ic.s.user1_addr[1] << 8) | 
+(sdk_g_ic.s.user1_addr[2] << 16);
+        } else {
+            addr = sdk_g_ic.s.user0_addr[0] | (sdk_g_ic.s.user0_addr[1] << 8) | (sdk_g_ic.s.user0_addr[2] << 16);
+        }
+    } else {
+        if (!sdk_system_upgrade_userbin_check()) {
+            addr = 0x00001000;
+        } else {
+            sdk_spi_flash_read(0, (uint32_t *)buf, 8);
+            flash_size_code = buf[3] >> 4;
+            if (flash_size_code >= 2 && flash_size_code < 5) {
+                flash_size_code = 0x81;
+            } else if (flash_size_code == 1) {
+                flash_size_code = 0x41;
+            } else {
+                // FIXME: In the original code, this loads from a local stack
+                // variable, which is never actually assigned to anywhere.
+                // It's unclear what this value is actually supposed to be.
+                flash_size_code = unknown_var;
+            }
+            addr = flash_size_code << 12;
+        }
+    }
+    return addr;
+}
+
+uint8_t sdk_system_get_boot_mode(void) {
+    int boot_version = sdk_g_ic.s.boot_info & 0x1f;
+    if (boot_version < 3 || boot_version == 0x1f) {
+        return 1;
+    }
+    return sdk_g_ic.s.boot_info >> 7;
+}
+
+bool sdk_system_restart_enhance(uint8_t bin_type, uint32_t bin_addr) {
+    uint32_t current_addr;
+
+    if (!_check_boot_version()) {
+        return false;
+    }
+    if (bin_type == 0) {
+        current_addr = sdk_system_get_userbin_addr();
+        printf("restart to use user bin @ %x\n", bin_addr);
+        sdk_g_ic.s.user1_addr[0] = bin_addr;
+        sdk_g_ic.s.user1_addr[1] = bin_addr >> 8;
+        sdk_g_ic.s.user1_addr[2] = bin_addr >> 16;
+        sdk_g_ic.s.user0_addr[0] = current_addr;
+        sdk_g_ic.s.user0_addr[1] = current_addr >> 8;
+        sdk_g_ic.s.user0_addr[2] = current_addr >> 16;
+        sdk_g_ic.s._unknown1d8 = (sdk_g_ic.s._unknown1d8 & 0xfb) | 0x04;
+        sdk_g_ic.s.boot_info &= 0x7f;
+        sdk_wifi_param_save_protect(&sdk_g_ic.s);
+        sdk_system_restart();
+        return true;
+    } else {
+        if (bin_type != 1) {
+            printf("don't supported type.\n");
+            return false;
+        }
+        if (!sdk_system_get_test_result()) {
+            printf("test already passed.\n");
+            return false;
+        }
+       
+        printf("reboot to use test bin @ %x\n", bin_addr);
+        sdk_g_ic.s.user0_addr[0] = bin_addr;
+        sdk_g_ic.s.user0_addr[1] = bin_addr >> 8;
+        sdk_g_ic.s.user0_addr[2] = bin_addr >> 16;
+        sdk_g_ic.s.boot_info &= 0xbf;
+        sdk_wifi_param_save_protect(&sdk_g_ic.s);
+        sdk_system_restart();
+       
+        return true;
+    }
+}
+
+bool sdk_system_upgrade_userbin_set(uint8_t userbin) {
+    uint8_t userbin_val, userbin_mask;
+    uint8_t boot_ver = sdk_system_get_boot_version();
+
+    if (userbin >= 2) {
+        return false;
+    } else {
+        if (boot_ver == 2 || boot_ver == 0x1f) {
+            userbin_val = userbin & 0x0f;
+            userbin_mask = 0xf0;
+        } else {
+            userbin_val = userbin & 0x03;
+            userbin_mask = 0xfc;
+        }
+        sdk_g_ic.s._unknown1d8 = (sdk_g_ic.s._unknown1d8 & userbin_mask) | userbin_val;
+        return true;
+    }
+}
+
+uint8_t sdk_system_upgrade_userbin_check(void) {
+    uint8_t boot_ver = sdk_system_get_boot_version();
+    if (boot_ver != 0x1f && boot_ver != 2) {
+        if ((sdk_g_ic.s._unknown1d8 & 0x03) == 1) {
+            if (sdk_g_ic.s._unknown1d8 & 0x4) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else {
+            if (sdk_g_ic.s._unknown1d8 & 0x4) {
+                return 0;
+            } else {
+                return 1;
+            }
+        }
+    } else {
+        if ((sdk_g_ic.s._unknown1d8 & 0x0f) == 1) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+}
+
+bool sdk_system_upgrade_flag_set(uint8_t flag) {
+    if (flag < 3) {
+        _system_upgrade_flag = flag;
+        return true;
+    }
+    return false;
+}
+
+uint8_t sdk_system_upgrade_flag_check(void) {
+    return _system_upgrade_flag;
+}
+
+bool sdk_system_upgrade_reboot(void) {
+    uint8_t boot_ver = sdk_system_get_boot_version();
+    uint8_t new__unknown1d8;
+
+    if (_system_upgrade_flag != 2) {
+        return false;
+    }
+    printf("reboot to use");
+    if (boot_ver != 2 && boot_ver != 0x1f) {
+        sdk_g_ic.s.boot_info = (sdk_g_ic.s.boot_info & 0x7f) | 0x80;
+        sdk_g_ic.s._unknown1d8 = (sdk_g_ic.s._unknown1d8 & 0xfb) | 0x04;
+        if ((sdk_g_ic.s._unknown1d8 & 0x03) == 1) {
+            printf("1\n");
+            new__unknown1d8 = sdk_g_ic.s._unknown1d8 & 0xfc;
+        } else {
+            printf("2\n");
+            new__unknown1d8 = (sdk_g_ic.s._unknown1d8 & 0xfc) | 0x01;
+        }
+    } else {
+        if ((sdk_g_ic.s._unknown1d8 & 0x0f) == 1) {
+            printf("1\n");
+            new__unknown1d8 = sdk_g_ic.s._unknown1d8 & 0xf0;
+        } else {
+            printf("2\n");
+            new__unknown1d8 = (sdk_g_ic.s._unknown1d8 & 0xf0) | 0x01;
+        }
+    }
+    sdk_g_ic.s._unknown1d8 = new__unknown1d8;
+    sdk_wifi_param_save_protect(&sdk_g_ic.s);
+    sdk_system_restart();
+    return true;
+}
+
+static void _deep_sleep_phase2(void *timer_arg) {
+    uint32_t time_in_us = (uint32_t)timer_arg;
+
+    printf("deep sleep %ds\n\n", time_in_us / 1000000);
+    while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(0).STATUS)) {}
+    while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(1).STATUS)) {}
+    RTC.CTRL0 = 0;
+    RTC.CTRL0 &= 0xffffbfff;
+    RTC.CTRL0 |= 0x00000030;
+    RTC._unknown44 = 0x00000004;
+    RTC._unknownc = 0x00010010;
+    RTC._unknown48 = (RTC._unknown48 & 0xffff01ff) | 0x0000fc00;
+    RTC._unknown48 = (RTC._unknown48 & 0xfffffe00) | 0x00000080;
+    RTC.COUNTER_ALARM = RTC.COUNTER + 136;
+    RTC.RESET_REASON2 = 0x00000008;
+    RTC.RESET_REASON0 = 0x00100000;
+    sdk_os_delay_us(200);
+    RTC.GPIO_CFG[2] = 0x00000011;
+    RTC.GPIO_CFG[3] = 0x00000003;
+    RTC._unknownc = 0x000640c8;
+    RTC.CTRL0 &= 0xffffffcf;
+    sdk_pm_rtc_clock_cali_proc();
+    sdk_pm_set_sleep_time(time_in_us);
+    RTC.GPIO_CFG[2] = 0x00000011;
+    RTC.GPIO_CFG[3] = 0x00000003;
+    DPORT.INT_ENABLE &= ~(DPORT_INT_ENABLE_WDT);
+    _xt_isr_mask(1 << ETS_WDT_INUM);
+    RTC._unknown40 = 0xffffffff;
+    RTC._unknown44 = 0x00000020;
+    RTC._unknown10 = 0x00000000;
+    if (time_in_us == 0) {
+        RTC.RESET_REASON2 = 0x00000000;
+    } else {
+        RTC.RESET_REASON2 = 0x00000008;
+    }
+    RTC.RESET_REASON0 = 0x00100000;
+}
+
+void sdk_system_deep_sleep(uint32_t time_in_us) {
+    if (sdk_wifi_get_opmode() != 2) {
+        sdk_wifi_station_stop();
+    }
+    if (sdk_wifi_get_opmode() != 1) {
+        sdk_wifi_softap_stop();
+    }
+    sdk_os_timer_disarm(&sdk_sta_con_timer);
+    sdk_os_timer_setfn(&sdk_sta_con_timer, _deep_sleep_phase2, (void *)time_in_us);
+    sdk_os_timer_arm(&sdk_sta_con_timer, 100, 0);
+}
+
+bool sdk_system_update_cpu_freq(uint8_t freq) {
+    if (freq == 80) {
+        DPORT.CPU_CLOCK &= ~(DPORT_CPU_CLOCK_X2);
+        sdk_os_update_cpu_frequency(80);
+    } else if (freq == 160) {
+        DPORT.CPU_CLOCK |= DPORT_CPU_CLOCK_X2;
+        sdk_os_update_cpu_frequency(160);
+    } else {
+        return false;
+    }
+    return true;
+}
+
+uint8_t sdk_system_get_cpu_freq(void) {
+    return sdk_os_get_cpu_frequency();
+}
+
+bool sdk_system_overclock(void) {
+    if (sdk_system_get_cpu_freq() == 80) {
+        sdk_cpu_overclock = true;
+        sdk_system_update_cpu_freq(160);
+        return true;
+    }
+    return false;
+}
+
+bool sdk_system_restoreclock(void) {
+    if (sdk_system_get_cpu_freq() == 160 && sdk_cpu_overclock) {
+        sdk_cpu_overclock = false;
+        sdk_system_update_cpu_freq(80);
+        return true;
+    }
+    return false;
+}
+
+uint32_t sdk_system_get_time(void) {
+    return WDEV.SYS_TIME + sdk_WdevTimOffSet;
+}
+
+uint32_t sdk_system_relative_time(uint32_t reltime) {
+    return WDEV.SYS_TIME - reltime;
+}
+
+void sdk_system_station_got_ip_set(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw) {
+    uint8_t *ip_bytes = (uint8_t *)&ip->addr;
+    uint8_t *mask_bytes = (uint8_t *)&mask->addr;
+    uint8_t *gw_bytes = (uint8_t *)&gw->addr;
+    uint32_t gpio_mask;
+
+    sdk_g_ic.v.station_netif_info->connect_status = STATION_GOT_IP;
+    printf("ip:%d.%d.%d.%d,mask:%d.%d.%d.%d,gw:%d.%d.%d.%d", ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3], mask_bytes[0], mask_bytes[1], mask_bytes[2], mask_bytes[3], gw_bytes[0], gw_bytes[1], gw_bytes[2], gw_bytes[3]);
+    printf("\n");
+    if ((sdk_g_ic.s.wifi_led_enable == 1) && (sdk_g_ic.s.wifi_mode == 1)) {
+        sdk_os_timer_disarm(&sdk_sta_con_timer);
+        gpio_mask = 1 << sdk_g_ic.s.wifi_led_gpio;
+        sdk_gpio_output_set(0, gpio_mask, gpio_mask, 0);
+    }
+}
+
+void sdk_system_print_meminfo(void) {
+    printf("%s: 0x%x ~ 0x%x, len: %d\n", "data  ", _data_start, _data_end, _data_end - _data_start);
+    printf("%s: 0x%x ~ 0x%x, len: %d\n", "rodata", _rodata_start, _rodata_end, _rodata_end - _rodata_start);
+    printf("%s: 0x%x ~ 0x%x, len: %d\n", "bss   ", _bss_start, _bss_end, _bss_end - _bss_start);
+    printf("%s: 0x%x ~ 0x%x, len: %d\n", "heap  ", _heap_start, 0x3fffc000, 0x3fffc000 - _heap_start);
+}
+
+uint32_t sdk_system_get_free_heap_size(void) {
+    return xPortGetFreeHeapSize();
+}
+
+uint32_t sdk_system_get_chip_id(void) {
+    uint32_t mac0 = DPORT.OTP_MAC0 & 0xff000000;
+    uint32_t mac1 = DPORT.OTP_MAC1 & 0x00ffffff;
+    return (mac1 << 8) | (mac0 >> 24);
+}
+
+uint32_t sdk_system_rtc_clock_cali_proc(void) {
+    return sdk_pm_rtc_clock_cali_proc();
+}
+    
+uint32_t sdk_system_get_rtc_time(void) {
+    return RTC.COUNTER;
+}
+
+struct sdk_rst_info *sdk_system_get_rst_info(void) {
+    return &sdk_rst_if;
+}
+
+static struct netif *_get_netif(uint32_t mode) {
+    struct sdk_g_ic_netif_info *info;
+
+    if (mode >= 2) {
+        return NULL;
+    }
+    if (mode == 0) {
+        info = sdk_g_ic.v.station_netif_info;
+    } else {
+        info = sdk_g_ic.v.softap_netif_info;
+    }
+    if (info) {
+        return info->netif;
+    }
+    return NULL;
+}
+
+bool sdk_wifi_station_dhcpc_start(void) {
+    struct netif *netif = _get_netif(0);
+    if (sdk_wifi_get_opmode() == 2) {
+        return false;
+    }
+    if (netif && sdk_dhcpc_flag == DHCP_STOPPED) {
+        sdk_info.ipaddr.addr = 0;
+        sdk_info.netmask.addr = 0;
+        sdk_info.gw.addr = 0;
+        netif_set_addr(netif, &sdk_info.ipaddr, &sdk_info.netmask, &sdk_info.gw);
+        if (dhcp_start(netif)) {
+            return false;
+        }
+    }
+    sdk_dhcpc_flag = DHCP_STARTED;
+    return true;
+}
+
+bool sdk_wifi_station_dhcpc_stop(void) {
+    struct netif *netif = _get_netif(0);
+    if (sdk_wifi_get_opmode() == 2) {
+        return false;
+    }
+    if (netif && sdk_dhcpc_flag == DHCP_STARTED) {
+        dhcp_stop(netif);
+    }
+    sdk_dhcpc_flag = DHCP_STOPPED;
+    return true;
+}
+
+enum sdk_dhcp_status sdk_wifi_station_dhcpc_status(void) {
+    return sdk_dhcpc_flag;
+}
+
+#endif /* OPEN_LIBMAIN_USER_INTERFACE */

From e3827b2f1ca5a0c1d0512b18da7e9520fdc3c7a1 Mon Sep 17 00:00:00 2001
From: Angus Gratton <gus@projectgus.com>
Date: Thu, 30 Jun 2016 09:51:02 +1000
Subject: [PATCH 6/9] Fix rboot-api sdk_spi_flash_read pointer types

---
 extras/rboot-ota/rboot-api.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/extras/rboot-ota/rboot-api.c b/extras/rboot-ota/rboot-api.c
index b9a5e57..85b459d 100644
--- a/extras/rboot-ota/rboot-api.c
+++ b/extras/rboot-ota/rboot-api.c
@@ -249,7 +249,7 @@ bool rboot_verify_image(uint32_t initial_offset, uint32_t *image_length, const c
     /* sanity limit on how far we can read */
     uint32_t end_limit = offset + 0x100000;
     image_header_t image_header __attribute__((aligned(4)));
-    if(sdk_spi_flash_read(offset, &image_header, sizeof(image_header_t))) {
+    if(sdk_spi_flash_read(offset, (uint32_t *)&image_header, sizeof(image_header_t))) {
         error = "Flash fail";
         goto fail;
     }
@@ -271,7 +271,7 @@ bool rboot_verify_image(uint32_t initial_offset, uint32_t *image_length, const c
     {
         /* read section header */
         section_header_t header __attribute__((aligned(4)));
-        if(sdk_spi_flash_read(offset, &header, sizeof(section_header_t))) {
+        if(sdk_spi_flash_read(offset, (uint32_t *)&header, sizeof(section_header_t))) {
             error = "Flash fail";
             goto fail;
         }
@@ -359,7 +359,7 @@ bool rboot_digest_image(uint32_t offset, uint32_t image_length, rboot_digest_upd
 {
     uint8_t buf[32] __attribute__((aligned(4)));
     for(int i = 0; i < image_length; i += sizeof(buf)) {
-        if(sdk_spi_flash_read(offset+i, buf, sizeof(buf)))
+        if(sdk_spi_flash_read(offset+i, (uint32_t *)buf, sizeof(buf)))
             return false;
         uint32_t digest_len = sizeof(buf);
         if(i + digest_len  > image_length)

From 701a4c42846c8ac8ffd0b10c4baf1eb3dabfb4a9 Mon Sep 17 00:00:00 2001
From: Angus Gratton <gus@projectgus.com>
Date: Thu, 30 Jun 2016 09:30:21 +1000
Subject: [PATCH 7/9] sdk_system_rtc_mem_read: Fix destination buffer pointer

---
 open_esplibs/libmain/user_interface.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/open_esplibs/libmain/user_interface.c b/open_esplibs/libmain/user_interface.c
index 1533594..9d6865b 100644
--- a/open_esplibs/libmain/user_interface.c
+++ b/open_esplibs/libmain/user_interface.c
@@ -110,7 +110,7 @@ bool IRAM sdk_system_rtc_mem_write(uint32_t des_addr, void *src_addr, uint16_t s
 }
 
 bool IRAM sdk_system_rtc_mem_read(uint32_t src_addr, void *des_addr, uint16_t save_size) {
-    uint32_t volatile *src_buf = (uint32_t *)src_addr;
+    uint32_t *dest_buf = (uint32_t *)des_addr;
 
     if (src_addr > 191) {
         return false;
@@ -125,7 +125,7 @@ bool IRAM sdk_system_rtc_mem_read(uint32_t src_addr, void *des_addr, uint16_t sa
         save_size = (save_size & ~3) + 4;
     }
     for (uint8_t i = 0; i < (save_size >> 2); i++) {
-        src_buf[i] = RTCMEM_SYSTEM[i];
+        dest_buf[i] = RTCMEM_SYSTEM[i];
     }
     return true;
 }

From 678b59babfdc30b473d43c0b054ad06938e23601 Mon Sep 17 00:00:00 2001
From: Angus Gratton <gus@projectgus.com>
Date: Thu, 30 Jun 2016 09:22:17 +1000
Subject: [PATCH 8/9] Honour values of configCPU_CLOCK_HZ & configTICK_RATE_HZ
 for tick rate

Fixes #147

* Can vary tick rate from 100Hz via configTICK_RATE_HZ. Note that the
  SDK binary libraries are hard-coded to assume the tick rate is 100Hz,
  so changing the tick rate may have unexpected consequences for lower
  layer WiFi behaviour (such as certain kinds of timeouts happening
  faster/slower.)

* Setting configCPU_CLOCK_HZ to 160MHz means ESP will set 160MHz during
  initialisation. Only 80MHz and 160MHz are supported.

* Timing of tasks is no longer affected by current CPU freq (whether set
  via configCPU_CLOCK_HZ or via sdk_system_update_cpu_freq().)
  Previously doubling the CPU frequency would double the tick rate.
---
 FreeRTOS/Source/include/FreeRTOSConfig.h | 7 +++++++
 core/app_main.c                          | 4 ++++
 examples/blink/blink.c                   | 1 +
 open_esplibs/include/esplibs/libmain.h   | 4 ++++
 open_esplibs/libmain/os_cpu_a.c          | 5 +++--
 5 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/FreeRTOS/Source/include/FreeRTOSConfig.h b/FreeRTOS/Source/include/FreeRTOSConfig.h
index 6604df3..d886828 100644
--- a/FreeRTOS/Source/include/FreeRTOSConfig.h
+++ b/FreeRTOS/Source/include/FreeRTOSConfig.h
@@ -34,6 +34,13 @@
 #define configUSE_TICK_HOOK			0
 #endif
 #ifndef configCPU_CLOCK_HZ
+/* This is the _default_ clock speed for the CPU. Can be either 80MHz
+ * or 160MHz, and the system will set the clock speed to match at startup.
+
+Note that it's possible to change the clock speed at runtime, so you
+can/should use sdk_system_get_cpu_frequency() in order to determine the
+current CPU frequency, in preference to this macro.
+*/
 #define configCPU_CLOCK_HZ			( ( unsigned long ) 80000000 )
 #endif
 #ifndef configTICK_RATE_HZ
diff --git a/core/app_main.c b/core/app_main.c
index ac74426..43fed17 100644
--- a/core/app_main.c
+++ b/core/app_main.c
@@ -382,6 +382,10 @@ static __attribute__((noinline)) void user_start_phase2(void) {
 
     srand(hwrand()); /* seed libc rng */
 
+    // Set intial CPU clock speed to 160MHz if necessary
+    _Static_assert(configCPU_CLOCK_HZ == 80000000 || configCPU_CLOCK_HZ == 160000000, "FreeRTOSConfig must define initial clock speed as either 80MHz or 160MHz");
+    sdk_system_update_cpu_freq(configCPU_CLOCK_HZ / 1000000);
+
     // Call gcc constructor functions
     void (**ctor)(void);
     for ( ctor = &__init_array_start; ctor != &__init_array_end; ++ctor) {
diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index 9d2ae3c..1539b67 100644
--- a/examples/blink/blink.c
+++ b/examples/blink/blink.c
@@ -2,6 +2,7 @@
  *
  * This sample code is in the public domain.
  */
+#include <stdlib.h>
 #include "espressif/esp_common.h"
 #include "esp/uart.h"
 #include "FreeRTOS.h"
diff --git a/open_esplibs/include/esplibs/libmain.h b/open_esplibs/include/esplibs/libmain.h
index dc36117..98ccb54 100644
--- a/open_esplibs/include/esplibs/libmain.h
+++ b/open_esplibs/include/esplibs/libmain.h
@@ -1,3 +1,4 @@
+#include "sdk_internal.h"
 #ifndef _ESPLIBS_LIBMAIN_H
 #define _ESPLIBS_LIBMAIN_H
 
@@ -5,6 +6,9 @@
 
 // misc.c
 int sdk_os_get_cpu_frequency(void);
+
+/* Don't call this function from user code, it doesn't change the CPU
+ * speed. Call sdk_system_update_cpu_freq() instead. */
 void sdk_os_update_cpu_frequency(int freq);
 
 // user_interface.c
diff --git a/open_esplibs/libmain/os_cpu_a.c b/open_esplibs/libmain/os_cpu_a.c
index 7908b6f..dac5247 100644
--- a/open_esplibs/libmain/os_cpu_a.c
+++ b/open_esplibs/libmain/os_cpu_a.c
@@ -7,6 +7,7 @@
 #include "task.h"
 #include "xtensa_ops.h"
 #include "common_macros.h"
+#include "esplibs/libmain.h"
 
 // xPortSysTickHandle is defined in FreeRTOS/Source/portable/esp8266/port.c but
 // does not exist in any header files.
@@ -66,7 +67,7 @@ void IRAM sdk__xt_int_exit(void) {
 void IRAM sdk__xt_timer_int(void) {
     uint32_t trigger_ccount;
     uint32_t current_ccount;
-    uint32_t ccount_interval = portTICK_RATE_MS * 80000; //FIXME
+    uint32_t ccount_interval = portTICK_RATE_MS * sdk_os_get_cpu_frequency() * 1000;
 
     do {
         RSR(trigger_ccount, ccompare0);
@@ -87,7 +88,7 @@ void IRAM sdk__xt_timer_int1(void) {
 void IRAM sdk__xt_tick_timer_init(void) {
     uint32_t ints_enabled;
     uint32_t current_ccount;
-    uint32_t ccount_interval = portTICK_RATE_MS * 80000; //FIXME
+    uint32_t ccount_interval = portTICK_RATE_MS * sdk_os_get_cpu_frequency() * 1000;
 
     RSR(current_ccount, ccount);
     WSR(current_ccount + ccount_interval, ccompare0);

From 6c9d478336e9976d6844cb32241183546465ed9b Mon Sep 17 00:00:00 2001
From: Angus Gratton <gus@projectgus.com>
Date: Thu, 30 Jun 2016 16:08:59 +1000
Subject: [PATCH 9/9] open_esplibs: Add README and Copyright headers

---
 open_esplibs/README.md                     | 15 +++++++++++++++
 open_esplibs/include/esplibs/libmain.h     |  8 ++++++++
 open_esplibs/include/esplibs/libnet80211.h |  8 ++++++++
 open_esplibs/include/esplibs/libphy.h      |  8 ++++++++
 open_esplibs/include/esplibs/libpp.h       |  8 ++++++++
 open_esplibs/libmain/misc.c                |  5 +++++
 open_esplibs/libmain/os_cpu_a.c            |  5 +++++
 open_esplibs/libmain/spi_flash.c           |  5 +++++
 open_esplibs/libmain/timers.c              |  5 +++++
 open_esplibs/libmain/uart.c                |  5 +++++
 open_esplibs/libmain/user_interface.c      |  5 +++++
 open_esplibs/libmain/xtensa_context.S      |  5 +++++
 12 files changed, 82 insertions(+)
 create mode 100644 open_esplibs/README.md

diff --git a/open_esplibs/README.md b/open_esplibs/README.md
new file mode 100644
index 0000000..ba11452
--- /dev/null
+++ b/open_esplibs/README.md
@@ -0,0 +1,15 @@
+# Open Espressif Libs
+
+These are functional recreations of the MIT licensed binary Espressif SDK libraries found in `lib`. They keep the same functionality as the SDK libraries (possibly with bugfixes or other minor tweaks), but are compiled from source.
+
+Most of the reverse engineering work so far has been by Alex Stewart (@foogod).
+
+See http://esp8266-re.foogod.com/wiki/ for more technical details of SDK library internals.
+
+# Disabling
+
+The open ESP libs are compiled in by default, and they automatically replace any binary SDK symbols (functions, etc.) with the same names.
+
+To compile using the binary SDK libraries only, override the COMPONENTS list in parameters.mk to remove the open_esplibs component, or add -DOPEN_ESPLIBS=0 to CPPFLAGS.
+
+To selectively replace some functionality with binary SDK functionality for debugging, edit the header file open_esplibs/include/open_esplibs.h
diff --git a/open_esplibs/include/esplibs/libmain.h b/open_esplibs/include/esplibs/libmain.h
index 98ccb54..9bbfe6f 100644
--- a/open_esplibs/include/esplibs/libmain.h
+++ b/open_esplibs/include/esplibs/libmain.h
@@ -1,3 +1,11 @@
+/* Internal function declarations for Espressif SDK libmain functions.
+
+   These are internal-facing declarations, it is not recommended to include these headers in your program.
+   (look at the headers in include/espressif/ instead and use these whenever possible.)
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE.
+*/
 #include "sdk_internal.h"
 #ifndef _ESPLIBS_LIBMAIN_H
 #define _ESPLIBS_LIBMAIN_H
diff --git a/open_esplibs/include/esplibs/libnet80211.h b/open_esplibs/include/esplibs/libnet80211.h
index 12f5980..1c0ac9a 100644
--- a/open_esplibs/include/esplibs/libnet80211.h
+++ b/open_esplibs/include/esplibs/libnet80211.h
@@ -1,3 +1,11 @@
+/* Internal function declarations for Espressif SDK libnet80211 functions.
+
+   These are internal-facing declarations, it is not recommended to include these headers in your program.
+   (look at the headers in include/espressif/ instead and use these whenever possible.)
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE.
+*/
 #ifndef _ESPLIBS_LIBNET80211_H
 #define _ESPLIBS_LIBNET80211_H
 
diff --git a/open_esplibs/include/esplibs/libphy.h b/open_esplibs/include/esplibs/libphy.h
index 92ec355..2c7639c 100644
--- a/open_esplibs/include/esplibs/libphy.h
+++ b/open_esplibs/include/esplibs/libphy.h
@@ -1,3 +1,11 @@
+/* Internal function declarations for Espressif SDK libphy functions.
+
+   These are internal-facing declarations, it is not recommended to include these headers in your program.
+   (look at the headers in include/espressif/ instead and use these whenever possible.)
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE.
+*/
 #ifndef _ESPLIBS_LIBPHY_H
 #define _ESPLIBS_LIBPHY_H
 
diff --git a/open_esplibs/include/esplibs/libpp.h b/open_esplibs/include/esplibs/libpp.h
index c2ed458..238ad02 100644
--- a/open_esplibs/include/esplibs/libpp.h
+++ b/open_esplibs/include/esplibs/libpp.h
@@ -1,3 +1,11 @@
+/* Internal function declarations for Espressif SDK libpp functions.
+
+   These are internal-facing declarations, it is not recommended to include these headers in your program.
+   (look at the headers in include/espressif/ instead and use these whenever possible.)
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE.
+*/
 #ifndef _ESPLIBS_LIBPP_H
 #define _ESPLIBS_LIBPP_H
 
diff --git a/open_esplibs/libmain/misc.c b/open_esplibs/libmain/misc.c
index 3c1cd02..f11d4fd 100644
--- a/open_esplibs/libmain/misc.c
+++ b/open_esplibs/libmain/misc.c
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain misc.o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_MISC
 // The contents of this file are only built if OPEN_LIBMAIN_MISC is set to true
diff --git a/open_esplibs/libmain/os_cpu_a.c b/open_esplibs/libmain/os_cpu_a.c
index dac5247..9ace3a8 100644
--- a/open_esplibs/libmain/os_cpu_a.c
+++ b/open_esplibs/libmain/os_cpu_a.c
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain os_cpu_o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_OS_CPU_A
 // The contents of this file are only built if OPEN_LIBMAIN_OS_CPU_A is set to true
diff --git a/open_esplibs/libmain/spi_flash.c b/open_esplibs/libmain/spi_flash.c
index ee2d2f4..91ee829 100644
--- a/open_esplibs/libmain/spi_flash.c
+++ b/open_esplibs/libmain/spi_flash.c
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain os_cpu_o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_SPI_FLASH
 // The contents of this file are only built if OPEN_LIBMAIN_SPI_FLASH is set to true
diff --git a/open_esplibs/libmain/timers.c b/open_esplibs/libmain/timers.c
index d460088..4c1edb9 100644
--- a/open_esplibs/libmain/timers.c
+++ b/open_esplibs/libmain/timers.c
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain timers.o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_TIMERS
 // The contents of this file are only built if OPEN_LIBMAIN_TIMERS is set to true
diff --git a/open_esplibs/libmain/uart.c b/open_esplibs/libmain/uart.c
index 5ee2699..b93d681 100644
--- a/open_esplibs/libmain/uart.c
+++ b/open_esplibs/libmain/uart.c
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain uart.o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_UART
 // The contents of this file are only built if OPEN_LIBMAIN_UART is set to true
diff --git a/open_esplibs/libmain/user_interface.c b/open_esplibs/libmain/user_interface.c
index 9d6865b..5e89424 100644
--- a/open_esplibs/libmain/user_interface.c
+++ b/open_esplibs/libmain/user_interface.c
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain user_interface.o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_USER_INTERFACE
 // The contents of this file are only built if OPEN_LIBMAIN_USER_INTERFACE is set to true
diff --git a/open_esplibs/libmain/xtensa_context.S b/open_esplibs/libmain/xtensa_context.S
index 139d5db..9e94cfd 100644
--- a/open_esplibs/libmain/xtensa_context.S
+++ b/open_esplibs/libmain/xtensa_context.S
@@ -1,3 +1,8 @@
+/* Recreated Espressif libmain xtensa_context.o contents.
+
+   Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries.
+   BSD Licensed as described in the file LICENSE
+*/
 #include "open_esplibs.h"
 #if OPEN_LIBMAIN_XTENSA_CONTEXT
 // The contents of this file are only built if OPEN_LIBMAIN_XTENSA_CONTEXT is set to true