From 5b36f32996ff58da81d3c65e31f5349d498e09e4 Mon Sep 17 00:00:00 2001
From: Deomid Ryabkov <rojer@cesanta.com>
Date: Tue, 24 Nov 2015 00:11:51 +0000
Subject: [PATCH] Add ESP8266 RTOS example

    PUBLISHED_FROM=892d01b09f5801d3d19e6db1ce22b7916d2f83d5
---
 examples/ESP8266_RTOS/Makefile         | 118 +++++++++++++++++
 examples/ESP8266_RTOS/README.md        |  26 ++++
 examples/ESP8266_RTOS/gen_misc.sh      | 173 +++++++++++++++++++++++++
 examples/ESP8266_RTOS/readme.txt       |  56 ++++++++
 examples/ESP8266_RTOS/user/Makefile    |  47 +++++++
 examples/ESP8266_RTOS/user/esp_libc.c  |  54 ++++++++
 examples/ESP8266_RTOS/user/mongoose.c  |   1 +
 examples/ESP8266_RTOS/user/mongoose.h  |   1 +
 examples/ESP8266_RTOS/user/user_main.c | 108 +++++++++++++++
 9 files changed, 584 insertions(+)
 create mode 100644 examples/ESP8266_RTOS/Makefile
 create mode 100644 examples/ESP8266_RTOS/README.md
 create mode 100644 examples/ESP8266_RTOS/gen_misc.sh
 create mode 100644 examples/ESP8266_RTOS/readme.txt
 create mode 100644 examples/ESP8266_RTOS/user/Makefile
 create mode 100644 examples/ESP8266_RTOS/user/esp_libc.c
 create mode 120000 examples/ESP8266_RTOS/user/mongoose.c
 create mode 120000 examples/ESP8266_RTOS/user/mongoose.h
 create mode 100644 examples/ESP8266_RTOS/user/user_main.c

