added user sample program

pull/16/head
Martin Ger 2017-06-02 01:04:48 +02:00
rodzic 7b3905ae16
commit ebfb3e897a
14 zmienionych plików z 2346 dodań i 640 usunięć

279
Makefile
Wyświetl plik

@ -1,134 +1,99 @@
# none sdkota espboot rboot
OTA ?= none
OTA_APP_ADDR = 0x2000
OTA_BOOTLOADER_PATH = ../esp-bootloader/firmware/espboot.bin
THISDIR:=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
# Base directory for the compiler. Needs a / at the end; if not set it'll use the tools that are in
# the PATH.
XTENSA_TOOLS_ROOT ?=
# base directory of the ESP8266 SDK package, absolute
SDK_BASE ?= /home/martin/github/esp-open-sdk/sdk/
#Esptool.py path and port
ESPTOOL ?= /home/martin/github/esp-open-sdk/esptool/esptool.py
ESPPORT ?= /dev/ttyUSB0
#ESPPORT ?= /dev/tty.wchusbserial1410
#ESPDELAY indicates seconds to wait between flashing the two binary images
ESPDELAY ?= 3
#ESPBAUD ?= 115200
ESPBAUD ?= 460800
# 40m 26m 20m 80m
ESP_FREQ = 40m
# qio qout dio dout
ESP_MODE = dio
#4m 2m 8m 16m 32m
ESP_SIZE = 32m
VERBOSE = yes
FLAVOR = debug
# name for the target project
TARGET ?= esp_mqtt
# name for the target when compiling as library
TARGET_LIB ?= libmqtt.a
# which modules (subdirectories) of the project to include in compiling
USER_MODULES = user driver mqtt modules
USER_INC = include
USER_LIB =
# which modules (subdirectories) of the project to include when compiling as library
LIB_MODULES = mqtt
SDK_LIBDIR = lib
SDK_LIBS = c gcc phy pp net80211 wpa main lwip crypto ssl json driver
SDK_INC = include include/json
# Makefile for ESP8266 projects
#
# Thanks to:
# - zarya
# - Jeroen Domburg (Sprite_tm)
# - Christian Klippel (mamalala)
# - Tommie Gannert (tommie)
#
# Changelog:
# - 2014-10-06: Changed the variables to include the header file directory
# - 2014-10-06: Added global var for the Xtensa tool root
# - 2014-11-23: Updated for SDK 0.9.3
# - 2014-12-25: Replaced esptool by esptool.py
BUILD_AREA = /home/martin/github
# Output directors to store intermediate compiled files
# relative to the project directory
BUILD_BASE = build
FIRMWARE_BASE = firmware
BUILD_BASE = build
FW_BASE = firmware
# Opensdk patches stdint.h when compiled with an internal SDK. If you run into compile problems pertaining to
# redefinition of int types, try setting this to 'yes'.
USE_OPENSDK ?= yes
# base directory for the compiler
XTENSA_TOOLS_ROOT ?= $(BUILD_AREA)/esp-open-sdk/xtensa-lx106-elf/bin
DATETIME := $(shell date "+%Y-%b-%d_%H:%M:%S_%Z")
# # base directory of the ESP8266 SDK package, absolute
SDK_BASE ?= $(BUILD_AREA)/esp-open-sdk/sdk
# # esptool.py path and port
ESPTOOL ?= $(BUILD_AREA)/esp-open-sdk/esptool/esptool.py
ESPPORT ?= /dev/ttyUSB0
# name for the target project
TARGET = app
# which modules (subdirectories) of the project to include in compiling
MODULES = driver user mqtt
#EXTRA_INCDIR = $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include include
EXTRA_INCDIR = include
LIB_MODULES = mqtt
# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal pp phy net80211 lwip wpa main
# compiler flags using during compilation of source files
CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DUSE_OPTIMIZE_PRINTF
# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static
# linker script used for the above linkier step
LD_SCRIPT = eagle.app.v6.ld
# various paths from the SDK used in this project
SDK_LIBDIR = lib
SDK_LDDIR = ld
SDK_INCDIR = include include/json
# we create two different files for uploading into the flash
# these are the names and options to generate them
FW_FILE_1_ADDR = 0x00000
FW_FILE_2_ADDR = 0x10000
# select which tools to use as compiler, librarian and linker
CC := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-gcc
AR := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-ar
LD := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-gcc
OBJCOPY := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-objcopy
CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar
LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
####
#### no user configurable options below here
####
SRC_DIR := $(USER_MODULES)
SRC_DIR_LIB := $(LIB_MODULES)
BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(USER_MODULES))
INCDIR := $(addprefix -I,$(SRC_DIR))
EXTRA_INCDIR := $(addprefix -I,$(USER_INC))
MODULE_INCDIR := $(addsuffix /include,$(INCDIR))
SRC_DIR := $(MODULES)
BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES))
SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR))
SDK_LIBS := $(addprefix -l,$(SDK_LIBS))
SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INC))
SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
SRC_LIB := $(foreach sdir,$(SRC_DIR_LIB),$(wildcard $(sdir)/*.c))
ASMSRC = $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.S))
ASMSRC_LIB = $(foreach sdir,$(SRC_DIR_LIB),$(wildcard $(sdir)/*.S))
OBJ = $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC))
OBJ_LIB = $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC_LIB))
OBJ += $(patsubst %.S,$(BUILD_BASE)/%.o,$(ASMSRC))
OBJ_LIB += $(patsubst %.c,$(BUILD_BASE)/%.o,$(ASMSRC_LIB))
APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET).a)
OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC))
LIBS := $(addprefix -l,$(LIBS))
APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a)
TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out)
LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT))
INCDIR := $(addprefix -I,$(SRC_DIR))
EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR))
MODULE_INCDIR := $(addsuffix /include,$(INCDIR))
# compiler flags using during compilation of source files
CFLAGS = -g \
-Wpointer-arith \
-Wundef \
-Wl,-EL \
-Wno-implicit-function-declaration \
-fno-inline-functions \
-nostdlib \
-mlongcalls \
-mtext-section-literals \
-ffunction-sections \
-fdata-sections \
-fno-builtin-printf\
-DICACHE_FLASH \
-DBUID_TIME=\"$(DATETIME)\"
# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static
ifeq ($(FLAVOR),debug)
LDFLAGS += -g -O2
CFLAGS += -DMQTT_DEBUG_ON -DDEBUG_ON
endif
ifeq ($(FLAVOR),release)
LDFLAGS += -g -O0
endif
FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin)
FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin)
V ?= $(VERBOSE)
ifeq ("$(V)","yes")
ifeq ("$(V)","1")
Q :=
vecho := @true
else
@ -136,110 +101,42 @@ Q := @
vecho := @echo
endif
ifeq ("$(USE_OPENSDK)","yes")
CFLAGS += -DUSE_OPENSDK
else
CFLAGS += -D_STDINT_H
endif
ifneq ("$(wildcard $(THISDIR)/include/user_config.local.h)","")
CFLAGS += -DLOCAL_CONFIG_AVAILABLE
endif
ESPTOOL_OPTS=--port $(ESPPORT) --baud $(ESPBAUD)
#32m
ESP_INIT_DATA_DEFAULT_ADDR = 0xfc000
ifeq ("$(ESP_SIZE)","16m")
ESP_INIT_DATA_DEFAULT_ADDR = 0x1fc000
else ifeq ("$(ESP_SIZE)","32m")
ESP_INIT_DATA_DEFAULT_ADDR = 0x3fc000
endif
ifeq ("$(OTA)","espboot")
OUTPUT := $(addprefix $(FIRMWARE_BASE)/,$(TARGET)-0x2000.bin)
ESPTOOL_WRITE = write_flash --flash_freq $(ESP_FREQ) --flash_mode $(ESP_MODE) --flash_size $(ESP_SIZE) \
0x00000 $(OTA_BOOTLOADER_PATH) \
$(OTA_APP_ADDR) $(OUTPUT) \
$(ESP_INIT_DATA_DEFAULT_ADDR) $(SDK_BASE)/bin/esp_init_data_default.bin
ESPTOOL_FLASHDEF=--version=2
LD_SCRIPT = -Tld/with-espboot-flash-at-0x2000-size-1M.ld
else
OUTPUT := $(addprefix $(FIRMWARE_BASE)/,$(TARGET))
ESPTOOL_WRITE = write_flash --flash_freq $(ESP_FREQ) --flash_mode $(ESP_MODE) --flash_size $(ESP_SIZE) \
0x00000 $(OUTPUT)0x00000.bin \
0x10000 $(OUTPUT)0x10000.bin \
$(ESP_INIT_DATA_DEFAULT_ADDR) $(SDK_BASE)/bin/esp_init_data_default.bin
ESPTOOL_FLASHDEF=
LD_SCRIPT = -T$(SDK_BASE)/ld/eagle.app.v6.ld
endif
OUTPUT_LIB := $(addprefix $(FIRMWARE_BASE)/,$(TARGET_LIB))
vpath %.c $(SRC_DIR)
define compile-objects
$1/%.o: %.c
$(vecho) "CC $$<"
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
endef
.PHONY: all checkdirs flash clean
all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)
.PHONY: all lib checkdirs clean
all: touch checkdirs $(OUTPUT)
lib: checkdirs $(OUTPUT_LIB)
touch:
$(vecho) "-------------------------------------------\n"
$(vecho) "BUID TIME $(DATETIME)"
$(vecho) "-------------------------------------------\n"
$(Q) touch user/user_main.c
checkdirs: $(BUILD_DIR) $(FIRMWARE_BASE)
$(OUTPUT): $(TARGET_OUT)
$(vecho) "FW $@"
$(Q) $(ESPTOOL) elf2image $(ESPTOOL_FLASHDEF) $< -o $(OUTPUT)
$(OUTPUT_LIB): $(OBJ_LIB)
$(vecho) "AR $@"
$(Q) $(AR) cru $@ $^
$(BUILD_DIR):
$(Q) mkdir -p $@
$(FIRMWARE_BASE):
$(Q) mkdir -p $@
$(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE)
$(vecho) "FW $(FW_BASE)/"
$(Q) $(ESPTOOL) elf2image -o $(FW_BASE)/ $(TARGET_OUT)
$(TARGET_OUT): $(APP_AR)
$(vecho) "LD $@"
$(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(SDK_LIBS) $(APP_AR) -Wl,--end-group -o $@
$(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
$(APP_AR): $(OBJ)
$(vecho) "AR $@"
$(Q) $(AR) cru $@ $^
flash:
$(ESPTOOL) $(ESPTOOL_OPTS) $(ESPTOOL_WRITE)
checkdirs: $(BUILD_DIR) $(FW_BASE)
fast: all flash openport
$(BUILD_DIR):
$(Q) mkdir -p $@
openport:
$(vecho) "After flash, terminal will enter serial port screen"
$(vecho) "Please exit with command:"
$(vecho) "\033[0;31m" "Ctrl + A + k" "\033[0m"
$(FW_BASE):
$(Q) mkdir -p $@
#@read -p "Press any key to continue... " -n1 -s
@screen $(ESPPORT) 115200
flash: $(FW_FILE_1) $(FW_FILE_2)
sudo $(ESPTOOL) --port $(ESPPORT) write_flash $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2)
clean:
$(Q) rm -rf $(BUILD_DIR)
$(Q) rm -rf $(FIRMWARE_BASE)
$(Q) rm -rf $(FW_BASE) $(BUILD_BASE)
$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))

471
driver/new_uart.c 100644
Wyświetl plik

@ -0,0 +1,471 @@
/*
* File : uart.c
* Copyright (C) 2013 - 2016, Espressif Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ets_sys.h"
#include "osapi.h"
#include "driver/uart.h"
#include "osapi.h"
#include "driver/uart_register.h"
#include "mem.h"
#include "os_type.h"
#ifdef _ENABLE_RING_BUFFER
static ringbuf_t rxBuff;
static ringbuf_t txBuff;
#endif
#ifdef _ENABLE_CONSOLE_INTEGRATION
uint8_t linked_to_console = 0;
#endif
extern UartDevice UartDev;
/* Local variables */
static uint8 uart_recvTaskPrio = 0;
/* Internal Functions */
static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no);
static void uart0_rx_intr_handler(void *para);
/* Public APIs */
void ICACHE_FLASH_ATTR UART_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 recv_task_priority);
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DBG
#define DBG1 os_printf
#define DBG2 os_printf
#else
#define DBG
#define DBG1
#define DBG2
#endif
#if _ENABLE_CONSOLE_INTEGRATION == 1
void ICACHE_FLASH_ATTR UART_init_console(UartBautRate uart0_br,
uint8 recv_task_priority,
ringbuf_t rxbuffer,
ringbuf_t txBuffer)
{
/* Set the task which should receive the signals once the data is received */
uart_recvTaskPrio = recv_task_priority;
UartDev.baut_rate = uart0_br;
rxBuff = rxbuffer;
txBuff = txBuffer;
linked_to_console = 1;
uart_config(UART0);
UART_SetPrintPort(UART0);
UartDev.baut_rate = uart0_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
}
#endif
void ICACHE_FLASH_ATTR UART_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 recv_task_priority)
{
/* Set the task which should receive the signals once the data is received */
uart_recvTaskPrio = recv_task_priority;
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UART_SetPrintPort(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
#if _ENABLE_CONSOLE_INTEGRATION == 0
#if _ENABLE_RING_BUFFER == 1
rxBuff = ringbuf_new(RX_RING_BUFFER_SIZE);
#endif
#endif
}
/******************************************************************************
* FunctionName : uart_config
* Description : Internal used function
* UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled
* UART1 just used for debug output
* Parameters : uart_no, use UART0 or UART1 defined ahead
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR uart_config(uint8 uart_no)
{
if (uart_no == UART1)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
}
else
{
/* rcv_buff size if 0x100 */
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
#if UART_HW_RTS
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //HW FLOW CONTROL RTS PIN
#endif
#if UART_HW_CTS
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //HW FLOW CONTROL CTS PIN
#endif
}
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));//SET BAUDRATE
WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) //SET BIT AND PARITY MODE
| ((UartDev.parity & UART_PARITY_M) <<UART_PARITY_S )
| ((UartDev.stop_bits & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S)
| ((UartDev.data_bits & UART_BIT_NUM) << UART_BIT_NUM_S));
//clear rx and tx fifo,not ready
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); //RESET FIFO
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
if (uart_no == UART0)
{
int rx_threshold = 10;
#if _ENABLE_CONSOLE_INTEGRATION == 1
rx_threshold = 1;
#endif
//set rx fifo trigger
WRITE_PERI_REG(UART_CONF1(uart_no),
((rx_threshold & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
#if UART_HW_RTS
((110 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |
UART_RX_FLOW_EN | //enbale rx flow control
#endif
// (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |
// UART_RX_TOUT_EN|
((0x10 & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S));//wjl
#if UART_HW_CTS
SET_PERI_REG_MASK( UART_CONF0(uart_no),UART_TX_FLOW_EN); //add this sentense to add a tx flow control via MTCK( CTS )
#endif
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA |UART_FRM_ERR_INT_ENA);
}
else
{
WRITE_PERI_REG(UART_CONF1(uart_no),((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));//TrigLvl default val == 1
}
//clear all interrupt
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
//enable rx_interrupt
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_OVF_INT_ENA);
}
/******************************************************************************
* FunctionName : UART_Recv
* Description : Public API, unloads the contents of the Rx FIFO for specified
* uart into the buffer specified. Will unload upto buffer size
* only
* Parameters : IN uart number (uart_no)
* IN/OUT char *buffer
* IN int max_buf_len
* Returns : int (number of bytes unloaded ) 0 if FIFO is empty
*******************************************************************************/
int UART_Recv(uint8 uart_no, char *buffer, int max_buf_len)
{
uint8 max_unload, index = -1;
#if _ENABLE_RING_BUFFER == 1
/* If the ring buffer is enabled, then unload from Rx Ring Buffer */
uint8 bytes_ringbuffer = ringbuf_bytes_used(rxBuff);
//ring_buffer_dump(rxBuff);
if (bytes_ringbuffer)
{
max_unload = (bytes_ringbuffer<max_buf_len ? bytes_ringbuffer: max_buf_len);
ringbuf_memcpy_from(buffer, rxBuff, max_unload);
}
#else
/* If the ring buffer is not enabled, then unload from Rx FIFO */
uint8 fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
if (fifo_len)
{
max_unload = (fifo_len<max_buf_len ? fifo_len : max_buf_len);
DBG1("Rx Fifo contains %d characters have to unload %d\r\n", fifo_len , max_unload);
for (index=0;index<max_unload; index++)
{
*(buffer+index) = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
}
//return index;
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
uart_rx_intr_enable(uart_no);
}
#endif
return index;
}
int UART_Send(uint8 uart_no, char *buffer, int len)
{
int index = 0;
char ch ;
//DBG1("Sending: %s\n", buffer);
for (index=0; index <len; index ++)
{
ch = *(buffer+index);
uart_tx_one_char(uart_no, ch);
}
}
/*---------------------------------------------------------------------------*
* Internal Functions
*---------------------------------------------------------------------------*/
/******************************************************************************
* FunctionName : uart_rx_intr_disable
* Description : Internal used function disables the uart interrupts
* Parameters : IN uart number (uart_no)
* Returns : NONE
*******************************************************************************/
void uart_rx_intr_disable(uint8 uart_no)
{
//DBG1("RxIntr Disabled\r\n");
#if 1
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
#else
ETS_UART_INTR_DISABLE();
#endif
}
/******************************************************************************
* FunctionName : uart_rx_intr_enable
* Description : Internal used function enables the uart interrupts
* Parameters : IN uart number (uart_no)
* Returns : NONE
*******************************************************************************/
void uart_rx_intr_enable(uint8 uart_no)
{
//DBG1("RxIntr Enabled\r\n");
#if 1
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
#else
ETS_UART_INTR_ENABLE();
#endif
}
/******************************************************************************
* FunctionName : uart0_rx_intr_handler
* Description : Internal used function
* UART0 interrupt handler, add self handle code inside
* Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
* Returns : NONE
*******************************************************************************/
static void uart0_rx_intr_handler(void *para)
{
uint8 uart_no = UART0;//UartDev.buff_uart_no;
/* Is the frame Error interrupt set ? */
if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))
{
/* The Frame Error (UART_FRM_ERR_INT_ST) has bee set */
DBG1("Frame Error\r\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
goto end_int_handler;
}
if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
{
/* Rx FIFO is full, hence the interrupt */
#if _ENABLE_RING_BUFFER == 1
uint16_t index;
uint16_t fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
//DBG1("RX FIFO FULL [%d]\r\n", fifo_len );
if (fifo_len)
{
//DBG1("Rx Fifo contains %d characters have to unload\r\n", fifo_len);
for (index=0;index<fifo_len; index++)
{
uint8_t ch = (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
//if (ch == '\r') ch = '\n';
ringbuf_memcpy_into(rxBuff, &ch, 1);
#if _ENABLE_CONSOLE_INTEGRATION == 1
uart_tx_one_char(uart_no, ch);
if (ch == '\r')
{
system_os_post(0, SIG_CONSOLE_RX, 0);
}
#endif
}
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
uart_rx_intr_enable(uart_no);
#if _ENABLE_CONSOLE_INTEGRATION == 0
system_os_post(uart_recvTaskPrio, SIG_UART0, 0);
#endif
}
#else
DBG1("RX FIFO FULL [%d]\r\n", (READ_PERI_REG(UART_STATUS(uart_no))>>UART_RXFIFO_CNT_S)& UART_RXFIFO_CNT);
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
system_os_post(uart_recvTaskPrio, SIG_UART0, 0);
#endif
goto end_int_handler;
}
if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
{
/* The Time out threshold for Rx/Tx is being execeeded */
DBG1("Rx Timeout Threshold not being met \r\n");
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
system_os_post(uart_recvTaskPrio, SIG_UART0, 0);
goto end_int_handler;
}
if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST))
{
/* The Tx FIFO is empty, the FIFO needs to be fed with new data */
DBG1("Tx FIFO is empty\r\n");
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
#if UART_BUFF_EN
tx_start_uart_buffer(UART0);
#endif
//system_os_post(uart_recvTaskPrio, 1, 0);
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
}
end_int_handler:
return;
}
/******************************************************************************
* FunctionName : uart_tx_one_char_no_wait
* Description : uart tx a single char without waiting for fifo
* Parameters : uint8 uart - uart port
* uint8 TxChar - char to tx
* Returns : STATUS
*******************************************************************************/
STATUS uart_tx_one_char(uint8 uart, uint8 TxChar)
{
while (true)
{
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
break;
}
}
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
return OK;
}
/******************************************************************************
* FunctionName : uart_tx_one_char_no_wait
* Description : uart tx a single char without waiting for fifo
* Parameters : uint8 uart - uart port
* uint8 TxChar - char to tx
* Returns : STATUS
*******************************************************************************/
STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar)
{
uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(uart))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT);
if (fifo_cnt < 126)
{
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
}
return OK;
}
/******************************************************************************
* FunctionName : uart0_write_char_no_wait
* Description : tx a single char without waiting for uart 0.
helper function for os_printf output to fifo or tx buffer
* Parameters : uint8 uart - uart port
* uint8 TxChar - char to tx
* Returns : STATUS
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR uart0_write_char_no_wait(char c)
{
#if UART_BUFF_EN //send to uart0 fifo but do not wait
uint8 chr;
if (c == '\n'){
chr = '\r';
tx_buff_enq(&chr, 1);
chr = '\n';
tx_buff_enq(&chr, 1);
}else if (c == '\r'){
}else{
tx_buff_enq(&c,1);
}
#else //send to uart tx buffer
if (c == '\n')
{
uart_tx_one_char(UART0, '\r');
uart_tx_one_char(UART0, '\n');
//uart_tx_one_char_no_wait(UART0, '\r');
//uart_tx_one_char_no_wait(UART0, '\n');
}
else
if (c == '\r')
{
uart_tx_one_char(UART0, c);
}
else
{
uart_tx_one_char(UART0, c);
//uart_tx_one_char_no_wait(UART0, c);
}
#endif
}
/******************************************************************************
* FunctionName : UART_SetPrintPort
* Description :
*
* Parameters :
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR UART_SetPrintPort(uint8 uart_no)
{
if(uart_no==1)
{
//os_install_putc1(uart1_write_char);
}
else
{
/*option 1: do not wait if uart fifo is full,drop current character*/
//os_install_putc1(uart0_write_char_no_wait);
/*option 2: wait for a while if uart fifo is full*/
//os_install_putc1(uart0_write_char);
}
}

