Removed example project junk & added UART drivers

This commit is contained in:
2017-01-23 01:48:05 +01:00
parent be3c0fe926
commit aaec5323cd
40 changed files with 1121 additions and 1072 deletions
-86
View File
@@ -1,86 +0,0 @@
/*
Cgi routines as used by the tests in the html/test subdirectory.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <esp8266.h>
#include "cgi-test.h"
typedef struct {
int len;
int sendPos;
} TestbedState;
httpd_cgi_state ICACHE_FLASH_ATTR cgiTestbed(HttpdConnData *connData) {
char buff[1024];
int first=0;
int l, x;
TestbedState *state=(TestbedState*)connData->cgiData;
if (connData->conn==NULL) {
//Connection aborted. Clean up.
if (state) free(state);
return HTTPD_CGI_DONE;
}
if (state==NULL) {
//First call
state=malloc(sizeof(TestbedState));
memset(state, 0, sizeof(state));
connData->cgiData=state;
first=1;
}
if (connData->requestType==HTTPD_METHOD_GET) {
if (first) {
httpdStartResponse(connData, 200);
httpdHeader(connData, "content-type", "application/data");
httpdEndHeaders(connData);
l=httpdFindArg(connData->getArgs, "len", buff, sizeof(buff));
state->len=1024;
if (l!=-1) state->len=atoi(buff);
state->sendPos=0;
return HTTPD_CGI_MORE;
} else {
l=sizeof(buff);
if (l>(state->len-state->sendPos)) l=(state->len-state->sendPos);
//Fill with semi-random data
for (x=0; x<l; x++) buff[x]=((x^(state->sendPos>>10))&0x1F)+'0';
httpdSend(connData, buff, l);
state->sendPos+=l;
printf("Test: Uploaded %d/%d bytes\n", state->sendPos, state->len);
if (state->len<=state->sendPos) {
if (state) free(state);
return HTTPD_CGI_DONE;
} else {
return HTTPD_CGI_MORE;
}
}
}
if (connData->requestType==HTTPD_METHOD_POST) {
if (connData->post->len!=connData->post->received) {
//Still receiving data. Ignore this.
printf("Test: got %d/%d bytes\n", connData->post->received, connData->post->len);
return HTTPD_CGI_MORE;
} else {
httpdStartResponse(connData, 200);
httpdHeader(connData, "content-type", "text/plain");
httpdEndHeaders(connData);
l=sprintf(buff, "%d", connData->post->received);
httpdSend(connData, buff, l);
return HTTPD_CGI_DONE;
}
}
return HTTPD_CGI_DONE;
}
-8
View File
@@ -1,8 +0,0 @@
#ifndef CGI_TEST_H
#define CGI_TEST_H
#include "httpd.h"
httpd_cgi_state cgiTestbed(HttpdConnData *connData);
#endif
-76
View File
@@ -1,76 +0,0 @@
/*
Some random cgi routines. Used in the LED example and the page that returns the entire
flash as a binary. Also handles the hit counter on the main page.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <esp8266.h>
#include "cgi.h"
#include "io.h"
//cause I can't be bothered to write an ioGetLed()
static char currLedState=0;
//Cgi that turns the LED on or off according to the 'led' param in the POST data
httpd_cgi_state ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
int len;
char buff[1024];
if (connData->conn==NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
len=httpdFindArg(connData->post->buff, "led", buff, sizeof(buff));
if (len!=0) {
currLedState=atoi(buff);
ioLed(currLedState);
}
httpdRedirect(connData, "led.tpl");
return HTTPD_CGI_DONE;
}
//Template code for the led page.
httpd_cgi_state ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) {
char buff[128];
if (token==NULL) return HTTPD_CGI_DONE;
os_strcpy(buff, "Unknown");
if (os_strcmp(token, "ledstate")==0) {
if (currLedState) {
os_strcpy(buff, "on");
} else {
os_strcpy(buff, "off");
}
}
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}
static long hitCounter=0;
//Template code for the counter on the index page.
httpd_cgi_state ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **arg) {
char buff[128];
if (token==NULL) return HTTPD_CGI_DONE;
if (os_strcmp(token, "counter")==0) {
hitCounter++;
os_sprintf(buff, "%ld", hitCounter);
}
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}
-10
View File
@@ -1,10 +0,0 @@
#ifndef CGI_H
#define CGI_H
#include "httpd.h"
httpd_cgi_state cgiLed(HttpdConnData *connData);
httpd_cgi_state tplLed(HttpdConnData *connData, char *token, void **arg);
httpd_cgi_state tplCounter(HttpdConnData *connData, char *token, void **arg);
#endif
+15 -4
View File
@@ -14,6 +14,8 @@
#define LEDGPIO 2
#define BTNGPIO 0
static bool enable_ap_button = false;
static ETSTimer resetBtntimer;
void ICACHE_FLASH_ATTR ioLed(int ena) {
@@ -27,25 +29,34 @@ void ICACHE_FLASH_ATTR ioLed(int ena) {
static void ICACHE_FLASH_ATTR resetBtnTimerCb(void *arg) {
static int resetCnt=0;
if (!GPIO_INPUT_GET(BTNGPIO)) {
if (enable_ap_button && !GPIO_INPUT_GET(BTNGPIO)) {
resetCnt++;
} else {
if (resetCnt>=6) { //3 sec pressed
wifi_station_disconnect();
wifi_set_opmode(0x3); //reset to AP+STA mode
os_printf("Reset to AP mode. Restarting system...\n");
wifi_set_opmode(STATIONAP_MODE); //reset to AP+STA mode
info("Reset to AP mode from GPIO0, Restarting system...");
system_restart();
}
resetCnt=0;
}
}
void ioInit() {
void ICACHE_FLASH_ATTR ioInit() {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
gpio_output_set(0, 0, (1<<LEDGPIO), (1<<BTNGPIO));
os_timer_disarm(&resetBtntimer);
os_timer_setfn(&resetBtntimer, resetBtnTimerCb, NULL);
os_timer_arm(&resetBtntimer, 500, 1);
// One way to enter AP mode - hold GPIO0 low.
if (GPIO_INPUT_GET(BTNGPIO) == 0) {
// starting "in BOOT mode" - do not install the AP reset timer
warn("GPIO0 stuck low - AP reset button disabled.\n");
} else {
enable_ap_button = true;
dbg("Note: Hold GPIO0 low for reset to AP mode.\n");
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef IO_H
#define IO_H
void ICACHE_FLASH_ATTR ioLed(int ena);
void ioLed(int ena);
void ioInit(void);
#endif
+28
View File
@@ -0,0 +1,28 @@
#include <esp8266.h>
#include "uart_driver.h"
#include "uart_handler.h"
// Here the bitrates are defined
#define UART0_BAUD BIT_RATE_115200
#define UART1_BAUD BIT_RATE_115200
/**
* Init the serial ports
*/
void ICACHE_FLASH_ATTR serialInit(void)
{
UART_Init(UART0_BAUD, UART1_BAUD);
UART_SetPrintPort(UART0);
UART_SetupAsyncReceiver();
}
/**
* Handle a byte received from UART.
* Might do some buffering here maybe
*
* @param c
*/
void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
{
printf("'%c',", c);
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef SERIAL_H
#define SERIAL_H
/** Init the uarts */
void serialInit(void);
void UART_HandleRxByte(char c);
#endif //SERIAL_H
-47
View File
@@ -1,47 +0,0 @@
//Stupid bit of code that does the bare minimum to make os_printf work.
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <esp8266.h>
#include <uart_hw.h>
static void ICACHE_FLASH_ATTR stdoutUartTxd(char c) {
//Wait until there is room in the FIFO
while (((READ_PERI_REG(UART_STATUS(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
//Send the character
WRITE_PERI_REG(UART_FIFO(0), c);
}
static void ICACHE_FLASH_ATTR stdoutPutchar(char c) {
//convert \n -> \r\n
if (c=='\n') stdoutUartTxd('\r');
stdoutUartTxd(c);
}
void stdoutInit() {
//Enable TxD pin
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
//Set baud rate and other serial parameters to 115200,n,8,1
uart_div_modify(0, UART_CLK_FREQ/BIT_RATE_115200);
WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| \
(EIGHT_BITS << UART_BIT_NUM_S));
//Reset tx & rx fifo
SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
//Clear pending interrupts
WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);
//Install our own putchar handler
os_install_putc1((void *)stdoutPutchar);
}
-6
View File
@@ -1,6 +0,0 @@
#ifndef STDOUT_H
#define STDOUT_H
void stdoutInit();
#endif
+249
View File
@@ -0,0 +1,249 @@
/*
* Driver file for ESP8266 UART, works with the SDK.
*/
#include "uart_driver.h"
#include <esp8266.h>
#include "ets_sys.h"
#include "osapi.h"
#include "mem.h"
#include "os_type.h"
#include "ets_sys_extra.h"
#include "uart_register.h"
//========================================================
void ICACHE_FLASH_ATTR UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len)
{
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_BIT_NUM, len, UART_BIT_NUM_S);
}
void ICACHE_FLASH_ATTR UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num)
{
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_STOP_BIT_NUM, bit_num, UART_STOP_BIT_NUM_S);
}
void ICACHE_FLASH_ATTR UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask)
{
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK);
SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask);
}
void ICACHE_FLASH_ATTR UART_SetParity(UARTn uart_no, UartParityMode Parity_mode)
{
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN);
if (Parity_mode == PARITY_NONE) {
} else {
SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN);
}
}
void ICACHE_FLASH_ATTR UART_SetBaudrate(UARTn uart_no, uint32 baud_rate)
{
uart_div_modify(uart_no, UART_CLK_FREQ / baud_rate);
}
void ICACHE_FLASH_ATTR UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh)
{
if (flow_ctrl & USART_HWFlow_RTS) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
SET_PERI_REG_BITS(UART_CONF1(uart_no), UART_RX_FLOW_THRHD, rx_thresh, UART_RX_FLOW_THRHD_S);
SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
} else {
CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
}
if (flow_ctrl & USART_HWFlow_CTS) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
} else {
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
}
}
void ICACHE_FLASH_ATTR UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us) //do not use if tx flow control enabled
{
uint32 t_s = system_get_time();
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)) {
if ((system_get_time() - t_s) > time_out_us) {
break;
}
system_soft_wdt_feed();
}
}
bool ICACHE_FLASH_ATTR UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us)
{
uint32 t_start = system_get_time();
uint8 tx_fifo_len;
while (1) {
tx_fifo_len = UART_TxQueLen(uart_no);
// TODO If using output circbuf, check if empty
if (tx_fifo_len == 0) {
return TRUE;
}
if (system_get_time() - t_start > time_out_us) {
return FALSE;
}
system_soft_wdt_feed();
}
}
void ICACHE_FLASH_ATTR UART_ResetFifo(UARTn uart_no)
{
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);
}
void ICACHE_FLASH_ATTR UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask)
{
WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
}
void ICACHE_FLASH_ATTR UART_SetIntrEna(UARTn uart_no, uint32 ena_mask)
{
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
}
LOCAL void u0_putc_crlf(char c)
{
UART_WriteCharCRLF(UART0, (u8)c, UART_TIMEOUT_US);
}
LOCAL void u1_putc_crlf(char c)
{
UART_WriteCharCRLF(UART1, (u8)c, UART_TIMEOUT_US);
}
void ICACHE_FLASH_ATTR UART_SetPrintPort(UARTn uart_no)
{
if (uart_no == UART0) {
os_install_putc1((void *)u0_putc_crlf);
} else {
os_install_putc1((void *)u1_putc_crlf);
}
}
// -------------- Custom UART functions -------------------------
// !!! write handlers are not ICACHE_FLASH_ATTR -> can be used in IRQ !!!
/**
* @brief Write a char to UART.
* @param uart_no
* @param c
* @param timeout_us - how long to max wait for space in FIFO.
* @return write success
*/
STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us)
{
if (timeout_us == 0) {
timeout_us = UART_TIMEOUT_US;
}
uint32 t_s = system_get_time();
while ((system_get_time() - t_s) < timeout_us) {
uint8 fifo_cnt = UART_TxQueLen(uart_no);
if (fifo_cnt < UART_TX_FULL_THRESH_VAL) {
WRITE_PERI_REG(UART_FIFO(uart_no), c);
return OK;
}
system_soft_wdt_feed();
}
return FAIL;
}
/**
* @brief Write a char to UART, translating LF to CRLF and discarding CR.
* @param uart_no
* @param c
* @param timeout_us - how long to max wait for space in FIFO.
* @return write success
*/
STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us)
{
STATUS st;
if (c == '\r') {
return OK;
} else if (c == '\n') {
st = UART_WriteChar(uart_no, '\r', timeout_us);
if (st != OK) return st;
st = UART_WriteChar(uart_no, '\n', timeout_us);
return st;
} else {
return UART_WriteChar(uart_no, c, timeout_us);
}
}
/**
* @brief Send a string to UART.
* @param uart_no
* @param str
* @param timeout_us - how long to max wait for space in FIFO.
* @return write success
*/
STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us)
{
while (*str) {
STATUS suc = UART_WriteChar(uart_no, (u8) * str++, timeout_us);
if (suc != OK) return suc;
}
return OK;
}
/**
* @brief Send a buffer
* @param uart_no
* @param buffer - buffer to send
* @param len - buffer size
* @param timeout_us - how long to max wait for space in FIFO.
* @return write success
*/
STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us)
{
for (size_t i = 0; i < len; i++) {
STATUS suc = UART_WriteChar(uart_no, (u8) * buffer++, timeout_us);
if (suc != OK) return suc;
}
return OK;
}
+201
View File
@@ -0,0 +1,201 @@
/**
* Low level UART peripheral support functions
*/
/*
* File : uart.h
* Copyright (C) 2013 - 2016, Espressif Systems
* Copyright (C) 2016, Ondřej Hruška (cleaning, modif.)
*
* 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
#include "uart_register.h"
#include "eagle_soc.h"
#include "c_types.h"
// ===========
// timeout for sending / receiving a char (default)
#define UART_TIMEOUT_US 5000
#define UART_TX_FULL_THRESH_VAL (UART_FIFO_LEN - 2) // if more than this many bytes in queue, don't write more
#define UART_TX_EMPTY_THRESH_VAL 16
// ===========
typedef enum {
UART0 = 0,
UART1 = 1
} UARTn;
typedef enum {
FIVE_BITS = 0x0,
SIX_BITS = 0x1,
SEVEN_BITS = 0x2,
EIGHT_BITS = 0x3
} UartBitsNum4Char;
typedef enum {
ONE_STOP_BIT = 0x1,
ONE_HALF_STOP_BIT = 0x2,
TWO_STOP_BIT = 0x3
} UartStopBitsNum;
typedef enum {
PARITY_NONE = 0x2,
PARITY_ODD = 1,
PARITY_EVEN = 0
} UartParityMode;
typedef enum {
PARITY_DIS = 0,
PARITY_EN = 1
} UartExistParity;
typedef enum {
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_460800 = 460800,
BIT_RATE_921600 = 921600,
BIT_RATE_1843200 = 1843200,
BIT_RATE_3686400 = 3686400,
} UartBautRate;
typedef enum {
NONE_CTRL,
HARDWARE_CTRL,
XON_XOFF_CTRL
} UartFlowCtrl;
typedef enum {
USART_HWFlow_None = 0x0,
USART_HWFlow_RTS = 0x1,
USART_HWFlow_CTS = 0x2,
USART_HWFlow_CTS_RTS = 0x3
} UART_HwFlowCtrl;
typedef enum {
EMPTY,
UNDER_WRITE,
WRITE_OVER
} RcvMsgBuffState;
typedef struct {
uint32 RcvBuffSize;
uint8 *pRcvMsgBuff;
uint8 *pWritePos;
uint8 *pReadPos;
uint8 TrigLvl; //JLU: may need to pad
RcvMsgBuffState BuffState;
} RcvMsgBuff;
typedef struct {
uint32 TrxBuffSize;
uint8 *pTrxBuff;
} TrxMsgBuff;
typedef enum {
BAUD_RATE_DET,
WAIT_SYNC_FRM,
SRCH_MSG_HEAD,
RCV_MSG_BODY,
RCV_ESC_CHAR,
} RcvMsgState;
typedef struct {
UartBautRate baut_rate;
UartBitsNum4Char data_bits;
UartExistParity exist_parity;
UartParityMode parity;
UartStopBitsNum stop_bits;
UartFlowCtrl flow_ctrl;
RcvMsgBuff rcv_buff;
TrxMsgBuff trx_buff;
RcvMsgState rcv_state;
int received;
int buff_uart_no; //indicate which uart use tx/rx buffer
} UartDevice;
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
//==============================================
// FIFO used count
#define UART_TxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT)
#define UART_RxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us);
STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us);
STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us);
STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us);
//==============================================
void UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len);
void UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num);
void UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask);
void UART_SetParity(UARTn uart_no, UartParityMode Parity_mode);
void UART_SetBaudrate(UARTn uart_no, uint32 baud_rate);
void UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh);
void UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us); //do not use if tx flow control enabled
void UART_ResetFifo(UARTn uart_no);
void UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask);
void UART_SetIntrEna(UARTn uart_no, uint32 ena_mask);
void UART_SetPrintPort(UARTn uart_no);
bool UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us);
//==============================================
#endif
+185
View File
@@ -0,0 +1,185 @@
//Stupid bit of code that does the bare minimum to make os_printf work.
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <esp8266.h>
#include "uart_driver.h"
#include "uart_handler.h"
// messy irq/task based UART handling below
static void uart0_rx_intr_handler(void *para);
static void uart_recvTask(os_event_t *events);
#define uart_recvTaskPrio 1
#define uart_recvTaskQueueLen 10
static os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen];
/** Clear the fifos */
void ICACHE_FLASH_ATTR clear_rxtx(int uart_no)
{
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);
}
/**
* @brief Configure UART 115200-8-N-1
* @param uart_no
*/
static void ICACHE_FLASH_ATTR my_uart_init(UARTn uart_no, uint32 baud)
{
UART_SetParity(uart_no, PARITY_NONE);
UART_SetStopBits(uart_no, ONE_STOP_BIT);
UART_SetWordLength(uart_no, EIGHT_BITS);
UART_SetBaudrate(uart_no, baud);
UART_ResetFifo(uart_no);
}
/** Configure basic UART func and pins */
void ICACHE_FLASH_ATTR UART_Init(uint32_t baud0, uint32_t baud1)
{
// U0TXD
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
// U0RXD
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
// U1TXD (GPIO2)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
// Configure the UART peripherals
my_uart_init(UART0, baud0); // main
my_uart_init(UART1, baud1); // debug (output only)
}
/** Configure Rx on UART0 */
void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void)
{
// Start the Rx reading task
system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen);
// set handler
ETS_UART_INTR_ATTACH((void *)uart0_rx_intr_handler, &(UartDev.rcv_buff)); // the buf will be used as an arg
// fifo threshold config
uint32_t conf = ((100 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
conf |= ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
// timeout config
conf |= ((0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
conf |= UART_RX_TOUT_EN; // enable timeout
WRITE_PERI_REG(UART_CONF1(UART0), conf);
// enable TOUT and ERR irqs
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);
/* clear interrupt flags */
WRITE_PERI_REG(UART_INT_CLR(UART0), 0xffff);
/* enable RX interrupts */
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_OVF_INT_ENA);
// Enable IRQ in Extensa
ETS_UART_INTR_ENABLE();
}
// ---- async receive stuff ----
void uart_rx_intr_disable(uint8 uart_no)
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
}
void uart_rx_intr_enable(uint8 uart_no)
{
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
}
/**
* @brief get number of bytes in UART tx fifo
* @param UART number
*/
#define UART_GetRxFifoCount(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
void ICACHE_FLASH_ATTR UART_PollRx(void)
{
uint8 fifo_len = UART_GetRxFifoCount(UART0);
for (uint8 idx = 0; idx < fifo_len; idx++) {
uint8 d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
UART_HandleRxByte(d_tmp);
}
}
static void ICACHE_FLASH_ATTR uart_recvTask(os_event_t *events)
{
if (events->sig == 0) {
UART_PollRx();
// clear irq flags
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
// enable rx irq again
uart_rx_intr_enable(UART0);
} else if (events->sig == 1) {
// ???
}
}
/******************************************************************************
* 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)
{
(void)para;
uint32_t status_reg = READ_PERI_REG(UART_INT_ST(UART0));
if (status_reg & UART_FRM_ERR_INT_ST) {
// Framing Error
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR);
}
if (status_reg & UART_RXFIFO_FULL_INT_ST) {
// RX fifo full
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
// run handler
system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
}
if (status_reg & UART_RXFIFO_TOUT_INT_ST) {
// Fifo timeout
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
// run handler
system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
}
if (status_reg & UART_TXFIFO_EMPTY_INT_ST) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
}
if (status_reg & UART_RXFIFO_OVF_INT_ST) {
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_OVF_INT_CLR);
}
}
+27
View File
@@ -0,0 +1,27 @@
/**
* UART init & async rx module.
*
* Call UART_Init(), UART_SetupAsyncReceiver() and
* define UART_HandleRxByte() somewhere in application code.
*
* Call UART_PollRx() to allow rx in a blocking handler.
*/
#ifndef UART_HANDLER_H
#define UART_HANDLER_H
#include <esp8266.h>
/** Configure basic UART func and pins */
void UART_Init(uint32_t baud0, uint32_t baud1);
/** Configure Rx on UART0 */
void UART_SetupAsyncReceiver(void);
/** User must provide this func for handling received bytes */
extern void UART_HandleRxByte(char c);
/** poll uart while waiting for something */
void UART_PollRx(void);
#endif
+48 -114
View File
@@ -7,84 +7,26 @@
* ----------------------------------------------------------------------------
*/
/*
This is example code for the esphttpd library. It's a small-ish demo showing off
the server, including WiFi connection management capabilities, some IO and
some pictures of cats.
*/
/**
* This is the ESP8266 Remote Terminal project main file.
*/
#include <esp8266.h>
#include "httpd.h"
#include <httpdespfs.h>
#include <cgiwebsocket.h>
#include <captdns.h>
#include <espfs.h>
#include <webpages-espfs.h>
#include "serial.h"
#include "io.h"
#include "httpdespfs.h"
#include "cgi.h"
#include "cgiwifi.h"
#include "cgiflash.h"
#include "stdout.h"
#include "auth.h"
#include "espfs.h"
#include "captdns.h"
#include "webpages-espfs.h"
#include "cgiwebsocket.h"
#include "cgi-test.h"
//The example can print out the heap use every 3 seconds. You can use this to catch memory leaks.
//#define SHOW_HEAP_USE
#define FIRMWARE_VERSION "0.1"
//Function that tells the authentication system what users/passwords live on the system.
//This is disabled in the default build; if you want to try it, enable the authBasic line in
//the builtInUrls below.
int myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) {
if (no==0) {
os_strcpy(user, "admin");
os_strcpy(pass, "s3cr3t");
return 1;
//Add more users this way. Check against incrementing no for each user added.
// } else if (no==1) {
// os_strcpy(user, "user1");
// os_strcpy(pass, "something");
// return 1;
}
return 0;
}
#define SHOW_HEAP_USE 1
static ETSTimer websockTimer;
//Broadcast the uptime in seconds every second over connected websockets
static void ICACHE_FLASH_ATTR websockTimerCb(void *arg) {
static int ctr=0;
char buff[128];
ctr++;
os_sprintf(buff, "Up for %d minutes %d seconds!\n", ctr/60, ctr%60);
cgiWebsockBroadcast("/websocket/ws.cgi", buff, os_strlen(buff), WEBSOCK_FLAG_NONE);
}
//On reception of a message, send "You sent: " plus whatever the other side sent
void myWebsocketRecv(Websock *ws, char *data, int len, int flags) {
int i;
char buff[128];
os_sprintf(buff, "You sent: ");
for (i=0; i<len; i++) buff[i+10]=data[i];
buff[i+10]=0;
cgiWebsocketSend(ws, buff, os_strlen(buff), WEBSOCK_FLAG_NONE);
}
//Websocket connected. Install reception handler and send welcome message.
void myWebsocketConnect(Websock *ws) {
ws->recvCb=myWebsocketRecv;
cgiWebsocketSend(ws, "Hi, Websocket!", 14, WEBSOCK_FLAG_NONE);
}
//On reception of a message, echo it back verbatim
void myEchoWebsocketRecv(Websock *ws, char *data, int len, int flags) {
os_printf("EchoWs: echo, len=%d\n", len);
cgiWebsocketSend(ws, data, len, flags);
}
//Echo websocket connected. Install reception handler.
void myEchoWebsocketConnect(Websock *ws) {
os_printf("EchoWs: connect\n");
ws->recvCb=myEchoWebsocketRecv;
// NOOP
}
@@ -108,47 +50,14 @@ CgiUploadFlashDef uploadParams={
#define INCLUDE_FLASH_FNS
#endif
/*
This is the main url->function dispatching data struct.
In short, it's a struct with various URLs plus their handlers. The handlers can
be 'standard' CGI functions you wrote, or 'special' CGIs requiring an argument.
They can also be auth-functions. An asterisk will match any url starting with
everything before the asterisks; "*" matches everything. The list will be
handled top-down, so make sure to put more specific rules above the more
general ones. Authorization things (like authBasic) act as a 'barrier' and
should be placed above the URLs they protect.
*/
/** Routes */
HttpdBuiltInUrl builtInUrls[]={
ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp8266.nonet"), // redirect func for the captive portal
ROUTE_REDIRECT("/", "/index.tpl"),
ROUTE_TPL("/led.tpl", tplLed),
ROUTE_TPL("/index.tpl", tplCounter),
ROUTE_CGI("/led.cgi", cgiLed),
#ifdef INCLUDE_FLASH_FNS
ROUTE_CGI_ARG("/flash/next", cgiGetFirmwareNext, &uploadParams),
ROUTE_CGI_ARG("/flash/upload", cgiUploadFirmware, &uploadParams),
#endif
ROUTE_CGI("/flash/reboot", cgiRebootFirmware),
// redirect func for the captive portal
ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp8266.nonet"),
//Routines to make the /wifi URL and everything beneath it work.
ROUTE_WS("/ws/update.cgi", myWebsocketConnect),
//Enable the line below to protect the WiFi configuration with an username/password combo.
// ROUTE_AUTH("/wifi/*", myPassFn),
ROUTE_REDIRECT("/wifi", "/wifi/wifi.tpl"),
ROUTE_REDIRECT("/wifi/", "/wifi/wifi.tpl"),
ROUTE_CGI("/wifi/wifiscan.cgi", cgiWiFiScan),
ROUTE_TPL("/wifi/wifi.tpl", tplWlan),
ROUTE_CGI("/wifi/connect.cgi", cgiWiFiConnect),
ROUTE_CGI("/wifi/connstatus.cgi", cgiWiFiConnStatus),
ROUTE_CGI("/wifi/setmode.cgi", cgiWiFiSetMode),
ROUTE_WS("/websocket/ws.cgi", myWebsocketConnect),
ROUTE_WS("/websocket/echo.cgi", myEchoWebsocketConnect),
ROUTE_REDIRECT("/test", "/test/index.html"),
ROUTE_REDIRECT("/test/", "/test/index.html"),
ROUTE_CGI("/test/test.cgi", cgiTestbed),
// TODO add funcs for WiFi management (when web UI is added)
ROUTE_FILESYSTEM(),
ROUTE_END(),
@@ -159,15 +68,28 @@ HttpdBuiltInUrl builtInUrls[]={
static ETSTimer prHeapTimer;
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) {
static int led = 0;
os_printf("Heap: %ld\n", (unsigned long)system_get_free_heap_size());
cgiWebsockBroadcast("/ws/update.cgi", "HELLO", 5, WEBSOCK_FLAG_NONE);
ioLed(led);
led = !led;
}
#endif
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
void user_init(void) {
stdoutInit();
ioInit();
serialInit();
banner("ESP8266 Remote Terminal");
banner_info("Version "FIRMWARE_VERSION", built "__DATE__" at "__TIME__);
dbg("!!! TODO (c) and GitHub link here !!!");
//stdoutInit();
captdnsInit();
ioInit();
// 0x40200000 is the base address for spi flash memory mapping, ESPFS_POS is the position
// where image is written in flash that is defined in Makefile.
@@ -176,18 +98,30 @@ void user_init(void) {
#else
espFsInit((void*)(webpages_espfs_start));
#endif
httpdInit(builtInUrls, 80);
#ifdef SHOW_HEAP_USE
os_timer_disarm(&prHeapTimer);
os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL);
os_timer_arm(&prHeapTimer, 3000, 1);
#endif
os_timer_disarm(&websockTimer);
os_timer_setfn(&websockTimer, websockTimerCb, NULL);
os_timer_arm(&websockTimer, 1000, 1);
os_printf("\nReady\n");
info("System ready!");
}
// ---- unused funcs removed from sdk to save space ---
void user_rf_pre_init() {
//Not needed, but some SDK versions want this defined.
}
// вызывается из phy_chip_v6.o
void ICACHE_FLASH_ATTR chip_v6_set_sense(void) {
// ret.n
}
// вызывается из phy_chip_v6.o
int ICACHE_FLASH_ATTR chip_v6_unset_chanfreq(void) {
return 0;
}