diff --git a/examples/ESP8266_RTOS/Makefile b/examples/ESP8266_RTOS/Makefile
new file mode 100644
index 000000000..0317ff878
--- /dev/null
+++ b/examples/ESP8266_RTOS/Makefile
@@ -0,0 +1,118 @@
+#############################################################
+# Required variables for each makefile
+# Discard this section from all parent makefiles
+# Expected variables (with automatic defaults):
+#   CSRCS (all "C" files in the dir)
+#   SUBDIRS (all subdirs with a Makefile)
+#   GEN_LIBS - list of libs to be generated ()
+#   GEN_IMAGES - list of object file images to be generated ()
+#   GEN_BINS - list of binaries to be generated ()
+#   COMPONENTS_xxx - a list of libs/objs in the form
+#     subdir/lib to be extracted and rolled up into
+#     a generated lib/image xxx.a ()
+#
+TARGET = eagle
+#FLAVOR = release
+FLAVOR = debug
+
+EXTRA_CCFLAGS += -Wall -Werror
+
+ifndef PDIR # {
+GEN_IMAGES= eagle.app.v6.out
+GEN_BINS= eagle.app.v6.bin
+SPECIAL_MKTARGETS=$(APP_MKTARGETS)
+SUBDIRS=user
+
+endif # } PDIR
+
+LDDIR = $(SDK_PATH)/ld
+
+CCFLAGS += -Os
+
+TARGET_LDFLAGS =		\
+	-nostdlib		\
+	-Wl,-EL \
+	--longcalls \
+	--text-section-literals
+
+ifeq ($(FLAVOR),debug)
+    TARGET_LDFLAGS += -g -O2
+endif
+
+ifeq ($(FLAVOR),release)
+    TARGET_LDFLAGS += -g -O0
+endif
+
+COMPONENTS_eagle.app.v6 = \
+	user/libuser.a
+
+LINKFLAGS_eagle.app.v6 = \
+	-L$(SDK_PATH)/lib        \
+	-Wl,--gc-sections   \
+	-nostdlib	\
+    -T$(LD_FILE)   \
+	-Wl,--no-check-sections	\
+    -u call_user_start	\
+	-Wl,-static						\
+	-Wl,--start-group					\
+	-lcirom \
+	-lgcc					\
+	-lhal					\
+	-lphy	\
+	-lpp	\
+	-lnet80211	\
+	-lwpa	\
+	-lcrypto    \
+	-lmain	\
+	-lfreertos	\
+	-llwip	\
+	$(DEP_LIBS_eagle.app.v6)					\
+	-Wl,--end-group
+
+DEPENDS_eagle.app.v6 = \
+                $(LD_FILE) \
+                $(LDDIR)/eagle.rom.addr.v6.ld
+
+#############################################################
+# Configuration i.e. compile options etc.
+# Target specific stuff (defines etc.) goes in here!
+# Generally values applying to a tree are captured in the
+#   makefile at its root level - these are then overridden
+#   for a subtree within the makefile rooted therein
+#
+
+#UNIVERSAL_TARGET_DEFINES =		\
+
+# Other potential configuration flags include:
+#	-DTXRX_TXBUF_DEBUG
+#	-DTXRX_RXBUF_DEBUG
+#	-DWLAN_CONFIG_CCX
+CONFIGURATION_DEFINES =	-DICACHE_FLASH
+
+DEFINES +=				\
+	$(UNIVERSAL_TARGET_DEFINES)	\
+	$(CONFIGURATION_DEFINES)
+
+DDEFINES +=				\
+	$(UNIVERSAL_TARGET_DEFINES)	\
+	$(CONFIGURATION_DEFINES)
+
+
+#############################################################
+# Recursion Magic - Don't touch this!!
+#
+# Each subtree potentially has an include directory
+#   corresponding to the common APIs applicable to modules
+#   rooted at that subtree. Accordingly, the INCLUDE PATH
+#   of a module can only contain the include directories up
+#   its parent path, and not its siblings
+#
+# Required for each makefile to inherit from the parent
+#
+
+INCLUDES := $(INCLUDES) -I $(PDIR)include
+sinclude $(SDK_PATH)/Makefile
+
+.PHONY: FORCE
+FORCE:
+
diff --git a/examples/ESP8266_RTOS/README.md b/examples/ESP8266_RTOS/README.md
new file mode 100644
index 000000000..f2a3c559c
--- /dev/null
+++ b/examples/ESP8266_RTOS/README.md
@@ -0,0 +1,26 @@
+This is a Mongoose "Hello, world" that can be compiled under ESP8266 RTOS SDK.
+
+It sets up an AP (SSID `Mongoose`) and serves a "hello world" page on http://192.168.4.1/
+
+Most of the the boilerplate comes from [project_template](https://github.com/espressif/ESP8266_RTOS_SDK/tree/master/examples/project_template) (@ [3ca6af5](https://github.com/espressif/ESP8266_RTOS_SDK/tree/3ca6af5da68678d809b34c7cd98bee71e0235039/examples/project_template)) with minimal changes.
+
+To build with no changes to the SDK, you will need a module with 1MB (8Mb) flash or more.
+
+Compile (for NodeMCU 1.0):
+
+```
+$ export SDK_PATH=/path/to/ESP8266_RTOS_SDK
+$ export BIN_PATH=./bin
+$ make clean; make BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=dio SPI_SIZE_MAP=6
+```
+
+Flash (using [esptool](https://github.com/themadinventor/esptool)):
+
+```
+$ esptool.py --port /dev/ttyUSB0 --baud 230400 \
+    write_flash --flash_mode=dio --flash_size=32m \
+    0x00000 ${SDK_PATH}/bin/boot_v1.4\(b1\).bin \
+    0x01000 ${BIN_PATH}/upgrade/user1.4096.new.6.bin
+```
+
+Note: the output can be made to fit in 512KB (4Mb) by moving `irom0_0_seg` in [eagle.app.v6.ld](https://github.com/espressif/ESP8266_RTOS_SDK/blob/master/ld/eagle.app.v6.ld) and increasing its size.
diff --git a/examples/ESP8266_RTOS/gen_misc.sh b/examples/ESP8266_RTOS/gen_misc.sh
new file mode 100644
index 000000000..7dcf6645c
--- /dev/null
+++ b/examples/ESP8266_RTOS/gen_misc.sh
@@ -0,0 +1,173 @@
+#!/bin/bash
+
+:<<!
+******NOTICE******
+MUST set SDK_PATH & BIN_PATH firstly!!!
+example:
+export SDK_PATH=~/ESP8266_RTOS_SDK
+export BIN_PATH=~/esp8266_bin
+!
+
+echo "gen_misc.sh version 20150911"
+echo ""
+
+if [ $SDK_PATH ]; then
+    echo "SDK_PATH:"
+    echo "$SDK_PATH"
+    echo ""
+else
+    echo "ERROR: Please export SDK_PATH in gen_misc.sh firstly, exit!!!"
+    exit
+fi
+
+if [ $BIN_PATH ]; then
+    echo "BIN_PATH:"
+    echo "$BIN_PATH"
+    echo ""
+else
+    echo "ERROR: Please export BIN_PATH in gen_misc.sh firstly, exit!!!"
+    exit
+fi
+
+echo "Please check SDK_PATH & BIN_PATH, enter (Y/y) to continue:"
+read input
+
+if [[ $input != Y ]] && [[ $input != y ]]; then
+    exit
+fi
+
+echo ""
+
+echo "Please follow below steps(1-5) to generate specific bin(s):"
+echo "STEP 1: use boot_v1.2+ by default"
+boot=new
+
+echo "boot mode: $boot"
+echo ""
+
+echo "STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)"
+echo "enter (0/1/2, default 0):"
+read input
+
+if [ -z "$input" ]; then
+    if [ $boot != none ]; then
+    	boot=none
+	echo "ignore boot"
+    fi
+    app=0
+    echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
+elif [ $input == 1 ]; then
+    if [ $boot == none ]; then
+    	app=0
+	echo "choose no boot before"
+	echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
+    else
+	app=1
+        echo "generate bin: user1.bin"
+    fi
+elif [ $input == 2 ]; then
+    if [ $boot == none ]; then
+    	app=0
+	echo "choose no boot before"
+	echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
+    else
+    	app=2
+    	echo "generate bin: user2.bin"
+    fi
+else
+    if [ $boot != none ]; then
+    	boot=none
+	echo "ignore boot"
+    fi
+    app=0
+    echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
+fi
+
+echo ""
+
+echo "STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)"
+echo "enter (0/1/2/3, default 2):"
+read input
+
+if [ -z "$input" ]; then
+    spi_speed=40
+elif [ $input == 0 ]; then
+    spi_speed=20
+elif [ $input == 1 ]; then
+    spi_speed=26.7
+elif [ $input == 3 ]; then
+    spi_speed=80
+else
+    spi_speed=40
+fi
+
+echo "spi speed: $spi_speed MHz"
+echo ""
+
+echo "STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)"
+echo "enter (0/1/2/3, default 0):"
+read input
+
+if [ -z "$input" ]; then
+    spi_mode=QIO
+elif [ $input == 1 ]; then
+    spi_mode=QOUT
+elif [ $input == 2 ]; then
+    spi_mode=DIO
+elif [ $input == 3 ]; then
+    spi_mode=DOUT
+else
+    spi_mode=QIO
+fi
+
+echo "spi mode: $spi_mode"
+echo ""
+
+echo "STEP 5: choose spi size and map"
+echo "    0= 512KB( 256KB+ 256KB)"
+echo "    2=1024KB( 512KB+ 512KB)"
+echo "    3=2048KB( 512KB+ 512KB)"
+echo "    4=4096KB( 512KB+ 512KB)"
+echo "    5=2048KB(1024KB+1024KB)"
+echo "    6=4096KB(1024KB+1024KB)"
+echo "enter (0/2/3/4/5/6, default 0):"
+read input
+
+if [ -z "$input" ]; then
+    spi_size_map=0
+    echo "spi size: 512KB"
+    echo "spi ota map:  256KB + 256KB"
+elif [ $input == 2 ]; then
+    spi_size_map=2
+    echo "spi size: 1024KB"
+    echo "spi ota map:  512KB + 512KB"
+elif [ $input == 3 ]; then
+    spi_size_map=3
+    echo "spi size: 2048KB"
+    echo "spi ota map:  512KB + 512KB"
+elif [ $input == 4 ]; then
+    spi_size_map=4
+    echo "spi size: 4096KB"
+    echo "spi ota map:  512KB + 512KB"
+elif [ $input == 5 ]; then
+    spi_size_map=5
+    echo "spi size: 2048KB"
+    echo "spi ota map:  1024KB + 1024KB"
+elif [ $input == 6 ]; then
+    spi_size_map=6
+    echo "spi size: 4096KB"
+    echo "spi ota map:  1024KB + 1024KB"
+else
+    spi_size_map=0
+    echo "spi size: 512KB"
+    echo "spi ota map:  256KB + 256KB"
+fi
+
+echo ""
+
+echo "start..."
+echo ""
+
+make clean
+
+make BOOT=$boot APP=$app SPI_SPEED=$spi_speed SPI_MODE=$spi_mode SPI_SIZE_MAP=$spi_size_map
diff --git a/examples/ESP8266_RTOS/readme.txt b/examples/ESP8266_RTOS/readme.txt
new file mode 100644
index 000000000..3c7e7e718
--- /dev/null
+++ b/examples/ESP8266_RTOS/readme.txt
@@ -0,0 +1,56 @@
+This is a simple project template.
+
+sample_lib is an example for multi-level folder Makefile, notice the folder structure and each Makefile, you can get the clue.
+
+
+HOWTO:
+1. Copy this folder to anywhere.
+Example:
+   Copy to ~/workspace/project_template
+   You can rename this folder as you like.
+
+2. Export SDK_PATH and BIN_PATH.
+Example:
+   Your SDK path is ~/esp_iot_rtos_sdk, and want generate bin at ~/esp8266_bin.
+   Do follow steps:
+     1>. export SDK_PATH=~/esp_iot_rtos_sdk
+     2>. export BIN_PATH=~/esp8266_bin
+   SDK and project are seperate, you can update SDK without change your project.
+
+3. Enter project_template folder, run ./gen_misc.sh, and follow the tips and steps.
+
+
+Compile Options:
+(1) COMPILE
+    Possible value: xcc
+    Default value:
+    If not set, use gcc by default.
+
+(2) BOOT
+    Possible value: none/old/new
+      none: no need boot
+      old: use boot_v1.1
+      new: use boot_v1.2
+    Default value: new
+
+(3) APP
+    Possible value: 0/1/2
+      0: original mode, generate eagle.app.v6.flash.bin and eagle.app.v6.irom0text.bin
+      1: generate user1
+      2: generate user2
+    Default value: 0
+
+(3) SPI_SPEED
+    Possible value: 20/26.7/40/80
+    Default value: 40
+
+(4) SPI_MODE
+    Possible value: QIO/QOUT/DIO/DOUT
+    Default value: QIO
+
+(4) SPI_SIZE_MAP
+    Possible value: 0/2/3/4/5/6
+    Default value: 0
+
+For example:
+    make COMPILE=gcc BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=QIO SPI_SIZE_MAP=0
diff --git a/examples/ESP8266_RTOS/user/Makefile b/examples/ESP8266_RTOS/user/Makefile
new file mode 100644
index 000000000..e005b7096
--- /dev/null
+++ b/examples/ESP8266_RTOS/user/Makefile
@@ -0,0 +1,47 @@
+
+#############################################################
+# Required variables for each makefile
+# Discard this section from all parent makefiles
+# Expected variables (with automatic defaults):
+#   CSRCS (all "C" files in the dir)
+#   SUBDIRS (all subdirs with a Makefile)
+#   GEN_LIBS - list of libs to be generated ()
+#   GEN_IMAGES - list of images to be generated ()
+#   COMPONENTS_xxx - a list of libs/objs in the form
+#     subdir/lib to be extracted and rolled up into
+#     a generated lib/image xxx.a ()
+#
+ifndef PDIR
+GEN_LIBS = libuser.a
+endif
+
+
+#############################################################
+# Configuration i.e. compile options etc.
+# Target specific stuff (defines etc.) goes in here!
+# Generally values applying to a tree are captured in the
+#   makefile at its root level - these are then overridden
+#   for a subtree within the makefile rooted therein
+#
+DEFINES += -DMG_DISABLE_DAV -DMG_DISABLE_SYNC_RESOLVER -DMG_DISABLE_CGI \
+           -DMG_DISABLE_SOCKETPAIR -DMG_DISABLE_DIRECTORY_LISTING \
+           -DMG_MAX_HTTP_HEADERS=20 -DMG_MAX_HTTP_REQUEST_SIZE=1024 \
+           -DMG_MAX_PATH=40 -DMG_MAX_HTTP_SEND_IOBUF=1024 \
+           -DMG_ESP8266 -DRTOS_SDK -DMG_LWIP
+
+#############################################################
+# Recursion Magic - Don't touch this!!
+#
+# Each subtree potentially has an include directory
+#   corresponding to the common APIs applicable to modules
+#   rooted at that subtree. Accordingly, the INCLUDE PATH
+#   of a module can only contain the include directories up
+#   its parent path, and not its siblings
+#
+# Required for each makefile to inherit from the parent
+#
+
+INCLUDES += -I ./
+PDIR := ../$(PDIR)
+sinclude $(PDIR)Makefile
+
diff --git a/examples/ESP8266_RTOS/user/esp_libc.c b/examples/ESP8266_RTOS/user/esp_libc.c
new file mode 100644
index 000000000..a48893f0b
--- /dev/null
+++ b/examples/ESP8266_RTOS/user/esp_libc.c
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2015 Cesanta Software Limited
+* All rights reserved
+*/
+
+#include <ctype.h>
+#include <sys/time.h>
+#include <stdint.h>
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "esp_common.h"
+
+/* Makes fprintf(stdout) and stderr work. */
+_ssize_t _write_r(struct _reent *r, int fd, void *buf, size_t len) {
+  if (fd == 1 || fd == 2) {
+    size_t i;
+    for (i = 0; i < len; i++) {
+      os_putc(((char *) buf)[i]);
+    }
+    return len;
+  }
+  return -1;
+}
+
+/*
+ * You'll need to implement _open_r and friends if you want file operations. See
+ * https://github.com/cesanta/smart.js/blob/master/platforms/esp8266/user/esp_fs.c
+ * for SPIFFS-based implementation.
+ */
+
+void abort(void) __attribute__((no_instrument_function));
+void abort(void) {
+  /* cause an unaligned access exception, that will drop you into gdb */
+  *(int *) 1 = 1;
+  while (1)
+    ; /* avoid gcc warning because stdlib abort() has noreturn attribute */
+}
+
+void _exit(int status) {
+  printf("_exit(%d)\n", status);
+  abort();
+}
+
+int _gettimeofday_r(struct _reent *r, struct timeval *tp, void *tzp) {
+  uint32_t time = system_get_time();
+  tp->tv_sec = time / 1000000;
+  tp->tv_usec = time % 1000000;
+  return 0;
+}
diff --git a/examples/ESP8266_RTOS/user/mongoose.c b/examples/ESP8266_RTOS/user/mongoose.c
new file mode 120000
index 000000000..5e522bbcd
--- /dev/null
+++ b/examples/ESP8266_RTOS/user/mongoose.c
@@ -0,0 +1 @@
+../../../mongoose.c
\ No newline at end of file
diff --git a/examples/ESP8266_RTOS/user/mongoose.h b/examples/ESP8266_RTOS/user/mongoose.h
new file mode 120000
index 000000000..ee4ac8232
--- /dev/null
+++ b/examples/ESP8266_RTOS/user/mongoose.h
@@ -0,0 +1 @@
+../../../mongoose.h
\ No newline at end of file
diff --git a/examples/ESP8266_RTOS/user/user_main.c b/examples/ESP8266_RTOS/user/user_main.c
new file mode 100644
index 000000000..e52e4784b
--- /dev/null
+++ b/examples/ESP8266_RTOS/user/user_main.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015 Cesanta Software Limited
+ * All rights reserved
+ */
+
+#include "esp_common.h"
+
+#include "mongoose.h"
+
+#define AP_SSID "Mongoose"
+#define AP_PASS "Mongoose"
+#define AP_CHAN 9
+#define MG_LISTEN_ADDR "80"
+
+#define MG_TASK_STACK_SIZE 2048
+#define MG_TASK_PRIORITY 1
+
+void uart_div_modify(int uart_no, unsigned int freq);
+
+void ev_handler(struct mg_connection *nc, int ev, void *p) {
+  static const char *reply_fmt =
+      "HTTP/1.0 200 OK\r\n"
+      "Connection: close\r\n"
+      "Content-Type: text/plain\r\n"
+      "\r\n"
+      "Hello %s\n";
+  LOG(LL_DEBUG, ("conn %p ev %d", nc, ev));
+
+  switch (ev) {
+    case MG_EV_ACCEPT: {
+      char addr[32];
+      mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
+                          MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
+      LOG(LL_INFO, ("Connection %p from %s", nc, addr));
+      break;
+    }
+    case MG_EV_HTTP_REQUEST: {
+      char addr[32];
+      struct http_message *hm = (struct http_message *) p;
+      mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
+                          MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
+      LOG(LL_INFO,
+          ("HTTP request from %s: %.*s %.*s", addr, (int) hm->method.len,
+           hm->method.p, (int) hm->uri.len, hm->uri.p));
+      mg_printf(nc, reply_fmt, addr);
+      nc->flags |= MG_F_SEND_AND_CLOSE;
+      break;
+    }
+    case MG_EV_CLOSE: {
+      LOG(LL_INFO, ("Connection %p closed", nc));
+      break;
+    }
+  }
+}
+
+void setup_ap() {
+  struct softap_config cfg;
+
+  wifi_set_opmode_current(SOFTAP_MODE);
+  memset(&cfg, 0, sizeof(cfg));
+  strcpy((char *) cfg.ssid, AP_SSID);
+  strcpy((char *) cfg.password, AP_PASS);
+  cfg.ssid_len = strlen((const char *) cfg.ssid);
+  cfg.authmode =
+      strlen((const char *) cfg.password) ? AUTH_WPA2_PSK : AUTH_OPEN;
+  cfg.channel = AP_CHAN;
+  cfg.ssid_hidden = 0;
+  cfg.max_connection = 10;
+  cfg.beacon_interval = 100; /* ms */
+
+  LOG(LL_INFO, ("Setting up AP '%s' on channel %d", cfg.ssid, cfg.channel));
+  wifi_softap_set_config_current(&cfg);
+}
+
+static void mg_task(void *arg) {
+  struct mg_mgr mgr;
+  struct mg_connection *nc;
+
+  cs_log_set_level(LL_INFO);
+
+  LOG(LL_INFO, ("SDK version: %s", system_get_sdk_version()));
+  setup_ap();
+
+  mg_mgr_init(&mgr, NULL);
+
+  nc = mg_bind(&mgr, MG_LISTEN_ADDR, ev_handler);
+  if (nc == NULL) {
+    LOG(LL_ERROR, ("Error setting up listener!"));
+    return;
+  }
+  mg_set_protocol_http_websocket(nc);
+
+  while (1) {
+    mg_mgr_poll(&mgr, 1000);
+  }
+}
+
+xTaskHandle s_mg_task_handle;
+
+void user_init(void) {
+  uart_div_modify(0, UART_CLK_FREQ / 115200);
+
+  setvbuf(stdout, NULL, _IONBF, 0);
+  setvbuf(stderr, NULL, _IONBF, 0);
+
+  xTaskCreate(mg_task, (const signed char *) "mongoose", MG_TASK_STACK_SIZE,
+              NULL, MG_TASK_PRIORITY, &s_mg_task_handle);
+}
-- 
GitLab