Wyświetl plik

@ -1,211 +0,0 @@
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: uart.c
*
* Description: Two UART mode configration and interrupt handler.
* Check your hardware connection while use this mode.
*
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "osapi.h"
#include "driver/uart.h"
#include "osapi.h"
#include "driver/uart_register.h"
#include "mem.h"
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
LOCAL void uart0_rx_intr_handler(void *para);
LOCAL void ICACHE_FLASH_ATTR
uart_config(uint8 uart_no)
{
if (uart_no == UART1)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
}
else
{
/* rcv_buff size if 0x100 */
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
}
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));
WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity
| UartDev.parity
| (UartDev.stop_bits << UART_STOP_BIT_NUM_S)
| (UartDev.data_bits << UART_BIT_NUM_S));
//clear rx and tx fifo,not ready
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
if (uart_no == UART0)
{
//set rx fifo trigger
WRITE_PERI_REG(UART_CONF1(uart_no),
((0x7F & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
//((128 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |
//UART_RX_FLOW_EN |
((0x0F & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S));
//UART_RX_TOUT_EN);
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);
}
else
{
WRITE_PERI_REG(UART_CONF1(uart_no),
((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));
}
//clear all interrupt
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
//enable rx_interrupt
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_OVF_INT_ENA);
}
LOCAL STATUS
uart_tx_one_char(uint8 uart, uint8 TxChar)
{
while (true)
{
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
break;
}
}
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
return OK;
}
void ICACHE_FLASH_ATTR
uart1_write_char(char c)
{
if (c == '\n')
{
uart_tx_one_char(UART1, '\r');
uart_tx_one_char(UART1, '\n');
}
else if (c == '\r')
{
}
else
{
uart_tx_one_char(UART1, c);
}
}
void ICACHE_FLASH_ATTR
uart0_write_char(char c)
{
if (c == '\n')
{
uart_tx_one_char(UART0, '\r');
uart_tx_one_char(UART0, '\n');
}
else if (c == '\r')
{
}
else
{
uart_tx_one_char(UART0, c);
}
}
void ICACHE_FLASH_ATTR
uart0_tx_buffer(uint8 *buf, uint16 len)
{
uint16 i;
for (i = 0; i < len; i++)
{
uart_tx_one_char(UART0, buf[i]);
}
}
void ICACHE_FLASH_ATTR
uart0_sendStr(const char *str)
{
while (*str)
{
uart_tx_one_char(UART0, *str++);
}
}
LOCAL void
uart0_rx_intr_handler(void *para)
{
uint8 RcvChar;
uint8 uart_no = UART0;//UartDev.buff_uart_no;
/* Is the frame Error interrupt set ? */
if (UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))
{
//INFO("FRM_ERR\r\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
}
else if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) /*fifo full*/
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
//INFO("Fifo full: %d\n", (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT);
while ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)
{
//TODO: MCU_Input( READ_PERI_REG(UART_FIFO(UART0)) & 0xFF );
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
}
else if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
//INFO("Fifo timeout: %d\n", (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT);
while ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)
{
//MCU_Input( READ_PERI_REG(UART_FIFO(UART0)) & 0xFF );
}
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
}
else if (UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST))
{
//INFO("FIFO FULL\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR);
}
else if (UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)) {
//INFO("TX EMPTY\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
}
ETS_UART_INTR_ENABLE();
}
void ICACHE_FLASH_ATTR
uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
{
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
// install uart1 putc callback
os_install_putc1((void *)uart0_write_char);
}
void ICACHE_FLASH_ATTR
uart_reattach()
{
uart_init(BIT_RATE_115200, BIT_RATE_115200);
}

Wyświetl plik

@ -1,3 +1,19 @@
/*
* File : uart.h
* Copyright (C) 2013 - 2016, Espressif Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UART_APP_H
#define UART_APP_H
@ -5,11 +21,29 @@
#include "eagle_soc.h"
#include "c_types.h"
#define RX_BUFF_SIZE 256
#define TX_BUFF_SIZE 100
#define UART_TX_BUFFER_SIZE 256 //Ring buffer length of tx buffer
#define UART_RX_BUFFER_SIZE 256 //Ring buffer length of rx buffer
#define UART_BUFF_EN 0 //use uart buffer , FOR UART0
#define UART_SELFTEST 0 //set 1:enable the loop test demo for uart buffer, FOR UART0
#define UART_HW_RTS 0 //set 1: enable uart hw flow control RTS, PIN MTDO, FOR UART0
#define UART_HW_CTS 0 //set1: enable uart hw flow contrl CTS , PIN MTCK, FOR UART0
#define _ENABLE_CONSOLE_INTEGRATION 1
#define _ENABLE_RING_BUFFER 1
#ifdef _ENABLE_RING_BUFFER
#include "ringbuf.h"
#define RX_RING_BUFFER_SIZE 250
#endif
#define UART0 0
#define UART1 1
typedef enum {
FIVE_BITS = 0x0,
SIX_BITS = 0x1,
@ -18,33 +52,48 @@ typedef enum {
} UartBitsNum4Char;
typedef enum {
ONE_STOP_BIT = 0,
ONE_HALF_STOP_BIT = BIT2,
TWO_STOP_BIT = BIT2
ONE_STOP_BIT = 0x1,
ONE_HALF_STOP_BIT = 0x2,
TWO_STOP_BIT = 0x3
} UartStopBitsNum;
typedef enum {
NONE_BITS = 0,
ODD_BITS = 0,
EVEN_BITS = BIT4
NONE_BITS = 0x2,
ODD_BITS = 1,
EVEN_BITS = 0
} UartParityMode;
typedef enum {
STICK_PARITY_DIS = 0,
STICK_PARITY_EN = BIT3 | BIT5
STICK_PARITY_EN = 1
} UartExistParity;
typedef enum {
BIT_RATE_9600 = 9600,
BIT_RATE_19200 = 19200,
BIT_RATE_38400 = 38400,
BIT_RATE_57600 = 57600,
BIT_RATE_74880 = 74880,
UART_None_Inverse = 0x0,
UART_Rxd_Inverse = UART_RXD_INV,
UART_CTS_Inverse = UART_CTS_INV,
UART_Txd_Inverse = UART_TXD_INV,
UART_RTS_Inverse = UART_RTS_INV,
} UART_LineLevelInverse;
typedef enum {
BIT_RATE_300 = 300,
BIT_RATE_600 = 600,
BIT_RATE_1200 = 1200,
BIT_RATE_2400 = 2400,
BIT_RATE_4800 = 4800,
BIT_RATE_9600 = 9600,
BIT_RATE_19200 = 19200,
BIT_RATE_38400 = 38400,
BIT_RATE_57600 = 57600,
BIT_RATE_74880 = 74880,
BIT_RATE_115200 = 115200,
BIT_RATE_230400 = 230400,
BIT_RATE_256000 = 256000,
BIT_RATE_460800 = 460800,
BIT_RATE_921600 = 921600
BIT_RATE_921600 = 921600,
BIT_RATE_1843200 = 1843200,
BIT_RATE_3686400 = 3686400,
} UartBautRate;
typedef enum {
@ -53,6 +102,13 @@ typedef enum {
XON_XOFF_CTRL
} UartFlowCtrl;
typedef enum {
USART_HardwareFlowControl_None = 0x0,
USART_HardwareFlowControl_RTS = 0x1,
USART_HardwareFlowControl_CTS = 0x2,
USART_HardwareFlowControl_CTS_RTS = 0x3
} UART_HwFlowCtrl;
typedef enum {
EMPTY,
UNDER_WRITE,
@ -82,10 +138,10 @@ typedef enum {
} RcvMsgState;
typedef struct {
UartBautRate baut_rate;
UartBautRate baut_rate;
UartBitsNum4Char data_bits;
UartExistParity exist_parity;
UartParityMode parity; // chip size in byte
UartParityMode parity;
UartStopBitsNum stop_bits;
UartFlowCtrl flow_ctrl;
RcvMsgBuff rcv_buff;
@ -97,5 +153,81 @@ typedef struct {
void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
void uart0_sendStr(const char *str);
///////////////////////////////////////
#define UART_FIFO_LEN 128 //define the tx fifo length
#define UART_TX_EMPTY_THRESH_VAL 0x10
struct UartBuffer{
uint32 UartBuffSize;
uint8 *pUartBuff;
uint8 *pInPos;
uint8 *pOutPos;
STATUS BuffState;
uint16 Space; //remanent space of the buffer
uint8 TcpControl;
struct UartBuffer * nextBuff;
};
struct UartRxBuff{
uint32 UartRxBuffSize;
uint8 *pUartRxBuff;
uint8 *pWritePos;
uint8 *pReadPos;
STATUS RxBuffState;
uint32 Space; //remanent space of the buffer
} ;
typedef enum {
RUN = 0,
BLOCK = 1,
} TCPState;
//void ICACHE_FLASH_ATTR uart_test_rx();
STATUS uart_tx_one_char(uint8 uart, uint8 TxChar);
STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar);
void uart1_sendStr_no_wait(const char *str);
struct UartBuffer* Uart_Buf_Init();
#if UART_BUFF_EN
LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len);
void uart_buf_free(struct UartBuffer* pBuff);
void tx_buff_enq(char* pdata, uint16 data_len );
LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no);
void tx_start_uart_buffer(uint8 uart_no);
uint16 rx_buff_deq(char* pdata, uint16 data_len );
void Uart_rx_buff_enq();
#endif
void uart_rx_intr_enable(uint8 uart_no);
void uart_rx_intr_disable(uint8 uart_no);
void uart0_tx_buffer(uint8 *buf, uint16 len);
//==============================================
#define FUNC_UART0_CTS 4
#define FUNC_U0CTS 4
#define FUNC_U1TXD_BK 2
#define UART_LINE_INV_MASK (0x3f<<19)
void UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len);
void UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num);
void UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask);
void UART_SetParity(uint8 uart_no, UartParityMode Parity_mode);
void UART_SetBaudrate(uint8 uart_no,uint32 baud_rate);
void UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh);
void UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us); //do not use if tx flow control enabled
void UART_ResetFifo(uint8 uart_no);
void UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask);
void UART_SetIntrEna(uint8 uart_no,uint32 ena_mask);
void UART_SetPrintPort(uint8 uart_no);
bool UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us);
//==============================================
void UART_init_console(UartBautRate uart0_br,
uint8 recv_task_priority,
ringbuf_t rxbuffer,
ringbuf_t txBuffer);
#endif

Wyświetl plik

@ -1,128 +1,156 @@
//Generated at 2012-07-03 18:44:06
/*
* File : uart_register.h
* Copyright (C) 2013 - 2016, Espressif Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (c) 2010 - 2011 Espressif System
*
*/
#ifndef UART_REGISTER_H_INCLUDED
#define UART_REGISTER_H_INCLUDED
#define REG_UART_BASE( i ) (0x60000000+(i)*0xf00)
#ifndef UART_REGISTER_H_
#define UART_REGISTER_H_
#define REG_UART_BASE(i) (0x60000000 + (i)*0xf00)
//version value:32'h062000
#define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0)
#define UART_RXFIFO_RD_BYTE 0x000000FF
#define UART_RXFIFO_RD_BYTE_S 0
#define UART_FIFO(i) (REG_UART_BASE(i) + 0x0)
#define UART_RXFIFO_RD_BYTE 0x000000FF
#define UART_RXFIFO_RD_BYTE_S 0
#define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4)
#define UART_RXFIFO_TOUT_INT_RAW (BIT(8))
#define UART_BRK_DET_INT_RAW (BIT(7))
#define UART_CTS_CHG_INT_RAW (BIT(6))
#define UART_DSR_CHG_INT_RAW (BIT(5))
#define UART_RXFIFO_OVF_INT_RAW (BIT(4))
#define UART_FRM_ERR_INT_RAW (BIT(3))
#define UART_PARITY_ERR_INT_RAW (BIT(2))
#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1))
#define UART_RXFIFO_FULL_INT_RAW (BIT(0))
#define UART_INT_RAW(i) (REG_UART_BASE(i) + 0x4)
#define UART_RXFIFO_TOUT_INT_RAW (BIT(8))
#define UART_BRK_DET_INT_RAW (BIT(7))
#define UART_CTS_CHG_INT_RAW (BIT(6))
#define UART_DSR_CHG_INT_RAW (BIT(5))
#define UART_RXFIFO_OVF_INT_RAW (BIT(4))
#define UART_FRM_ERR_INT_RAW (BIT(3))
#define UART_PARITY_ERR_INT_RAW (BIT(2))
#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1))
#define UART_RXFIFO_FULL_INT_RAW (BIT(0))
#define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8)
#define UART_RXFIFO_TOUT_INT_ST (BIT(8))
#define UART_BRK_DET_INT_ST (BIT(7))
#define UART_CTS_CHG_INT_ST (BIT(6))
#define UART_DSR_CHG_INT_ST (BIT(5))
#define UART_RXFIFO_OVF_INT_ST (BIT(4))
#define UART_FRM_ERR_INT_ST (BIT(3))
#define UART_PARITY_ERR_INT_ST (BIT(2))
#define UART_TXFIFO_EMPTY_INT_ST (BIT(1))
#define UART_RXFIFO_FULL_INT_ST (BIT(0))
#define UART_INT_ST(i) (REG_UART_BASE(i) + 0x8)
#define UART_RXFIFO_TOUT_INT_ST (BIT(8))
#define UART_BRK_DET_INT_ST (BIT(7))
#define UART_CTS_CHG_INT_ST (BIT(6))
#define UART_DSR_CHG_INT_ST (BIT(5))
#define UART_RXFIFO_OVF_INT_ST (BIT(4))
#define UART_FRM_ERR_INT_ST (BIT(3))
#define UART_PARITY_ERR_INT_ST (BIT(2))
#define UART_TXFIFO_EMPTY_INT_ST (BIT(1))
#define UART_RXFIFO_FULL_INT_ST (BIT(0))
#define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC)
#define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
#define UART_BRK_DET_INT_ENA (BIT(7))
#define UART_CTS_CHG_INT_ENA (BIT(6))
#define UART_DSR_CHG_INT_ENA (BIT(5))
#define UART_RXFIFO_OVF_INT_ENA (BIT(4))
#define UART_FRM_ERR_INT_ENA (BIT(3))
#define UART_PARITY_ERR_INT_ENA (BIT(2))
#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1))
#define UART_RXFIFO_FULL_INT_ENA (BIT(0))
#define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC)
#define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
#define UART_BRK_DET_INT_ENA (BIT(7))
#define UART_CTS_CHG_INT_ENA (BIT(6))
#define UART_DSR_CHG_INT_ENA (BIT(5))
#define UART_RXFIFO_OVF_INT_ENA (BIT(4))
#define UART_FRM_ERR_INT_ENA (BIT(3))
#define UART_PARITY_ERR_INT_ENA (BIT(2))
#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1))
#define UART_RXFIFO_FULL_INT_ENA (BIT(0))
#define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10)
#define UART_RXFIFO_TOUT_INT_CLR (BIT(8))
#define UART_BRK_DET_INT_CLR (BIT(7))
#define UART_CTS_CHG_INT_CLR (BIT(6))
#define UART_DSR_CHG_INT_CLR (BIT(5))
#define UART_RXFIFO_OVF_INT_CLR (BIT(4))
#define UART_FRM_ERR_INT_CLR (BIT(3))
#define UART_PARITY_ERR_INT_CLR (BIT(2))
#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1))
#define UART_RXFIFO_FULL_INT_CLR (BIT(0))
#define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10)
#define UART_RXFIFO_TOUT_INT_CLR (BIT(8))
#define UART_BRK_DET_INT_CLR (BIT(7))
#define UART_CTS_CHG_INT_CLR (BIT(6))
#define UART_DSR_CHG_INT_CLR (BIT(5))
#define UART_RXFIFO_OVF_INT_CLR (BIT(4))
#define UART_FRM_ERR_INT_CLR (BIT(3))
#define UART_PARITY_ERR_INT_CLR (BIT(2))
#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1))
#define UART_RXFIFO_FULL_INT_CLR (BIT(0))
#define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14)
#define UART_CLKDIV_CNT 0x000FFFFF
#define UART_CLKDIV_S 0
#define UART_CLKDIV(i) (REG_UART_BASE(i) + 0x14)
#define UART_CLKDIV_CNT 0x000FFFFF
#define UART_CLKDIV_S 0
#define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18)
#define UART_GLITCH_FILT 0x000000FF
#define UART_GLITCH_FILT_S 8
#define UART_AUTOBAUD_EN (BIT(0))
#define UART_AUTOBAUD(i) (REG_UART_BASE(i) + 0x18)
#define UART_GLITCH_FILT 0x000000FF
#define UART_GLITCH_FILT_S 8
#define UART_AUTOBAUD_EN (BIT(0))
#define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C)
#define UART_TXD (BIT(31))
#define UART_RTSN (BIT(30))
#define UART_DTRN (BIT(29))
#define UART_TXFIFO_CNT 0x000000FF
#define UART_TXFIFO_CNT_S 16
#define UART_RXD (BIT(15))
#define UART_CTSN (BIT(14))
#define UART_DSRN (BIT(13))
#define UART_RXFIFO_CNT 0x000000FF
#define UART_RXFIFO_CNT_S 0
#define UART_STATUS(i) (REG_UART_BASE(i) + 0x1C)
#define UART_TXD (BIT(31))
#define UART_RTSN (BIT(30))
#define UART_DTRN (BIT(29))
#define UART_TXFIFO_CNT 0x000000FF
#define UART_TXFIFO_CNT_S 16
#define UART_RXD (BIT(15))
#define UART_CTSN (BIT(14))
#define UART_DSRN (BIT(13))
#define UART_RXFIFO_CNT 0x000000FF
#define UART_RXFIFO_CNT_S 0
#define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20)
#define UART_TXFIFO_RST (BIT(18))
#define UART_RXFIFO_RST (BIT(17))
#define UART_IRDA_EN (BIT(16))
#define UART_TX_FLOW_EN (BIT(15))
#define UART_LOOPBACK (BIT(14))
#define UART_IRDA_RX_INV (BIT(13))
#define UART_IRDA_TX_INV (BIT(12))
#define UART_IRDA_WCTL (BIT(11))
#define UART_IRDA_TX_EN (BIT(10))
#define UART_IRDA_DPLX (BIT(9))
#define UART_TXD_BRK (BIT(8))
#define UART_SW_DTR (BIT(7))
#define UART_SW_RTS (BIT(6))
#define UART_STOP_BIT_NUM 0x00000003
#define UART_STOP_BIT_NUM_S 4
#define UART_BIT_NUM 0x00000003
#define UART_BIT_NUM_S 2
#define UART_PARITY_EN (BIT(1))
#define UART_PARITY (BIT(0))
#define UART_CONF0(i) (REG_UART_BASE(i) + 0x20)
#define UART_DTR_INV (BIT(24))
#define UART_RTS_INV (BIT(23))
#define UART_TXD_INV (BIT(22))
#define UART_DSR_INV (BIT(21))
#define UART_CTS_INV (BIT(20))
#define UART_RXD_INV (BIT(19))
#define UART_TXFIFO_RST (BIT(18))
#define UART_RXFIFO_RST (BIT(17))
#define UART_IRDA_EN (BIT(16))
#define UART_TX_FLOW_EN (BIT(15))
#define UART_LOOPBACK (BIT(14))
#define UART_IRDA_RX_INV (BIT(13))
#define UART_IRDA_TX_INV (BIT(12))
#define UART_IRDA_WCTL (BIT(11))
#define UART_IRDA_TX_EN (BIT(10))
#define UART_IRDA_DPLX (BIT(9))
#define UART_TXD_BRK (BIT(8))
#define UART_SW_DTR (BIT(7))
#define UART_SW_RTS (BIT(6))
#define UART_STOP_BIT_NUM 0x00000003
#define UART_STOP_BIT_NUM_S 4
#define UART_BIT_NUM 0x00000003
#define UART_BIT_NUM_S 2
#define UART_PARITY_EN (BIT(1))
#define UART_PARITY_EN_M 0x00000001
#define UART_PARITY_EN_S 1
#define UART_PARITY (BIT(0))
#define UART_PARITY_M 0x00000001
#define UART_PARITY_S 0
#define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24)
#define UART_RX_TOUT_EN (BIT(31))
#define UART_RX_TOUT_THRHD 0x0000007F
#define UART_RX_TOUT_THRHD_S 24
#define UART_RX_FLOW_EN (BIT(23))
#define UART_RX_FLOW_THRHD 0x0000007F
#define UART_RX_FLOW_THRHD_S 16
#define UART_TXFIFO_EMPTY_THRHD 0x0000007F
#define UART_TXFIFO_EMPTY_THRHD_S 8
#define UART_RXFIFO_FULL_THRHD 0x0000007F
#define UART_RXFIFO_FULL_THRHD_S 0
#define UART_CONF1(i) (REG_UART_BASE(i) + 0x24)
#define UART_RX_TOUT_EN (BIT(31))
#define UART_RX_TOUT_THRHD 0x0000007F
#define UART_RX_TOUT_THRHD_S 24
#define UART_RX_FLOW_EN (BIT(23))
#define UART_RX_FLOW_THRHD 0x0000007F
#define UART_RX_FLOW_THRHD_S 16
#define UART_TXFIFO_EMPTY_THRHD 0x0000007F
#define UART_TXFIFO_EMPTY_THRHD_S 8
#define UART_RXFIFO_FULL_THRHD 0x0000007F
#define UART_RXFIFO_FULL_THRHD_S 0
#define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28)
#define UART_LOWPULSE_MIN_CNT 0x000FFFFF
#define UART_LOWPULSE_MIN_CNT_S 0
#define UART_LOWPULSE(i) (REG_UART_BASE(i) + 0x28)
#define UART_LOWPULSE_MIN_CNT 0x000FFFFF
#define UART_LOWPULSE_MIN_CNT_S 0
#define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C)
#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF
#define UART_HIGHPULSE_MIN_CNT_S 0
#define UART_HIGHPULSE(i) (REG_UART_BASE(i) + 0x2C)
#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF
#define UART_HIGHPULSE_MIN_CNT_S 0
#define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30)
#define UART_PULSE_NUM(i) (REG_UART_BASE(i) + 0x30)
#define UART_PULSE_NUM_CNT 0x0003FF
#define UART_PULSE_NUM_CNT_S 0
#define UART_PULSE_NUM_CNT_S 0
#define UART_DATE(i) (REG_UART_BASE(i) + 0x78)
#define UART_ID(i) (REG_UART_BASE(i) + 0x7C)
#define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78)
#define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C)
#endif // UART_REGISTER_H_INCLUDED

Wyświetl plik

@ -47,7 +47,6 @@ extern "C" {
/*| --- Message Type---- | DUP Flag | QoS Level | Retain |
/* Remaining Length */
enum mqtt_message_type
{
MQTT_MSG_TYPE_CONNECT = 1,

Wyświetl plik

@ -0,0 +1,94 @@
#include "lwip/ip.h"
#include "config_flash.h"
/* From the document 99A-SDK-Espressif IOT Flash RW Operation_v0.2 *
* -------------------------------------------------------------------------*
* Flash is erased sector by sector, which means it has to erase 4Kbytes one
* time at least. When you want to change some data in flash, you have to
* erase the whole sector, and then write it back with the new data.
*--------------------------------------------------------------------------*/
void config_load_default(sysconfig_p config)
{
uint8_t mac[6];
os_memset(config, 0, sizeof(sysconfig_t));
os_printf("Loading default configuration\r\n");
config->magic_number = MAGIC_NUMBER;
config->length = sizeof(sysconfig_t);
os_sprintf(config->ssid,"%s", WIFI_SSID);
os_sprintf(config->password,"%s", WIFI_PASSWORD);
config->auto_connect = 1;
os_sprintf(config->ap_ssid,"%s", WIFI_AP_SSID);
os_sprintf(config->ap_password,"%s",WIFI_AP_PASSWORD);
config->ap_open = 1;
config->ap_on = 1;
config->locked = 0;
IP4_ADDR(&config->network_addr, 192, 168, 4, 1);
config->dns_addr.addr = 0; // use DHCP
config->my_addr.addr = 0; // use DHCP
config->my_netmask.addr = 0; // use DHCP
config->my_gw.addr = 0; // use DHCP
config->clock_speed = 80;
config->config_port = CONSOLE_SERVER_PORT;
}
int config_load(sysconfig_p config)
{
if (config == NULL) return -1;
uint16_t base_address = FLASH_BLOCK_NO;
spi_flash_read(base_address* SPI_FLASH_SEC_SIZE, &config->magic_number, 4);
if((config->magic_number != MAGIC_NUMBER))
{
os_printf("\r\nNo config found, saving default in flash\r\n");
config_load_default(config);
config_save(config);
return -1;
}
os_printf("\r\nConfig found and loaded\r\n");
spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, (uint32 *) config, sizeof(sysconfig_t));
if (config->length != sizeof(sysconfig_t))
{
os_printf("Length Mismatch, probably old version of config, loading defaults\r\n");
config_load_default(config);
config_save(config);
return -1;
}
return 0;
}
void config_save(sysconfig_p config)
{
uint16_t base_address = FLASH_BLOCK_NO;
os_printf("Saving configuration\r\n");
spi_flash_erase_sector(base_address);
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32 *)config, sizeof(sysconfig_t));
}
void blob_save(uint8_t blob_no, uint32_t *data, uint16_t len)
{
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
spi_flash_erase_sector(base_address);
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, data, len);
}
void blob_load(uint8_t blob_no, uint32_t *data, uint16_t len)
{
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, data, len);
}
void blob_zero(uint8_t blob_no, uint16_t len)
{
int i;
uint8_t z[len];
os_memset(z, 0,len);
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
spi_flash_erase_sector(base_address);
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32_t *)z, len);
}

Wyświetl plik

@ -0,0 +1,56 @@
#ifndef _CONFIG_FLASH_H_
#define _CONFIG_FLASH_H_
#include "c_types.h"
#include "mem.h"
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "spi_flash.h"
#include "user_config.h"
#define FLASH_BLOCK_NO 0xc
#define MAGIC_NUMBER 0x015005fc
typedef struct
{
// To check if the structure is initialized or not in flash
uint32_t magic_number;
// Length of the structure, since this is a evolving library, the variant may change
// hence used for verification
uint16_t length;
/* Below variables are specific to my code */
uint8_t ssid[32]; // SSID of the AP to connect to
uint8_t password[64]; // Password of the network
uint8_t auto_connect; // Should we auto connect
uint8_t ap_ssid[32]; // SSID of the own AP
uint8_t ap_password[64]; // Password of the own network
uint8_t ap_open; // Should we use no WPA?
uint8_t ap_on; // AP enabled?
uint8_t locked; // Should we allow for config changes
ip_addr_t network_addr; // Address of the internal network
ip_addr_t dns_addr; // Optional: address of the dns server
ip_addr_t my_addr; // Optional (if not DHCP): IP address of the uplink side
ip_addr_t my_netmask; // Optional (if not DHCP): IP netmask of the uplink side
ip_addr_t my_gw; // Optional (if not DHCP): Gateway of the uplink side
uint16_t clock_speed; // Freq of the CPU
uint16_t config_port; // Port on which the concole listenes (0 if no access)
} sysconfig_t, *sysconfig_p;
int config_load(sysconfig_p config);
void config_save(sysconfig_p config);
void blob_save(uint8_t blob_no, uint32_t *data, uint16_t len);
void blob_load(uint8_t blob_no, uint32_t *data, uint16_t len);
void blob_zero(uint8_t blob_no, uint16_t len);
#endif

250
user/ringbuf.c 100644
Wyświetl plik

@ -0,0 +1,250 @@
/*
* ringbuf.c - C ring buffer (FIFO) implementation.
*
* Written in 2011 by Drew Hess <dhess-src@bothan.net>.
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to
* the public domain worldwide. This software is distributed without
* any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "ringbuf.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/param.h>
#include "osapi.h"
#include "mem.h"
#define assert(x)
/*
* The code is written for clarity, not cleverness or performance, and
* contains many assert()s to enforce invariant assumptions and catch
* bugs. Feel free to optimize the code and to remove asserts for use
* in your own projects, once you're comfortable that it functions as
* intended.
*/
struct ringbuf_t
{
uint8_t *buf;
uint8_t *head, *tail;
size_t size;
};
ringbuf_t
ringbuf_new(size_t capacity)
{
ringbuf_t rb = (ringbuf_t)os_malloc(sizeof(struct ringbuf_t));
if (rb) {
/* One byte is used for detecting the full condition. */
rb->size = capacity + 1;
rb->buf = (uint8_t *)os_malloc(rb->size);
if (rb->buf)
ringbuf_reset(rb);
else {
os_free(rb);
return 0;
}
}
return rb;
}
size_t
ringbuf_buffer_size(const struct ringbuf_t *rb)
{
return rb->size;
}
void
ringbuf_reset(ringbuf_t rb)
{
rb->head = rb->tail = rb->buf;
}
void
ringbuf_free(ringbuf_t *rb)
{
assert(rb && *rb);
os_free((*rb)->buf);
os_free(*rb);
*rb = 0;
}
size_t
ringbuf_capacity(const struct ringbuf_t *rb)
{
return ringbuf_buffer_size(rb) - 1;
}
/*
* Return a pointer to one-past-the-end of the ring buffer's
* contiguous buffer. You shouldn't normally need to use this function
* unless you're writing a new ringbuf_* function.
*/
static const uint8_t *
ringbuf_end(const struct ringbuf_t *rb)
{
return rb->buf + ringbuf_buffer_size(rb);
}
size_t
ringbuf_bytes_free(const struct ringbuf_t *rb)
{
if (rb->head >= rb->tail)
return ringbuf_capacity(rb) - (rb->head - rb->tail);
else
return rb->tail - rb->head - 1;
}
size_t
ringbuf_bytes_used(const struct ringbuf_t *rb)
{
return ringbuf_capacity(rb) - ringbuf_bytes_free(rb);
}
int
ringbuf_is_full(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == 0;
}
int
ringbuf_is_empty(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == ringbuf_capacity(rb);
}
const void *
ringbuf_tail(const struct ringbuf_t *rb)
{
return rb->tail;
}
const void *
ringbuf_head(const struct ringbuf_t *rb)
{
return rb->head;
}
/*
* Given a ring buffer rb and a pointer to a location within its
* contiguous buffer, return the a pointer to the next logical
* location in the ring buffer.
*/
static uint8_t *
ringbuf_nextp(ringbuf_t rb, const uint8_t *p)
{
/*
* The assert guarantees the expression (++p - rb->buf) is
* non-negative; therefore, the modulus operation is safe and
* portable.
*/
assert((p >= rb->buf) && (p < ringbuf_end(rb)));
return rb->buf + ((++p - rb->buf) % ringbuf_buffer_size(rb));
}
void *
ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count)
{
const uint8_t *u8src = src;
const uint8_t *bufend = ringbuf_end(dst);
int overflow = count > ringbuf_bytes_free(dst);
size_t nread = 0;
while (nread != count) {
/* don't copy beyond the end of the buffer */
assert(bufend > dst->head);
size_t n = MIN(bufend - dst->head, count - nread);
os_memcpy(dst->head, u8src + nread, n);
dst->head += n;
nread += n;
/* wrap? */
if (dst->head == bufend)
dst->head = dst->buf;
}
if (overflow) {
dst->tail = ringbuf_nextp(dst, dst->head);
assert(ringbuf_is_full(dst));
}
return dst->head;
}
void *
ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count)
{
size_t bytes_used = ringbuf_bytes_used(src);
if (count > bytes_used)
return 0;
uint8_t *u8dst = dst;
const uint8_t *bufend = ringbuf_end(src);
size_t nwritten = 0;
while (nwritten != count) {
assert(bufend > src->tail);
size_t n = MIN(bufend - src->tail, count - nwritten);
os_memcpy(u8dst + nwritten, src->tail, n);
src->tail += n;
nwritten += n;
/* wrap ? */
if (src->tail == bufend)
src->tail = src->buf;
}
assert(count + ringbuf_bytes_used(src) == bytes_used);
return src->tail;
}
void *
ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count)
{
size_t src_bytes_used = ringbuf_bytes_used(src);
if (count > src_bytes_used)
return 0;
int overflow = count > ringbuf_bytes_free(dst);
const uint8_t *src_bufend = ringbuf_end(src);
const uint8_t *dst_bufend = ringbuf_end(dst);
size_t ncopied = 0;
while (ncopied != count) {
assert(src_bufend > src->tail);
size_t nsrc = MIN(src_bufend - src->tail, count - ncopied);
assert(dst_bufend > dst->head);
size_t n = MIN(dst_bufend - dst->head, nsrc);
os_memcpy(dst->head, src->tail, n);
src->tail += n;
dst->head += n;
ncopied += n;
/* wrap ? */
if (src->tail == src_bufend)
src->tail = src->buf;
if (dst->head == dst_bufend)
dst->head = dst->buf;
}
assert(count + ringbuf_bytes_used(src) == src_bytes_used);
if (overflow) {
dst->tail = ringbuf_nextp(dst, dst->head);
assert(ringbuf_is_full(dst));
}
return dst->head;
}

167
user/ringbuf.h 100644
Wyświetl plik

@ -0,0 +1,167 @@
#ifndef INCLUDED_RINGBUF_H
#define INCLUDED_RINGBUF_H
/*
* ringbuf.h - C ring buffer (FIFO) interface.
*
* Written in 2011 by Drew Hess <dhess-src@bothan.net>.
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to
* the public domain worldwide. This software is distributed without
* any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/*
* A byte-addressable ring buffer FIFO implementation.
*
* The ring buffer's head pointer points to the starting location
* where data should be written when copying data *into* the buffer
* (e.g., with ringbuf_read). The ring buffer's tail pointer points to
* the starting location where data should be read when copying data
* *from* the buffer (e.g., with ringbuf_write).
*/
#include <stddef.h>
#include <sys/types.h>
typedef struct ringbuf_t *ringbuf_t;
/*
* Create a new ring buffer with the given capacity (usable
* bytes). Note that the actual internal buffer size may be one or
* more bytes larger than the usable capacity, for bookkeeping.
*
* Returns the new ring buffer object, or 0 if there's not enough
* memory to fulfill the request for the given capacity.
*/
ringbuf_t
ringbuf_new(size_t capacity);
/*
* The size of the internal buffer, in bytes. One or more bytes may be
* unusable in order to distinguish the "buffer full" state from the
* "buffer empty" state.
*
* For the usable capacity of the ring buffer, use the
* ringbuf_capacity function.
*/
size_t
ringbuf_buffer_size(const struct ringbuf_t *rb);
/*
* Deallocate a ring buffer, and, as a side effect, set the pointer to
* 0.
*/
void
ringbuf_free(ringbuf_t *rb);
/*
* Reset a ring buffer to its initial state (empty).
*/
void
ringbuf_reset(ringbuf_t rb);
/*
* The usable capacity of the ring buffer, in bytes. Note that this
* value may be less than the ring buffer's internal buffer size, as
* returned by ringbuf_buffer_size.
*/
size_t
ringbuf_capacity(const struct ringbuf_t *rb);
/*
* The number of free/available bytes in the ring buffer. This value
* is never larger than the ring buffer's usable capacity.
*/
size_t
ringbuf_bytes_free(const struct ringbuf_t *rb);
/*
* The number of bytes currently being used in the ring buffer. This
* value is never larger than the ring buffer's usable capacity.
*/
size_t
ringbuf_bytes_used(const struct ringbuf_t *rb);
int
ringbuf_is_full(const struct ringbuf_t *rb);
int
ringbuf_is_empty(const struct ringbuf_t *rb);
/*
* Const access to the head and tail pointers of the ring buffer.
*/
const void *
ringbuf_tail(const struct ringbuf_t *rb);
const void *
ringbuf_head(const struct ringbuf_t *rb);
/*
* Copy n bytes from a contiguous memory area src into the ring buffer
* dst. Returns the ring buffer's new head pointer.
*
* It is possible to copy more data from src than is available in the
* buffer; i.e., it's possible to overflow the ring buffer using this
* function. When an overflow occurs, the state of the ring buffer is
* guaranteed to be consistent, including the head and tail pointers;
* old data will simply be overwritten in FIFO fashion, as
* needed. However, note that, if calling the function results in an
* overflow, the value of the ring buffer's tail pointer may be
* different than it was before the function was called.
*/
void *
ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count);
/*
* Copy n bytes from the ring buffer src, starting from its tail
* pointer, into a contiguous memory area dst. Returns the value of
* src's tail pointer after the copy is finished.
*
* Note that this copy is destructive with respect to the ring buffer:
* the n bytes copied from the ring buffer are no longer available in
* the ring buffer after the copy is complete, and the ring buffer
* will have n more free bytes than it did before the function was
* called.
*
* This function will *not* allow the ring buffer to underflow. If
* count is greater than the number of bytes used in the ring buffer,
* no bytes are copied, and the function will return 0.
*/
void *
ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count);
/*
* Copy count bytes from ring buffer src, starting from its tail
* pointer, into ring buffer dst. Returns dst's new head pointer after
* the copy is finished.
*
* Note that this copy is destructive with respect to the ring buffer
* src: any bytes copied from src into dst are no longer available in
* src after the copy is complete, and src will have 'count' more free
* bytes than it did before the function was called.
*
* It is possible to copy more data from src than is available in dst;
* i.e., it's possible to overflow dst using this function. When an
* overflow occurs, the state of dst is guaranteed to be consistent,
* including the head and tail pointers; old data will simply be
* overwritten in FIFO fashion, as needed. However, note that, if
* calling the function results in an overflow, the value dst's tail
* pointer may be different than it was before the function was
* called.
*
* It is *not* possible to underflow src; if count is greater than the
* number of bytes used in src, no bytes are copied, and the function
* returns 0.
*/
void *
ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count);
#endif /* INCLUDED_RINGBUF_H */

32
user/sys_time.c 100644
Wyświetl plik

@ -0,0 +1,32 @@
#include "c_types.h"
#include "osapi.h"
typedef union _timer {
uint32_t time_s[2];
uint64_t time_l;
} long_time_t;
static long_time_t time;
static uint32_t old;
uint64_t ICACHE_FLASH_ATTR get_long_systime() {
uint32_t now = system_get_time();
if (now < old) {
time.time_s[1]++;
}
old = now;
time.time_s[0] = now;
return time.time_l;
}
uint64_t ICACHE_FLASH_ATTR get_low_systime() {
get_long_systime();
return time.time_s[0];
}
void init_long_systime() {
old = system_get_time();
time.time_l = (uint64_t)old;
}

12
user/sys_time.h 100644
Wyświetl plik

@ -0,0 +1,12 @@
#include "c_types.h"
// returns time until boot in us
uint64_t ICACHE_FLASH_ATTR get_long_systime();
// returns lower half of time until boot in us
uint64_t ICACHE_FLASH_ATTR get_low_systime();
// initializes the timer
void init_long_systime();

48
user/user_config.h 100644
Wyświetl plik

@ -0,0 +1,48 @@
#ifndef _USER_CONFIG_
#define _USER_CONFIG_
typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SIG_CONSOLE_RX, SIG_CONSOLE_TX, SIG_GPIO_INT} USER_SIGNALS;
#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "password"
#define WIFI_AP_SSID "MyAP"
#define WIFI_AP_PASSWORD "none"
#define MAX_CLIENTS 8
#define MAX_DHCP 8
//
// Here the MQTT stuff
//
#define MQTT_BUF_SIZE 1024
#define MQTT_KEEPALIVE 120 /*seconds*/
#define MQTT_RECONNECT_TIMEOUT 5 /*seconds*/
//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/
//
// Size of the console buffers
//
#define MAX_CON_SEND_SIZE 1024
#define MAX_CON_CMD_SIZE 80
//
// Define this if you have a status LED connected to a GPIO pin
//
#define STATUS_LED_GIPO 2
//
// Define this to support the "scan" command for AP search
//
#define ALLOW_SCANNING 1
//
// Define this if you want to have access to the config console via TCP.
// Ohterwise only local access via serial is possible
//
#define REMOTE_CONFIG 1
#define CONSOLE_SERVER_PORT 7777
#endif

Wyświetl plik

@ -1,129 +1,860 @@
/* main.c -- MQTT client example
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "ets_sys.h"
#include "driver/uart.h"
#include "osapi.h"
#include "mqtt.h"
#include "wifi.h"
#include "debug.h"
#include "gpio.h"
#include "user_interface.h"
#include "c_types.h"
#include "mem.h"
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
MQTT_Client mqttClient;
static void ICACHE_FLASH_ATTR wifiConnectCb(uint8_t status)
#include "user_interface.h"
#include "string.h"
#include "driver/uart.h"
#include "ringbuf.h"
#include "user_config.h"
#include "config_flash.h"
#include "sys_time.h"
#include "mqtt_server.h"
#include "mqtt_topiclist.h"
#include "mqtt_retainedlist.h"
/* System Task, for signals refer to user_config.h */
#define user_procTaskPrio 0
#define user_procTaskQueueLen 1
os_event_t user_procTaskQueue[user_procTaskQueueLen];
static void user_procTask(os_event_t *events);
static os_timer_t ptimer;
/* Some stats */
uint64_t Bytes_in, Bytes_out, Bytes_in_last, Bytes_out_last;
uint32_t Packets_in, Packets_out, Packets_in_last, Packets_out_last;
uint64_t t_old;
/* Hold the system wide configuration */
sysconfig_t config;
static ringbuf_t console_rx_buffer, console_tx_buffer;
static ip_addr_t my_ip;
static ip_addr_t dns_ip;
bool connected;
uint8_t my_channel;
bool do_ip_config;
uint8_t remote_console_disconnect;
void ICACHE_FLASH_ATTR user_set_softap_wifi_config(void);
void ICACHE_FLASH_ATTR user_set_softap_ip_config(void);
int parse_str_into_tokens(char *str, char **tokens, int max_tokens)
{
if (status == STATION_GOT_IP) {
MQTT_Connect(&mqttClient);
} else {
MQTT_Disconnect(&mqttClient);
}
}
static void ICACHE_FLASH_ATTR mqttConnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
INFO("MQTT: Connected\r\n");
MQTT_Subscribe(client, "/mqtt/topic/0", 0);
MQTT_Subscribe(client, "/mqtt/topic/1", 1);
MQTT_Subscribe(client, "/mqtt/topic/2", 2);
char *p, *q;
int token_count = 0;
bool in_token = false;
MQTT_Publish(client, "/mqtt/topic/0", "hello0", 6, 0, 0);
MQTT_Publish(client, "/mqtt/topic/1", "hello1", 6, 1, 0);
MQTT_Publish(client, "/mqtt/topic/2", "hello2", 6, 2, 0);
// preprocessing
for (p = q = str; *p != 0; p++) {
if (*p == '\\') {
// next char is quoted, copy it skip, this one
if (*(p+1) != 0) *q++ = *++p;
} else if (*p == 8) {
// backspace - delete previous char
if (q != str) q--;
} else if (*p <= ' ') {
// mark this as whitespace
*q++ = 1;
} else {
*q++ = *p;
}
}
}
static void ICACHE_FLASH_ATTR mqttDisconnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
INFO("MQTT: Disconnected\r\n");
}
static void ICACHE_FLASH_ATTR mqttPublishedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
INFO("MQTT: Published\r\n");
}
static void ICACHE_FLASH_ATTR mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
{
char *topicBuf = (char*)os_zalloc(topic_len + 1),
*dataBuf = (char*)os_zalloc(data_len + 1);
MQTT_Client* client = (MQTT_Client*)args;
os_memcpy(topicBuf, topic, topic_len);
topicBuf[topic_len] = 0;
os_memcpy(dataBuf, data, data_len);
dataBuf[data_len] = 0;
INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf);
os_free(topicBuf);
os_free(dataBuf);
}
void ICACHE_FLASH_ATTR print_info()
{
INFO("\r\n\r\n[INFO] BOOTUP...\r\n");
INFO("[INFO] SDK: %s\r\n", system_get_sdk_version());
INFO("[INFO] Chip ID: %08X\r\n", system_get_chip_id());
INFO("[INFO] Memory info:\r\n");
system_print_meminfo();
INFO("[INFO] -------------------------------------------\n");
INFO("[INFO] Build time: %s\n", BUID_TIME);
INFO("[INFO] -------------------------------------------\n");
*q = 0;
// cut into tokens
for (p = str; *p != 0; p++) {
if (*p == 1) {
if (in_token) {
*p = 0;
in_token = false;
}
} else {
if (*p & 0x80) *p &= 0x7f;
if (!in_token) {
tokens[token_count++] = p;
if (token_count == max_tokens)
return token_count;
in_token = true;
}
}
}
return token_count;
}
static void ICACHE_FLASH_ATTR app_init(void)
void console_send_response(struct espconn *pespconn)
{
uart_init(BIT_RATE_115200, BIT_RATE_115200);
print_info();
MQTT_InitConnection(&mqttClient, MQTT_HOST, MQTT_PORT, DEFAULT_SECURITY);
//MQTT_InitConnection(&mqttClient, "192.168.11.122", 1880, 0);
char payload[MAX_CON_SEND_SIZE+4];
uint16_t len = ringbuf_bytes_used(console_tx_buffer);
if ( !MQTT_InitClient(&mqttClient, MQTT_CLIENT_ID, MQTT_USER, MQTT_PASS, MQTT_KEEPALIVE, MQTT_CLEAN_SESSION) )
ringbuf_memcpy_from(payload, console_tx_buffer, len);
os_memcpy(&payload[len], "CMD>", 4);
if (pespconn != NULL)
espconn_sent(pespconn, payload, len+4);
else
UART_Send(0, &payload, len+4);
}
#ifdef ALLOW_SCANNING
struct espconn *scanconn;
void ICACHE_FLASH_ATTR scan_done(void *arg, STATUS status)
{
char response[128];
if (status == OK)
{
INFO("Failed to initialize properly. Check MQTT version.\r\n");
return;
}
//MQTT_InitClient(&mqttClient, "client_id", "user", "pass", 120, 1);
MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);
MQTT_OnConnected(&mqttClient, mqttConnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
MQTT_OnPublished(&mqttClient, mqttPublishedCb);
MQTT_OnData(&mqttClient, mqttDataCb);
struct bss_info *bss_link = (struct bss_info *)arg;
WIFI_Connect(STA_SSID, STA_PASS, wifiConnectCb);
ringbuf_memcpy_into(console_tx_buffer, "\r", 1);
while (bss_link != NULL)
{
os_sprintf(response, "%d,\"%s\",%d,\""MACSTR"\",%d\r\n",
bss_link->authmode, bss_link->ssid, bss_link->rssi,
MAC2STR(bss_link->bssid),bss_link->channel);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
bss_link = bss_link->next.stqe_next;
}
}
else
{
os_sprintf(response, "scan fail !!!\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
}
system_os_post(0, SIG_CONSOLE_TX, (ETSParam) scanconn);
}
void user_init(void)
#endif
bool ICACHE_FLASH_ATTR printf_topic(topic_entry *topic, void *user_data)
{
system_init_done_cb(app_init);
uint8_t *response = (uint8_t *)user_data;
os_sprintf(response, "%s: \"%s\" (QoS %d)\r\n",
topic->clientcon!=LOCAL_MQTT_CLIENT?topic->clientcon->connect_info.client_id:"LOCAL", topic->topic, topic->qos);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
return false;
}
bool ICACHE_FLASH_ATTR printf_retainedtopic(retained_entry *entry, void *user_data)
{
uint8_t *response = (uint8_t *)user_data;
os_sprintf(response, "\"%s\" len: %d (QoS %d)\r\n", entry->topic, entry->data_len, entry->qos);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
return false;
}
void MQTT_local_DataCallback(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t length)
{
os_printf("Received: \"%s\" len: %d\r\n", topic, length);
}
static char INVALID_LOCKED[] = "Invalid command. Config locked\r\n";
static char INVALID_NUMARGS[] = "Invalid number of arguments\r\n";
static char INVALID_ARG[] = "Invalid argument\r\n";
void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
{
#define MAX_CMD_TOKENS 9
char cmd_line[MAX_CON_CMD_SIZE+1];
char response[256];
char *tokens[MAX_CMD_TOKENS];
int bytes_count, nTokens;
bytes_count = ringbuf_bytes_used(console_rx_buffer);
ringbuf_memcpy_from(cmd_line, console_rx_buffer, bytes_count);
cmd_line[bytes_count] = 0;
response[0] = 0;
nTokens = parse_str_into_tokens(cmd_line, tokens, MAX_CMD_TOKENS);
if (nTokens == 0) {
char c = '\n';
ringbuf_memcpy_into(console_tx_buffer, &c, 1);
goto command_handled_2;
}
if (strcmp(tokens[0], "help") == 0)
{
os_sprintf(response, "show [config|stats|mqtt_broker]\r\n|set [ssid|password|auto_connect|ap_ssid|ap_password|network|dns|ip|netmask|gw|ap_on|ap_open|speed|config_port] <val>\r\n|quit|save [config]|reset [factory]|lock|unlock <password>|publish <topic> <data>|subscribe <topic>|unsubscribe <topic>");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#ifdef ALLOW_SCANNING
os_sprintf(response, "|scan");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#endif
ringbuf_memcpy_into(console_tx_buffer, "\r\n", 2);
goto command_handled_2;
}
if (strcmp(tokens[0], "show") == 0)
{
int16_t i;
ip_addr_t i_ip;
if (nTokens == 1 || (nTokens == 2 && strcmp(tokens[1], "config") == 0)) {
os_sprintf(response, "STA: SSID:%s PW:%s%s\r\n",
config.ssid,
config.locked?"***":(char*)config.password,
config.auto_connect?"":" [AutoConnect:0]");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
os_sprintf(response, "AP: SSID:%s PW:%s%s%s IP:%d.%d.%d.%d/24",
config.ap_ssid,
config.locked?"***":(char*)config.ap_password,
config.ap_open?" [open]":"",
config.ap_on?"":" [disabled]",
IP2STR(&config.network_addr));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
// if static DNS, add it
os_sprintf(response, config.dns_addr.addr?" DNS: %d.%d.%d.%d\r\n":"\r\n", IP2STR(&config.dns_addr));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
// if static IP, add it
os_sprintf(response, config.my_addr.addr?"Static IP: %d.%d.%d.%d Netmask: %d.%d.%d.%d Gateway: %d.%d.%d.%d\r\n":"",
IP2STR(&config.my_addr), IP2STR(&config.my_netmask), IP2STR(&config.my_gw));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
os_sprintf(response, "Clock speed: %d\r\n", config.clock_speed);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
goto command_handled_2;
}
if (nTokens == 2 && strcmp(tokens[1], "stats") == 0) {
uint32_t time = (uint32_t)(get_long_systime()/1000000);
int16_t i;
os_sprintf(response, "System uptime: %d:%02d:%02d\r\n",
time/3600, (time%3600)/60, time%60);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
os_sprintf(response, "%d KiB in (%d packets)\r\n%d KiB out (%d packets)\r\n",
(uint32_t)(Bytes_in/1024), Packets_in,
(uint32_t)(Bytes_out/1024), Packets_out);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
if (connected) {
os_sprintf(response, "External IP-address: " IPSTR "\r\n", IP2STR(&my_ip));
} else {
os_sprintf(response, "Not connected to AP\r\n");
}
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
if (config.ap_on)
os_sprintf(response, "%d Stations connected\r\n", wifi_softap_get_station_num());
else
os_sprintf(response, "AP disabled\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
goto command_handled_2;
}
if (nTokens == 2 && strcmp(tokens[1], "mqtt_broker") == 0) {
MQTT_ClientCon *clientcon = clientcon_list;
os_sprintf(response, "Current clients:\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
for (clientcon = clientcon_list; clientcon != NULL; clientcon = clientcon->next) {
os_sprintf(response, "%s%s", clientcon->connect_info.client_id, clientcon->next != NULL?", ":"");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
}
os_sprintf(response, "\r\nCurrent subsriptions:\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
iterate_topics(printf_topic, response);
os_sprintf(response, "Retained topics:\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
iterate_retainedtopics(printf_retainedtopic, response);
goto command_handled_2;
}
}
if (strcmp(tokens[0], "save") == 0)
{
if (config.locked) {
os_sprintf(response, INVALID_LOCKED);
goto command_handled;
}
if (nTokens == 1 || (nTokens == 2 && strcmp(tokens[1], "config") == 0)) {
config_save(&config);
os_sprintf(response, "Config saved\r\n");
goto command_handled;
}
}
#ifdef ALLOW_SCANNING
if (strcmp(tokens[0], "scan") == 0)
{
scanconn = pespconn;
wifi_station_scan(NULL,scan_done);
os_sprintf(response, "Scanning...\r\n");
goto command_handled;
}
#endif
if (strcmp(tokens[0], "reset") == 0)
{
if (nTokens == 2 && strcmp(tokens[1], "factory") == 0) {
config_load_default(&config);
config_save(&config);
}
os_printf("Restarting ... \r\n");
system_restart(); // if it works this will not return
os_sprintf(response, "Reset failed\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "quit") == 0)
{
remote_console_disconnect = 1;
os_sprintf(response, "Quitting console\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "publish") == 0)
{
if (nTokens != 3) {
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
MQTT_local_publish(tokens[1], tokens[2], os_strlen(tokens[2]), 0, 0);
os_sprintf(response, "Published topic\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "subscribe") == 0)
{
if (nTokens != 2) {
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
MQTT_local_subscribe(tokens[1], 0);
os_sprintf(response, "subscribed topic\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "unsubscribe") == 0)
{
if (nTokens != 2) {
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
uint8_t retval = MQTT_local_unsubscribe(tokens[1]);
if (retval)
os_sprintf(response, "unsubscribed topic\r\n");
else
os_sprintf(response, "unsubscribe failed\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "lock") == 0)
{
config.locked = 1;
os_sprintf(response, "Config locked\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "unlock") == 0)
{
if (nTokens != 2) {
os_sprintf(response, INVALID_NUMARGS);
}
else if (strcmp(tokens[1],config.password) == 0) {
config.locked = 0;
os_sprintf(response, "Config unlocked\r\n");
} else {
os_sprintf(response, "Unlock failed. Invalid password\r\n");
}
goto command_handled;
}
if (strcmp(tokens[0], "set") == 0)
{
if (config.locked)
{
os_sprintf(response, INVALID_LOCKED);
goto command_handled;
}
/*
* For set commands atleast 2 tokens "set" "parameter" "value" is needed
* hence the check
*/
if (nTokens < 3)
{
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
else
{
// atleast 3 tokens, proceed
if (strcmp(tokens[1],"ssid") == 0)
{
os_sprintf(config.ssid, "%s", tokens[2]);
os_sprintf(response, "SSID set\r\n");
goto command_handled;
}
if (strcmp(tokens[1],"password") == 0)
{
os_sprintf(config.password, "%s", tokens[2]);
os_sprintf(response, "Password set\r\n");
goto command_handled;
}
if (strcmp(tokens[1],"auto_connect") == 0)
{
config.auto_connect = atoi(tokens[2]);
os_sprintf(response, "Auto Connect set\r\n");
goto command_handled;
}
if (strcmp(tokens[1],"ap_ssid") == 0)
{
os_sprintf(config.ap_ssid, "%s", tokens[2]);
os_sprintf(response, "AP SSID set\r\n");
goto command_handled;
}
if (strcmp(tokens[1],"ap_password") == 0)
{
if (os_strlen(tokens[2])<8) {
os_sprintf(response, "Password to short (min. 8)\r\n");
} else {
os_sprintf(config.ap_password, "%s", tokens[2]);
config.ap_open = 0;
os_sprintf(response, "AP Password set\r\n");
}
goto command_handled;
}
if (strcmp(tokens[1],"ap_open") == 0)
{
config.ap_open = atoi(tokens[2]);
os_sprintf(response, "Open Auth set\r\n");
goto command_handled;
}
if (strcmp(tokens[1],"ap_on") == 0)
{
if (atoi(tokens[2])) {
if (!config.ap_on) {
wifi_set_opmode(STATIONAP_MODE);
user_set_softap_wifi_config();
do_ip_config = true;
config.ap_on = true;
os_sprintf(response, "AP on\r\n");
} else {
os_sprintf(response, "AP already on\r\n");
}
} else {
if (config.ap_on) {
wifi_set_opmode(STATION_MODE);
config.ap_on = false;
os_sprintf(response, "AP off\r\n");
} else {
os_sprintf(response, "AP already off\r\n");
}
}
goto command_handled;
}
if (strcmp(tokens[1], "speed") == 0)
{
uint16_t speed = atoi(tokens[2]);
bool succ = system_update_cpu_freq(speed);
if (succ)
config.clock_speed = speed;
os_sprintf(response, "Clock speed update %s\r\n",
succ?"successful":"failed");
goto command_handled;
}
if (strcmp(tokens[1],"network") == 0)
{
config.network_addr.addr = ipaddr_addr(tokens[2]);
ip4_addr4(&config.network_addr) = 0;
os_sprintf(response, "Network set to %d.%d.%d.%d/24\r\n",
IP2STR(&config.network_addr));
goto command_handled;
}
if (strcmp(tokens[1],"ip") == 0)
{
if (os_strcmp(tokens[2], "dhcp") == 0) {
config.my_addr.addr = 0;
os_sprintf(response, "IP from DHCP\r\n");
} else {
config.my_addr.addr = ipaddr_addr(tokens[2]);
os_sprintf(response, "IP address set to %d.%d.%d.%d\r\n",
IP2STR(&config.my_addr));
}
goto command_handled;
}
if (strcmp(tokens[1],"netmask") == 0)
{
config.my_netmask.addr = ipaddr_addr(tokens[2]);
os_sprintf(response, "IP netmask set to %d.%d.%d.%d\r\n",
IP2STR(&config.my_netmask));
goto command_handled;
}
if (strcmp(tokens[1],"gw") == 0)
{
config.my_gw.addr = ipaddr_addr(tokens[2]);
os_sprintf(response, "Gateway set to %d.%d.%d.%d\r\n",
IP2STR(&config.my_gw));
goto command_handled;
}
}
}
/* Control comes here only if the tokens[0] command is not handled */
os_sprintf(response, "\r\nInvalid Command\r\n");
command_handled:
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
command_handled_2:
system_os_post(0, SIG_CONSOLE_TX, (ETSParam) pespconn);
return;
}
#ifdef REMOTE_CONFIG
static void ICACHE_FLASH_ATTR tcp_client_recv_cb(void *arg,
char *data,
unsigned short length)
{
struct espconn *pespconn = (struct espconn *)arg;
int index;
uint8_t ch;
for (index=0; index <length; index++)
{
ch = *(data+index);
ringbuf_memcpy_into(console_rx_buffer, &ch, 1);
// If a complete commandline is received, then signal the main
// task that command is available for processing
if (ch == '\n')
system_os_post(0, SIG_CONSOLE_RX, (ETSParam) arg);
}
*(data+length) = 0;
}
static void ICACHE_FLASH_ATTR tcp_client_discon_cb(void *arg)
{
os_printf("tcp_client_discon_cb(): client disconnected\n");
struct espconn *pespconn = (struct espconn *)arg;
}
/* Called when a client connects to the console server */
static void ICACHE_FLASH_ATTR tcp_client_connected_cb(void *arg)
{
char payload[128];
struct espconn *pespconn = (struct espconn *)arg;
os_printf("tcp_client_connected_cb(): Client connected\r\n");
//espconn_regist_sentcb(pespconn, tcp_client_sent_cb);
espconn_regist_disconcb(pespconn, tcp_client_discon_cb);
espconn_regist_recvcb(pespconn, tcp_client_recv_cb);
espconn_regist_time(pespconn, 300, 1); // Specific to console only
ringbuf_reset(console_rx_buffer);
ringbuf_reset(console_tx_buffer);
os_sprintf(payload, "CMD>");
espconn_sent(pespconn, payload, os_strlen(payload));
}
#endif /* REMOTE_CONFIG */
bool toggle;
// Timer cb function
void ICACHE_FLASH_ATTR timer_func(void *arg){
uint32_t Vcurr;
uint64_t t_new;
uint32_t t_diff;
toggle = !toggle;
// Do we still have to configure the AP netif?
if (do_ip_config) {
user_set_softap_ip_config();
do_ip_config = false;
}
t_new = get_long_systime();
os_timer_arm(&ptimer, toggle?1000:100, 0);
}
//Priority 0 Task
static void ICACHE_FLASH_ATTR user_procTask(os_event_t *events)
{
//os_printf("Sig: %d\r\n", events->sig);
switch(events->sig)
{
case SIG_START_SERVER:
// Anything else to do here, when the repeater has received its IP?
break;
case SIG_CONSOLE_TX:
{
struct espconn *pespconn = (struct espconn *) events->par;
console_send_response(pespconn);
if (pespconn != 0 && remote_console_disconnect) espconn_disconnect(pespconn);
remote_console_disconnect = 0;
}
break;
case SIG_CONSOLE_RX:
{
struct espconn *pespconn = (struct espconn *) events->par;
console_handle_command(pespconn);
}
break;
case SIG_DO_NOTHING:
default:
// Intentionally ignoring other signals
os_printf("Spurious Signal received\r\n");
break;
}
}
/* Callback called when the connection state of the module with an Access Point changes */
void wifi_handle_event_cb(System_Event_t *evt)
{
uint16_t i;
uint8_t mac_str[20];
//os_printf("wifi_handle_event_cb: ");
switch (evt->event)
{
case EVENT_STAMODE_CONNECTED:
os_printf("connect to ssid %s, channel %d\n", evt->event_info.connected.ssid, evt->event_info.connected.channel);
my_channel = evt->event_info.connected.channel;
break;
case EVENT_STAMODE_DISCONNECTED:
os_printf("disconnect from ssid %s, reason %d\n", evt->event_info.disconnected.ssid, evt->event_info.disconnected.reason);
connected = false;
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
os_printf("mode: %d -> %d\n", evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode);
break;
case EVENT_STAMODE_GOT_IP:
os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR ",dns:" IPSTR "\n", IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), IP2STR(&evt->event_info.got_ip.gw), IP2STR(&dns_ip));
my_ip = evt->event_info.got_ip.ip;
connected = true;
// Post a Server Start message as the IP has been acquired to Task with priority 0
system_os_post(user_procTaskPrio, SIG_START_SERVER, 0 );
break;
case EVENT_SOFTAPMODE_STACONNECTED:
os_sprintf(mac_str, MACSTR, MAC2STR(evt->event_info.sta_connected.mac));
os_printf("station: %s join, AID = %d\n", mac_str, evt->event_info.sta_connected.aid);
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
os_sprintf(mac_str, MACSTR, MAC2STR(evt->event_info.sta_disconnected.mac));
os_printf("station: %s leave, AID = %d\n", mac_str, evt->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
void ICACHE_FLASH_ATTR user_set_softap_wifi_config(void)
{
struct softap_config apConfig;
wifi_softap_get_config(&apConfig); // Get config first.
os_memset(apConfig.ssid, 0, 32);
os_sprintf(apConfig.ssid, "%s", config.ap_ssid);
os_memset(apConfig.password, 0, 64);
os_sprintf(apConfig.password, "%s", config.ap_password);
if (!config.ap_open)
apConfig.authmode = AUTH_WPA_WPA2_PSK;
else
apConfig.authmode = AUTH_OPEN;
apConfig.ssid_len = 0;// or its actual length
apConfig.max_connection = MAX_CLIENTS; // how many stations can connect to ESP8266 softAP at most.
// Set ESP8266 softap config
wifi_softap_set_config(&apConfig);
}
void ICACHE_FLASH_ATTR user_set_softap_ip_config(void)
{
struct ip_info info;
struct dhcps_lease dhcp_lease;
struct netif *nif;
int i;
// Configure the internal network
wifi_softap_dhcps_stop();
info.ip = config.network_addr;
ip4_addr4(&info.ip) = 1;
info.gw = info.ip;
IP4_ADDR(&info.netmask, 255, 255, 255, 0);
wifi_set_ip_info(1, &info);
dhcp_lease.start_ip = config.network_addr;
ip4_addr4(&dhcp_lease.start_ip) = 2;
dhcp_lease.end_ip = config.network_addr;
ip4_addr4(&dhcp_lease.end_ip) = 128;
wifi_softap_set_dhcps_lease(&dhcp_lease);
wifi_softap_dhcps_start();
}
void ICACHE_FLASH_ATTR user_set_station_config(void)
{
struct station_config stationConf;
char hostname[40];
/* Setup AP credentials */
stationConf.bssid_set = 0;
os_sprintf(stationConf.ssid, "%s", config.ssid);
os_sprintf(stationConf.password, "%s", config.password);
wifi_station_set_config(&stationConf);
os_sprintf(hostname, "NET_%s", config.ap_ssid);
hostname[32] = '\0';
wifi_station_set_hostname(hostname);
wifi_set_event_handler_cb(wifi_handle_event_cb);
wifi_station_set_auto_connect(config.auto_connect != 0);
}
void ICACHE_FLASH_ATTR user_init()
{
struct ip_info info;
connected = false;
do_ip_config = false;
my_ip.addr = 0;
Bytes_in = Bytes_out = Bytes_in_last = Bytes_out_last = 0,
Packets_in = Packets_out = Packets_in_last = Packets_out_last = 0;
t_old = 0;
console_rx_buffer = ringbuf_new(MAX_CON_CMD_SIZE);
console_tx_buffer = ringbuf_new(MAX_CON_SEND_SIZE);
gpio_init();
init_long_systime();
UART_init_console(BIT_RATE_115200, 0, console_rx_buffer, console_tx_buffer);
os_printf("\r\n\r\nWiFi Router/MQTT Broker V1.5 starting\r\n");
// Load config
config_load(&config);
// Configure the AP and start it, if required
if (config.dns_addr.addr == 0)
// Google's DNS as default, as long as we havn't got one from DHCP
IP4_ADDR(&dns_ip, 8, 8, 8, 8);
else
// We have a static DNS server
dns_ip.addr = config.dns_addr.addr;
if (config.ap_on) {
wifi_set_opmode(STATIONAP_MODE);
user_set_softap_wifi_config();
do_ip_config = true;
} else {
wifi_set_opmode(STATION_MODE);
}
if (config.my_addr.addr != 0) {
wifi_station_dhcpc_stop();
info.ip.addr = config.my_addr.addr;
info.gw.addr = config.my_gw.addr;
info.netmask.addr = config.my_netmask.addr;
wifi_set_ip_info(STATION_IF, &info);
espconn_dns_setserver(0, &dns_ip);
}
#ifdef REMOTE_CONFIG
if (config.config_port != 0) {
os_printf("Starting Console TCP Server on %d port\r\n", CONSOLE_SERVER_PORT);
struct espconn *pCon = (struct espconn *)os_zalloc(sizeof(struct espconn));
/* Equivalent to bind */
pCon->type = ESPCONN_TCP;
pCon->state = ESPCONN_NONE;
pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
pCon->proto.tcp->local_port = config.config_port;
/* Register callback when clients connect to the server */
espconn_regist_connectcb(pCon, tcp_client_connected_cb);
/* Put the connection in accept mode */
espconn_accept(pCon);
}
#endif
remote_console_disconnect = 0;
// Now start the STA-Mode
user_set_station_config();
system_update_cpu_freq(config.clock_speed);
espconn_tcp_set_max_con(10);
os_printf("Max number of TCP clients: %d\r\n", espconn_tcp_get_max_con());
MQTT_server_start(1883 /*port*/, 30 /*max_subscriptions*/, 30 /*max_retained_items*/);
//MQTT_local_subscribe("/test/#", 0);
MQTT_local_onData(MQTT_local_DataCallback);
// Start the timer
os_timer_setfn(&ptimer, timer_func, 0);
os_timer_arm(&ptimer, 500, 0);
//Start task
system_os_task(user_procTask, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);
}