Commit a33e3a4a authored by Vowstar's avatar Vowstar
Browse files

Merge pull request #687 from DiUS/dev140

Major upgrade to SDK 1.4.0 & open LWIP
parents 093a8959 8fba0f47
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: user_main.c
*
* Description: entry file of user application
*
* Modification history:
* 2014/1/1, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#include "user_devicefind.h"
#include "user_webserver.h"
#if ESP_PLATFORM
#include "user_esp_platform.h"
#endif
void user_rf_pre_init(void)
{
}
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void user_init(void)
{
os_printf("SDK version:%s\n", system_get_sdk_version());
#if ESP_PLATFORM
/*Initialization of the peripheral drivers*/
/*For light demo , it is user_light_init();*/
/* Also check whether assigned ip addr by the router.If so, connect to ESP-server */
user_esp_platform_init();
#endif
/*Establish a udp socket to receive local device detect info.*/
/*Listen to the port 1025, as well as udp broadcast.
/*If receive a string of device_find_request, it rely its IP address and MAC.*/
user_devicefind_init();
/*Establish a TCP server for http(with JSON) POST or GET command to communicate with the device.*/
/*You can find the command in "2B-SDK-Espressif IoT Demo.pdf" to see the details.*/
/*the JSON command for curl is like:*/
/*3 Channel mode: curl -X POST -H "Content-Type:application/json" -d "{\"period\":1000,\"rgb\":{\"red\":16000,\"green\":16000,\"blue\":16000}}" http://192.168.4.1/config?command=light */
/*5 Channel mode: curl -X POST -H "Content-Type:application/json" -d "{\"period\":1000,\"rgb\":{\"red\":16000,\"green\":16000,\"blue\":16000,\"cwhite\":3000,\"wwhite\",3000}}" http://192.168.4.1/config?command=light */
#ifdef SERVER_SSL_ENABLE
user_webserver_init(SERVER_SSL_PORT);
#else
user_webserver_init(SERVER_PORT);
#endif
}
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: user_plug.c
*
* Description: plug demo's function realization
*
* Modification history:
* 2014/5/1, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
#include "mem.h"
#include "user_interface.h"
#include "user_plug.h"
#if PLUG_DEVICE
LOCAL struct plug_saved_param plug_param;
LOCAL struct keys_param keys;
LOCAL struct single_key_param *single_key[PLUG_KEY_NUM];
LOCAL os_timer_t link_led_timer;
LOCAL uint8 link_led_level = 0;
/******************************************************************************
* FunctionName : user_plug_get_status
* Description : get plug's status, 0x00 or 0x01
* Parameters : none
* Returns : uint8 - plug's status
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
user_plug_get_status(void)
{
return plug_param.status;
}
/******************************************************************************
* FunctionName : user_plug_set_status
* Description : set plug's status, 0x00 or 0x01
* Parameters : uint8 - status
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_plug_set_status(bool status)
{
if (status != plug_param.status) {
if (status > 1) {
os_printf("error status input!\n");
return;
}
plug_param.status = status;
PLUG_STATUS_OUTPUT(PLUG_RELAY_LED_IO_NUM, status);
}
}
/******************************************************************************
* FunctionName : user_plug_short_press
* Description : key's short press function, needed to be installed
* Parameters : none
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
user_plug_short_press(void)
{
user_plug_set_status((~plug_param.status) & 0x01);
spi_flash_erase_sector(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE);
spi_flash_write((PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,
(uint32 *)&plug_param, sizeof(struct plug_saved_param));
}
/******************************************************************************
* FunctionName : user_plug_long_press
* Description : key's long press function, needed to be installed
* Parameters : none
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
user_plug_long_press(void)
{
user_esp_platform_set_active(0);
system_restore();
system_restart();
}
LOCAL void ICACHE_FLASH_ATTR
user_link_led_init(void)
{
PIN_FUNC_SELECT(PLUG_LINK_LED_IO_MUX, PLUG_LINK_LED_IO_FUNC);
}
void ICACHE_FLASH_ATTR
user_link_led_output(uint8 level)
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(PLUG_LINK_LED_IO_NUM), level);
}
LOCAL void ICACHE_FLASH_ATTR
user_link_led_timer_cb(void)
{
link_led_level = (~link_led_level) & 0x01;
GPIO_OUTPUT_SET(GPIO_ID_PIN(PLUG_LINK_LED_IO_NUM), link_led_level);
}
void ICACHE_FLASH_ATTR
user_link_led_timer_init(void)
{
os_timer_disarm(&link_led_timer);
os_timer_setfn(&link_led_timer, (os_timer_func_t *)user_link_led_timer_cb, NULL);
os_timer_arm(&link_led_timer, 50, 1);
link_led_level = 0;
GPIO_OUTPUT_SET(GPIO_ID_PIN(PLUG_LINK_LED_IO_NUM), link_led_level);
}
void ICACHE_FLASH_ATTR
user_link_led_timer_done(void)
{
os_timer_disarm(&link_led_timer);
GPIO_OUTPUT_SET(GPIO_ID_PIN(PLUG_LINK_LED_IO_NUM), 0);
}
/******************************************************************************
* FunctionName : user_plug_init
* Description : init plug's key function and relay output
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_plug_init(void)
{
user_link_led_init();
wifi_status_led_install(PLUG_WIFI_LED_IO_NUM, PLUG_WIFI_LED_IO_MUX, PLUG_WIFI_LED_IO_FUNC);
single_key[0] = key_init_single(PLUG_KEY_0_IO_NUM, PLUG_KEY_0_IO_MUX, PLUG_KEY_0_IO_FUNC,
user_plug_long_press, user_plug_short_press);
keys.key_num = PLUG_KEY_NUM;
keys.single_key = single_key;
key_init(&keys);
spi_flash_read((PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,
(uint32 *)&plug_param, sizeof(struct plug_saved_param));
PIN_FUNC_SELECT(PLUG_RELAY_LED_IO_MUX, PLUG_RELAY_LED_IO_FUNC);
// no used SPI Flash
if (plug_param.status == 0xff) {
plug_param.status = 1;
}
PLUG_STATUS_OUTPUT(PLUG_RELAY_LED_IO_NUM, plug_param.status);
}
#endif
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: user_humiture.c
*
* Description: humiture demo's function realization
*
* Modification history:
* 2014/5/1, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#if SENSOR_DEVICE
#include "user_sensor.h"
LOCAL struct keys_param keys;
LOCAL struct single_key_param *single_key[SENSOR_KEY_NUM];
LOCAL os_timer_t sensor_sleep_timer;
LOCAL os_timer_t link_led_timer;
LOCAL uint8 link_led_level = 0;
LOCAL uint32 link_start_time;
#if HUMITURE_SUB_DEVICE
#include "driver/i2c_master.h"
#define MVH3004_Addr 0x88
LOCAL uint8 humiture_data[4];
/******************************************************************************
* FunctionName : user_mvh3004_burst_read
* Description : burst read mvh3004's internal data
* Parameters : uint8 addr - mvh3004's address
* uint8 *pData - data point to put read data
* uint16 len - read length
* Returns : bool - true or false
*******************************************************************************/
LOCAL bool ICACHE_FLASH_ATTR
user_mvh3004_burst_read(uint8 addr, uint8 *pData, uint16 len)
{
uint8 ack;
uint16 i;
i2c_master_start();
i2c_master_writeByte(addr);
ack = i2c_master_getAck();
if (ack) {
os_printf("addr not ack when tx write cmd \n");
i2c_master_stop();
return false;
}
i2c_master_stop();
i2c_master_wait(40000);
i2c_master_start();
i2c_master_writeByte(addr + 1);
ack = i2c_master_getAck();
if (ack) {
os_printf("addr not ack when tx write cmd \n");
i2c_master_stop();
return false;
}
for (i = 0; i < len; i++) {
pData[i] = i2c_master_readByte();
i2c_master_setAck((i == (len - 1)) ? 1 : 0);
}
i2c_master_stop();
return true;
}
/******************************************************************************
* FunctionName : user_mvh3004_read_th
* Description : read mvh3004's humiture data
* Parameters : uint8 *data - where data to put
* Returns : bool - ture or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR
user_mvh3004_read_th(uint8 *data)
{
return user_mvh3004_burst_read(MVH3004_Addr, data, 4);
}
/******************************************************************************
* FunctionName : user_mvh3004_init
* Description : init mvh3004, mainly i2c master gpio
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_mvh3004_init(void)
{
i2c_master_gpio_init();
}
uint8 *ICACHE_FLASH_ATTR
user_mvh3004_get_poweron_th(void)
{
return humiture_data;
}
#endif
/******************************************************************************
* FunctionName : user_humiture_long_press
* Description : humiture key's function, needed to be installed
* Parameters : none
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
user_sensor_long_press(void)
{
user_esp_platform_set_active(0);
system_restore();
system_restart();
}
LOCAL void ICACHE_FLASH_ATTR
user_link_led_init(void)
{
PIN_FUNC_SELECT(SENSOR_LINK_LED_IO_MUX, SENSOR_LINK_LED_IO_FUNC);
PIN_FUNC_SELECT(SENSOR_UNUSED_LED_IO_MUX, SENSOR_UNUSED_LED_IO_FUNC);
GPIO_OUTPUT_SET(GPIO_ID_PIN(SENSOR_UNUSED_LED_IO_NUM), 0);
}
void ICACHE_FLASH_ATTR
user_link_led_output(uint8 level)
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(SENSOR_LINK_LED_IO_NUM), level);
}
LOCAL void ICACHE_FLASH_ATTR
user_link_led_timer_cb(void)
{
link_led_level = (~link_led_level) & 0x01;
GPIO_OUTPUT_SET(GPIO_ID_PIN(SENSOR_LINK_LED_IO_NUM), link_led_level);
}
void ICACHE_FLASH_ATTR
user_link_led_timer_init(void)
{
link_start_time = system_get_time();
os_timer_disarm(&link_led_timer);
os_timer_setfn(&link_led_timer, (os_timer_func_t *)user_link_led_timer_cb, NULL);
os_timer_arm(&link_led_timer, 50, 1);
link_led_level = 0;
GPIO_OUTPUT_SET(GPIO_ID_PIN(SENSOR_LINK_LED_IO_NUM), link_led_level);
}
void ICACHE_FLASH_ATTR
user_link_led_timer_done(void)
{
os_timer_disarm(&link_led_timer);
GPIO_OUTPUT_SET(GPIO_ID_PIN(SENSOR_LINK_LED_IO_NUM), 0);
}
void ICACHE_FLASH_ATTR
user_sensor_deep_sleep_enter(void)
{
system_deep_sleep(SENSOR_DEEP_SLEEP_TIME > link_start_time \
? SENSOR_DEEP_SLEEP_TIME - link_start_time : 30000000);
}
void ICACHE_FLASH_ATTR
user_sensor_deep_sleep_disable(void)
{
os_timer_disarm(&sensor_sleep_timer);
}
void ICACHE_FLASH_ATTR
user_sensor_deep_sleep_init(uint32 time)
{
os_timer_disarm(&sensor_sleep_timer);
os_timer_setfn(&sensor_sleep_timer, (os_timer_func_t *)user_sensor_deep_sleep_enter, NULL);
os_timer_arm(&sensor_sleep_timer, time, 0);
}
/******************************************************************************
* FunctionName : user_humiture_init
* Description : init humiture function, include key and mvh3004
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_sensor_init(uint8 active)
{
user_link_led_init();
wifi_status_led_install(SENSOR_WIFI_LED_IO_NUM, SENSOR_WIFI_LED_IO_MUX, SENSOR_WIFI_LED_IO_FUNC);
if (wifi_get_opmode() != SOFTAP_MODE) {
single_key[0] = key_init_single(SENSOR_KEY_IO_NUM, SENSOR_KEY_IO_MUX, SENSOR_KEY_IO_FUNC,
user_sensor_long_press, NULL);
keys.key_num = SENSOR_KEY_NUM;
keys.single_key = single_key;
key_init(&keys);
if (GPIO_INPUT_GET(GPIO_ID_PIN(SENSOR_KEY_IO_NUM)) == 0) {
user_sensor_long_press();
}
}
#if HUMITURE_SUB_DEVICE
user_mvh3004_init();
user_mvh3004_read_th(humiture_data);
#endif
#ifdef SENSOR_DEEP_SLEEP
if (wifi_get_opmode() != STATIONAP_MODE) {
if (active == 1) {
user_sensor_deep_sleep_init(SENSOR_DEEP_SLEEP_TIME / 1000 );
} else {
user_sensor_deep_sleep_init(SENSOR_DEEP_SLEEP_TIME / 1000 / 3 * 2);
}
}
#endif
}
#endif
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: user_webserver.c
*
* Description: The web server mode configration.
* Check your hardware connection with the host while use this mode.
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"
#include "user_iot_version.h"
#include "espconn.h"
#include "user_json.h"
#include "user_webserver.h"
#include "upgrade.h"
#if ESP_PLATFORM
#include "user_esp_platform.h"
#endif
#ifdef SERVER_SSL_ENABLE
#include "ssl/cert.h"
#include "ssl/private_key.h"
#endif
#if LIGHT_DEVICE
#include "user_light.h"
#endif
LOCAL struct station_config *sta_conf;
LOCAL struct softap_config *ap_conf;
//LOCAL struct secrty_server_info *sec_server;
//LOCAL struct upgrade_server_info *server;
//struct lewei_login_info *login_info;
LOCAL scaninfo *pscaninfo;
struct bss_info *bss;
struct bss_info *bss_temp;
struct bss_info *bss_head;
extern u16 scannum;
LOCAL uint32 PostCmdNeeRsp = 1;
uint8 upgrade_lock = 0;
LOCAL os_timer_t app_upgrade_10s;
LOCAL os_timer_t upgrade_check_timer;
/******************************************************************************
* FunctionName : device_get
* Description : set up the device information parmer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
device_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
if (os_strncmp(path, "manufacture", 11) == 0) {
jsontree_write_string(js_ctx, "Espressif Systems");
} else if (os_strncmp(path, "product", 7) == 0) {
#if SENSOR_DEVICE
#if HUMITURE_SUB_DEVICE
jsontree_write_string(js_ctx, "Humiture");
#elif FLAMMABLE_GAS_SUB_DEVICE
jsontree_write_string(js_ctx, "Flammable Gas");
#endif
#endif
#if PLUG_DEVICE
jsontree_write_string(js_ctx, "Plug");
#endif
#if LIGHT_DEVICE
jsontree_write_string(js_ctx, "Light");
#endif
}
return 0;
}
LOCAL struct jsontree_callback device_callback =
JSONTREE_CALLBACK(device_get, NULL);
/******************************************************************************
* FunctionName : userbin_get
* Description : get up the user bin paramer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
userbin_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
char string[32];
if (os_strncmp(path, "status", 8) == 0) {
os_sprintf(string, "200");
} else if (os_strncmp(path, "user_bin", 8) == 0) {
if (system_upgrade_userbin_check() == 0x00) {
os_sprintf(string, "user1.bin");
} else if (system_upgrade_userbin_check() == 0x01) {
os_sprintf(string, "user2.bin");
} else{
return 0;
}
}
jsontree_write_string(js_ctx, string);
return 0;
}
LOCAL struct jsontree_callback userbin_callback =
JSONTREE_CALLBACK(userbin_get, NULL);
JSONTREE_OBJECT(userbin_tree,
JSONTREE_PAIR("status", &userbin_callback),
JSONTREE_PAIR("user_bin", &userbin_callback));
JSONTREE_OBJECT(userinfo_tree,JSONTREE_PAIR("user_info",&userbin_tree));
/******************************************************************************
* FunctionName : version_get
* Description : set up the device version paramer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
version_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
char string[32];
if (os_strncmp(path, "hardware", 8) == 0) {
#if SENSOR_DEVICE
os_sprintf(string, "0.3");
#else
os_sprintf(string, "0.1");
#endif
} else if (os_strncmp(path, "sdk_version", 11) == 0) {
os_sprintf(string, "%s", system_get_sdk_version());
} else if (os_strncmp(path, "iot_version", 11) == 0) {
os_sprintf(string,"%s%d.%d.%dt%d(%s)",VERSION_TYPE,IOT_VERSION_MAJOR,\
IOT_VERSION_MINOR,IOT_VERSION_REVISION,device_type,UPGRADE_FALG);
}
jsontree_write_string(js_ctx, string);
return 0;
}
LOCAL struct jsontree_callback version_callback =
JSONTREE_CALLBACK(version_get, NULL);
JSONTREE_OBJECT(device_tree,
JSONTREE_PAIR("product", &device_callback),
JSONTREE_PAIR("manufacturer", &device_callback));
JSONTREE_OBJECT(version_tree,
JSONTREE_PAIR("hardware", &version_callback),
JSONTREE_PAIR("sdk_version", &version_callback),
JSONTREE_PAIR("iot_version", &version_callback),
);
JSONTREE_OBJECT(info_tree,
JSONTREE_PAIR("Version", &version_tree),
JSONTREE_PAIR("Device", &device_tree));
JSONTREE_OBJECT(INFOTree,
JSONTREE_PAIR("info", &info_tree));
LOCAL int ICACHE_FLASH_ATTR
connect_status_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
if (os_strncmp(path, "status", 8) == 0) {
jsontree_write_int(js_ctx, user_esp_platform_get_connect_status());
}
return 0;
}
LOCAL struct jsontree_callback connect_status_callback =
JSONTREE_CALLBACK(connect_status_get, NULL);
JSONTREE_OBJECT(status_sub_tree,
JSONTREE_PAIR("status", &connect_status_callback));
JSONTREE_OBJECT(connect_status_tree,
JSONTREE_PAIR("Status", &status_sub_tree));
JSONTREE_OBJECT(con_status_tree,
JSONTREE_PAIR("info", &connect_status_tree));
#if PLUG_DEVICE
/******************************************************************************
* FunctionName : status_get
* Description : set up the device status as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
status_get(struct jsontree_context *js_ctx)
{
if (user_plug_get_status() == 1) {
jsontree_write_int(js_ctx, 1);
} else {
jsontree_write_int(js_ctx, 0);
}
return 0;
}
/******************************************************************************
* FunctionName : status_set
* Description : parse the device status parmer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* parser -- A pointer to a JSON parser state
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
status_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
{
int type;
while ((type = jsonparse_next(parser)) != 0) {
if (type == JSON_TYPE_PAIR_NAME) {
if (jsonparse_strcmp_value(parser, "status") == 0) {
uint8 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
user_plug_set_status(status);
}
}
}
return 0;
}
LOCAL struct jsontree_callback status_callback =
JSONTREE_CALLBACK(status_get, status_set);
JSONTREE_OBJECT(status_tree,
JSONTREE_PAIR("status", &status_callback));
JSONTREE_OBJECT(response_tree,
JSONTREE_PAIR("Response", &status_tree));
JSONTREE_OBJECT(StatusTree,
JSONTREE_PAIR("switch", &response_tree));
#endif
#if LIGHT_DEVICE
LOCAL int ICACHE_FLASH_ATTR
light_status_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
if (os_strncmp(path, "red", 3) == 0) {
jsontree_write_int(js_ctx, user_light_get_duty(LIGHT_RED));
} else if (os_strncmp(path, "green", 5) == 0) {
jsontree_write_int(js_ctx, user_light_get_duty(LIGHT_GREEN));
} else if (os_strncmp(path, "blue", 4) == 0) {
jsontree_write_int(js_ctx, user_light_get_duty(LIGHT_BLUE));
} else if (os_strncmp(path, "wwhite", 6) == 0) {
if(PWM_CHANNEL>LIGHT_WARM_WHITE){
jsontree_write_int(js_ctx, user_light_get_duty(LIGHT_WARM_WHITE));
}else{
jsontree_write_int(js_ctx, 0);
}
} else if (os_strncmp(path, "cwhite", 6) == 0) {
if(PWM_CHANNEL>LIGHT_COLD_WHITE){
jsontree_write_int(js_ctx, user_light_get_duty(LIGHT_COLD_WHITE));
}else{
jsontree_write_int(js_ctx, 0);
}
} else if (os_strncmp(path, "period", 6) == 0) {
jsontree_write_int(js_ctx, user_light_get_period());
}
return 0;
}
LOCAL int ICACHE_FLASH_ATTR
light_status_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
{
int type;
static uint32 r,g,b,cw,ww,period;
period = 1000;
cw=0;
ww=0;
extern uint8 light_sleep_flg;
while ((type = jsonparse_next(parser)) != 0) {
if (type == JSON_TYPE_PAIR_NAME) {
if (jsonparse_strcmp_value(parser, "red") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
r=status;
os_printf("R: %d \n",status);
//user_light_set_duty(status, LIGHT_RED);
//light_set_aim_r( r);
} else if (jsonparse_strcmp_value(parser, "green") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
g=status;
os_printf("G: %d \n",status);
//user_light_set_duty(status, LIGHT_GREEN);
//light_set_aim_g( g);
} else if (jsonparse_strcmp_value(parser, "blue") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
b=status;
os_printf("B: %d \n",status);
//user_light_set_duty(status, LIGHT_BLUE);
//set_aim_b( b);
} else if (jsonparse_strcmp_value(parser, "cwhite") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
cw=status;
os_printf("CW: %d \n",status);
//user_light_set_duty(status, LIGHT_BLUE);
//set_aim_b( b);
} else if (jsonparse_strcmp_value(parser, "wwhite") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
ww=status;
os_printf("WW: %d \n",status);
//user_light_set_duty(status, LIGHT_BLUE);
//set_aim_b( b);
} else if (jsonparse_strcmp_value(parser, "period") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
os_printf("PERIOD: %d \n",status);
period=status;
//user_light_set_period(status);
}else if (jsonparse_strcmp_value(parser, "response") == 0) {
uint32 status;
jsonparse_next(parser);
jsonparse_next(parser);
status = jsonparse_get_value_as_int(parser);
os_printf("rspneed: %d \n",status);
PostCmdNeeRsp = status;
}
}
}
if((r|g|b|ww|cw) == 0){
if(light_sleep_flg==0){
}
}else{
if(light_sleep_flg==1){
os_printf("modem sleep en\r\n");
wifi_set_sleep_type(MODEM_SLEEP_T);
light_sleep_flg =0;
}
}
light_set_aim(r,g,b,cw,ww,period);
return 0;
}
LOCAL struct jsontree_callback light_callback =
JSONTREE_CALLBACK(light_status_get, light_status_set);
JSONTREE_OBJECT(rgb_tree,
JSONTREE_PAIR("red", &light_callback),
JSONTREE_PAIR("green", &light_callback),
JSONTREE_PAIR("blue", &light_callback),
JSONTREE_PAIR("cwhite", &light_callback),
JSONTREE_PAIR("wwhite", &light_callback),
);
JSONTREE_OBJECT(sta_tree,
JSONTREE_PAIR("period", &light_callback),
JSONTREE_PAIR("rgb", &rgb_tree));
JSONTREE_OBJECT(PwmTree,
JSONTREE_PAIR("light", &sta_tree));
#endif
/******************************************************************************
* FunctionName : wifi_station_get
* Description : set up the station paramer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
wifi_station_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
struct ip_info ipconfig;
uint8 buf[20];
os_bzero(buf, sizeof(buf));
wifi_station_get_config(sta_conf);
wifi_get_ip_info(STATION_IF, &ipconfig);
if (os_strncmp(path, "ssid", 4) == 0) {
jsontree_write_string(js_ctx, sta_conf->ssid);
} else if (os_strncmp(path, "password", 8) == 0) {
jsontree_write_string(js_ctx, sta_conf->password);
} else if (os_strncmp(path, "ip", 2) == 0) {
os_sprintf(buf, IPSTR, IP2STR(&ipconfig.ip));
jsontree_write_string(js_ctx, buf);
} else if (os_strncmp(path, "mask", 4) == 0) {
os_sprintf(buf, IPSTR, IP2STR(&ipconfig.netmask));
jsontree_write_string(js_ctx, buf);
} else if (os_strncmp(path, "gw", 2) == 0) {
os_sprintf(buf, IPSTR, IP2STR(&ipconfig.gw));
jsontree_write_string(js_ctx, buf);
}
return 0;
}
/******************************************************************************
* FunctionName : wifi_station_set
* Description : parse the station parmer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* parser -- A pointer to a JSON parser state
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
wifi_station_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
{
int type;
uint8 station_tree;
while ((type = jsonparse_next(parser)) != 0) {
if (type == JSON_TYPE_PAIR_NAME) {
char buffer[64];
os_bzero(buffer, 64);
if (jsonparse_strcmp_value(parser, "Station") == 0) {
station_tree = 1;
} else if (jsonparse_strcmp_value(parser, "Softap") == 0) {
station_tree = 0;
}
if (station_tree) {
if (jsonparse_strcmp_value(parser, "ssid") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_memcpy(sta_conf->ssid, buffer, os_strlen(buffer));
} else if (jsonparse_strcmp_value(parser, "password") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_memcpy(sta_conf->password, buffer, os_strlen(buffer));
}
#if ESP_PLATFORM
else if (jsonparse_strcmp_value(parser, "token") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
user_esp_platform_set_token(buffer);
}
#endif
}
}
}
return 0;
}
LOCAL struct jsontree_callback wifi_station_callback =
JSONTREE_CALLBACK(wifi_station_get, wifi_station_set);
JSONTREE_OBJECT(get_station_config_tree,
JSONTREE_PAIR("ssid", &wifi_station_callback),
JSONTREE_PAIR("password", &wifi_station_callback));
JSONTREE_OBJECT(set_station_config_tree,
JSONTREE_PAIR("ssid", &wifi_station_callback),
JSONTREE_PAIR("password", &wifi_station_callback),
JSONTREE_PAIR("token", &wifi_station_callback));
JSONTREE_OBJECT(ip_tree,
JSONTREE_PAIR("ip", &wifi_station_callback),
JSONTREE_PAIR("mask", &wifi_station_callback),
JSONTREE_PAIR("gw", &wifi_station_callback));
JSONTREE_OBJECT(get_station_tree,
JSONTREE_PAIR("Connect_Station", &get_station_config_tree),
JSONTREE_PAIR("Ipinfo_Station", &ip_tree));
JSONTREE_OBJECT(set_station_tree,
JSONTREE_PAIR("Connect_Station", &set_station_config_tree));
//JSONTREE_OBJECT(get_wifi_station_info_tree,
// JSONTREE_PAIR("Station", &get_station_tree));
//JSONTREE_OBJECT(set_wifi_station_info_tree,
// JSONTREE_PAIR("station", &set_station_tree));
/******************************************************************************
* FunctionName : wifi_softap_get
* Description : set up the softap paramer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
wifi_softap_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
struct ip_info ipconfig;
uint8 buf[20];
os_bzero(buf, sizeof(buf));
wifi_softap_get_config(ap_conf);
wifi_get_ip_info(SOFTAP_IF, &ipconfig);
if (os_strncmp(path, "ssid", 4) == 0) {
jsontree_write_string(js_ctx, ap_conf->ssid);
} else if (os_strncmp(path, "password", 8) == 0) {
jsontree_write_string(js_ctx, ap_conf->password);
} else if (os_strncmp(path, "channel", 7) == 0) {
jsontree_write_int(js_ctx, ap_conf->channel);
} else if (os_strncmp(path, "authmode", 8) == 0) {
switch (ap_conf->authmode) {
case AUTH_OPEN:
jsontree_write_string(js_ctx, "OPEN");
break;
case AUTH_WEP:
jsontree_write_string(js_ctx, "WEP");
break;
case AUTH_WPA_PSK:
jsontree_write_string(js_ctx, "WPAPSK");
break;
case AUTH_WPA2_PSK:
jsontree_write_string(js_ctx, "WPA2PSK");
break;
case AUTH_WPA_WPA2_PSK:
jsontree_write_string(js_ctx, "WPAPSK/WPA2PSK");
break;
default :
jsontree_write_int(js_ctx, ap_conf->authmode);
break;
}
} else if (os_strncmp(path, "ip", 2) == 0) {
os_sprintf(buf, IPSTR, IP2STR(&ipconfig.ip));
jsontree_write_string(js_ctx, buf);
} else if (os_strncmp(path, "mask", 4) == 0) {
os_sprintf(buf, IPSTR, IP2STR(&ipconfig.netmask));
jsontree_write_string(js_ctx, buf);
} else if (os_strncmp(path, "gw", 2) == 0) {
os_sprintf(buf, IPSTR, IP2STR(&ipconfig.gw));
jsontree_write_string(js_ctx, buf);
}
return 0;
}
/******************************************************************************
* FunctionName : wifi_softap_set
* Description : parse the softap parmer as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* parser -- A pointer to a JSON parser state
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
wifi_softap_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
{
int type;
uint8 softap_tree;
while ((type = jsonparse_next(parser)) != 0) {
if (type == JSON_TYPE_PAIR_NAME) {
char buffer[64];
os_bzero(buffer, 64);
if (jsonparse_strcmp_value(parser, "Station") == 0) {
softap_tree = 0;
} else if (jsonparse_strcmp_value(parser, "Softap") == 0) {
softap_tree = 1;
}
if (softap_tree) {
if (jsonparse_strcmp_value(parser, "authmode") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
// other mode will be supported later...
if (os_strcmp(buffer, "OPEN") == 0) {
ap_conf->authmode = AUTH_OPEN;
} else if (os_strcmp(buffer, "WPAPSK") == 0) {
ap_conf->authmode = AUTH_WPA_PSK;
os_printf("%d %s\n", ap_conf->authmode, buffer);
} else if (os_strcmp(buffer, "WPA2PSK") == 0) {
ap_conf->authmode = AUTH_WPA2_PSK;
} else if (os_strcmp(buffer, "WPAPSK/WPA2PSK") == 0) {
ap_conf->authmode = AUTH_WPA_WPA2_PSK;
} else {
ap_conf->authmode = AUTH_OPEN;
return 0;
}
}
if (jsonparse_strcmp_value(parser, "channel") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
ap_conf->channel = jsonparse_get_value_as_int(parser);
} else if (jsonparse_strcmp_value(parser, "ssid") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_memcpy(ap_conf->ssid, buffer, os_strlen(buffer));
} else if (jsonparse_strcmp_value(parser, "password") == 0) {
jsonparse_next(parser);
jsonparse_next(parser);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_memcpy(ap_conf->password, buffer, os_strlen(buffer));
}
}
}
}
return 0;
}
LOCAL struct jsontree_callback wifi_softap_callback =
JSONTREE_CALLBACK(wifi_softap_get, wifi_softap_set);
JSONTREE_OBJECT(softap_config_tree,
JSONTREE_PAIR("authmode", &wifi_softap_callback),
JSONTREE_PAIR("channel", &wifi_softap_callback),
JSONTREE_PAIR("ssid", &wifi_softap_callback),
JSONTREE_PAIR("password", &wifi_softap_callback));
JSONTREE_OBJECT(softap_ip_tree,
JSONTREE_PAIR("ip", &wifi_softap_callback),
JSONTREE_PAIR("mask", &wifi_softap_callback),
JSONTREE_PAIR("gw", &wifi_softap_callback));
JSONTREE_OBJECT(get_softap_tree,
JSONTREE_PAIR("Connect_Softap", &softap_config_tree),
JSONTREE_PAIR("Ipinfo_Softap", &softap_ip_tree));
JSONTREE_OBJECT(set_softap_tree,
JSONTREE_PAIR("Ipinfo_Softap", &softap_config_tree));
JSONTREE_OBJECT(get_wifi_tree,
JSONTREE_PAIR("Station", &get_station_tree),
JSONTREE_PAIR("Softap", &get_softap_tree));
JSONTREE_OBJECT(set_wifi_tree,
JSONTREE_PAIR("Station", &set_station_tree),
JSONTREE_PAIR("Softap", &set_softap_tree));
JSONTREE_OBJECT(wifi_response_tree,
JSONTREE_PAIR("Response", &get_wifi_tree));
JSONTREE_OBJECT(wifi_request_tree,
JSONTREE_PAIR("Request", &set_wifi_tree));
JSONTREE_OBJECT(wifi_info_tree,
JSONTREE_PAIR("wifi", &wifi_response_tree));
JSONTREE_OBJECT(wifi_req_tree,
JSONTREE_PAIR("wifi", &wifi_request_tree));
/******************************************************************************
* FunctionName : scan_get
* Description : set up the scan data as a JSON format
* Parameters : js_ctx -- A pointer to a JSON set up
* Returns : result
*******************************************************************************/
LOCAL int ICACHE_FLASH_ATTR
scan_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
// STAILQ_HEAD(, bss_info) *pbss = scanarg;
// LOCAL struct bss_info *bss;
if (os_strncmp(path, "TotalPage", 9) == 0) {
jsontree_write_int(js_ctx, pscaninfo->totalpage);
} else if (os_strncmp(path, "PageNum", 7) == 0) {
jsontree_write_int(js_ctx, pscaninfo->pagenum);
} else if (os_strncmp(path, "bssid", 5) == 0) {
if( bss == NULL )
bss = bss_head;
u8 buffer[32];
//if (bss != NULL){
os_memset(buffer, 0, sizeof(buffer));
os_sprintf(buffer, MACSTR, MAC2STR(bss->bssid));
jsontree_write_string(js_ctx, buffer);
//}
} else if (os_strncmp(path, "ssid", 4) == 0) {
//if (bss != NULL)
jsontree_write_string(js_ctx, bss->ssid);
} else if (os_strncmp(path, "rssi", 4) == 0) {
//if (bss != NULL)
jsontree_write_int(js_ctx, -(bss->rssi));
} else if (os_strncmp(path, "channel", 7) == 0) {
//if (bss != NULL)
jsontree_write_int(js_ctx, bss->channel);
} else if (os_strncmp(path, "authmode", 8) == 0) {
//if (bss != NULL){
switch (bss->authmode) {
case AUTH_OPEN:
jsontree_write_string(js_ctx, "OPEN");
break;
case AUTH_WEP:
jsontree_write_string(js_ctx, "WEP");
break;
case AUTH_WPA_PSK:
jsontree_write_string(js_ctx, "WPAPSK");
break;
case AUTH_WPA2_PSK:
jsontree_write_string(js_ctx, "WPA2PSK");
break;
case AUTH_WPA_WPA2_PSK:
jsontree_write_string(js_ctx, "WPAPSK/WPA2PSK");
break;
default :
jsontree_write_int(js_ctx, bss->authmode);
break;
}
bss = STAILQ_NEXT(bss, next);
// os_free(bss);
//}
}
return 0;
}
LOCAL struct jsontree_callback scan_callback =
JSONTREE_CALLBACK(scan_get, NULL);
JSONTREE_OBJECT(scaninfo_tree,
JSONTREE_PAIR("bssid", &scan_callback),
JSONTREE_PAIR("ssid", &scan_callback),
JSONTREE_PAIR("rssi", &scan_callback),
JSONTREE_PAIR("channel", &scan_callback),
JSONTREE_PAIR("authmode", &scan_callback));
JSONTREE_ARRAY(scanrslt_tree,
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree),
JSONTREE_PAIR_ARRAY(&scaninfo_tree));
JSONTREE_OBJECT(scantree,
JSONTREE_PAIR("TotalPage", &scan_callback),
JSONTREE_PAIR("PageNum", &scan_callback),
JSONTREE_PAIR("ScanResult", &scanrslt_tree));
JSONTREE_OBJECT(scanres_tree,
JSONTREE_PAIR("Response", &scantree));
JSONTREE_OBJECT(scan_tree,
JSONTREE_PAIR("scan", &scanres_tree));
/******************************************************************************
* FunctionName : parse_url
* Description : parse the received data from the server
* Parameters : precv -- the received data
* purl_frame -- the result of parsing the url
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
parse_url(char *precv, URL_Frame *purl_frame)
{
char *str = NULL;
uint8 length = 0;
char *pbuffer = NULL;
char *pbufer = NULL;
if (purl_frame == NULL || precv == NULL) {
return;
}
pbuffer = (char *)os_strstr(precv, "Host:");
if (pbuffer != NULL) {
length = pbuffer - precv;
pbufer = (char *)os_zalloc(length + 1);
pbuffer = pbufer;
os_memcpy(pbuffer, precv, length);
os_memset(purl_frame->pSelect, 0, URLSize);
os_memset(purl_frame->pCommand, 0, URLSize);
os_memset(purl_frame->pFilename, 0, URLSize);
if (os_strncmp(pbuffer, "GET ", 4) == 0) {
purl_frame->Type = GET;
pbuffer += 4;
} else if (os_strncmp(pbuffer, "POST ", 5) == 0) {
purl_frame->Type = POST;
pbuffer += 5;
}
pbuffer ++;
str = (char *)os_strstr(pbuffer, "?");
if (str != NULL) {
length = str - pbuffer;
os_memcpy(purl_frame->pSelect, pbuffer, length);
str ++;
pbuffer = (char *)os_strstr(str, "=");
if (pbuffer != NULL) {
length = pbuffer - str;
os_memcpy(purl_frame->pCommand, str, length);
pbuffer ++;
str = (char *)os_strstr(pbuffer, "&");
if (str != NULL) {
length = str - pbuffer;
os_memcpy(purl_frame->pFilename, pbuffer, length);
} else {
str = (char *)os_strstr(pbuffer, " HTTP");
if (str != NULL) {
length = str - pbuffer;
os_memcpy(purl_frame->pFilename, pbuffer, length);
}
}
}
}
os_free(pbufer);
} else {
return;
}
}
LOCAL char *precvbuffer;
static uint32 dat_sumlength = 0;
LOCAL bool ICACHE_FLASH_ATTR
save_data(char *precv, uint16 length)
{
bool flag = false;
char length_buf[10] = {0};
char *ptemp = NULL;
char *pdata = NULL;
uint16 headlength = 0;
static uint32 totallength = 0;
ptemp = (char *)os_strstr(precv, "\r\n\r\n");
if (ptemp != NULL) {
length -= ptemp - precv;
length -= 4;
totallength += length;
headlength = ptemp - precv + 4;
pdata = (char *)os_strstr(precv, "Content-Length: ");
if (pdata != NULL) {
pdata += 16;
precvbuffer = (char *)os_strstr(pdata, "\r\n");
if (precvbuffer != NULL) {
os_memcpy(length_buf, pdata, precvbuffer - pdata);
dat_sumlength = atoi(length_buf);
}
} else {
if (totallength != 0x00){
totallength = 0;
dat_sumlength = 0;
return false;
}
}
if ((dat_sumlength + headlength) >= 1024) {
precvbuffer = (char *)os_zalloc(headlength + 1);
os_memcpy(precvbuffer, precv, headlength + 1);
} else {
precvbuffer = (char *)os_zalloc(dat_sumlength + headlength + 1);
os_memcpy(precvbuffer, precv, os_strlen(precv));
}
} else {
if (precvbuffer != NULL) {
totallength += length;
os_memcpy(precvbuffer + os_strlen(precvbuffer), precv, length);
} else {
totallength = 0;
dat_sumlength = 0;
return false;
}
}
if (totallength == dat_sumlength) {
totallength = 0;
dat_sumlength = 0;
return true;
} else {
return false;
}
}
LOCAL bool ICACHE_FLASH_ATTR
check_data(char *precv, uint16 length)
{
//bool flag = true;
char length_buf[10] = {0};
char *ptemp = NULL;
char *pdata = NULL;
char *tmp_precvbuffer;
uint16 tmp_length = length;
uint32 tmp_totallength = 0;
ptemp = (char *)os_strstr(precv, "\r\n\r\n");
if (ptemp != NULL) {
tmp_length -= ptemp - precv;
tmp_length -= 4;
tmp_totallength += tmp_length;
pdata = (char *)os_strstr(precv, "Content-Length: ");
if (pdata != NULL){
pdata += 16;
tmp_precvbuffer = (char *)os_strstr(pdata, "\r\n");
if (tmp_precvbuffer != NULL){
os_memcpy(length_buf, pdata, tmp_precvbuffer - pdata);
dat_sumlength = atoi(length_buf);
os_printf("A_dat:%u,tot:%u,lenght:%u\n",dat_sumlength,tmp_totallength,tmp_length);
if(dat_sumlength != tmp_totallength){
return false;
}
}
}
}
return true;
}
LOCAL os_timer_t *restart_10ms;
LOCAL rst_parm *rstparm;
/******************************************************************************
* FunctionName : restart_10ms_cb
* Description : system restart or wifi reconnected after a certain time.
* Parameters : arg -- Additional argument to pass to the function
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
restart_10ms_cb(void *arg)
{
if (rstparm != NULL && rstparm->pespconn != NULL) {
switch (rstparm->parmtype) {
case WIFI:
//if (rstparm->pespconn->state == ESPCONN_CLOSE) {
if (sta_conf->ssid[0] != 0x00) {
wifi_station_set_config(sta_conf);
wifi_station_disconnect();
wifi_station_connect();
user_esp_platform_check_ip(1);
}
if (ap_conf->ssid[0] != 0x00) {
wifi_softap_set_config(ap_conf);
system_restart();
}
os_free(ap_conf);
ap_conf = NULL;
os_free(sta_conf);
sta_conf = NULL;
os_free(rstparm);
rstparm = NULL;
os_free(restart_10ms);
restart_10ms = NULL;
//} else {
// os_timer_arm(restart_10ms, 10, 0);
//}
break;
case DEEP_SLEEP:
case REBOOT:
if (rstparm->pespconn->state == ESPCONN_CLOSE) {
wifi_set_opmode(STATION_MODE);
if (rstparm->parmtype == DEEP_SLEEP) {
#if SENSOR_DEVICE
system_deep_sleep(SENSOR_DEEP_SLEEP_TIME);
#endif
}
} else {
os_timer_arm(restart_10ms, 10, 0);
}
break;
default:
break;
}
}
}
/******************************************************************************
* FunctionName : data_send
* Description : processing the data as http format and send to the client or server
* Parameters : arg -- argument to set for client or server
* responseOK -- true or false
* psend -- The send data
* Returns :
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
data_send(void *arg, bool responseOK, char *psend)
{
uint16 length = 0;
char *pbuf = NULL;
char httphead[256];
struct espconn *ptrespconn = arg;
os_memset(httphead, 0, 256);
if (responseOK) {
os_sprintf(httphead,
"HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",
psend ? os_strlen(psend) : 0);
if (psend) {
os_sprintf(httphead + os_strlen(httphead),
"Content-type: application/json\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n");
length = os_strlen(httphead) + os_strlen(psend);
pbuf = (char *)os_zalloc(length + 1);
os_memcpy(pbuf, httphead, os_strlen(httphead));
os_memcpy(pbuf + os_strlen(httphead), psend, os_strlen(psend));
} else {
os_sprintf(httphead + os_strlen(httphead), "\n");
length = os_strlen(httphead);
}
} else {
os_sprintf(httphead, "HTTP/1.0 400 BadRequest\r\n\
Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
length = os_strlen(httphead);
}
if (psend) {
#ifdef SERVER_SSL_ENABLE
espconn_secure_sent(ptrespconn, pbuf, length);
#else
espconn_sent(ptrespconn, pbuf, length);
#endif
} else {
#ifdef SERVER_SSL_ENABLE
espconn_secure_sent(ptrespconn, httphead, length);
#else
espconn_sent(ptrespconn, httphead, length);
#endif
}
if (pbuf) {
os_free(pbuf);
pbuf = NULL;
}
}
/******************************************************************************
* FunctionName : json_send
* Description : processing the data as json format and send to the client or server
* Parameters : arg -- argument to set for client or server
* ParmType -- json format type
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
json_send(void *arg, ParmType ParmType)
{
char *pbuf = NULL;
pbuf = (char *)os_zalloc(jsonSize);
struct espconn *ptrespconn = arg;
switch (ParmType) {
#if LIGHT_DEVICE
case LIGHT_STATUS:
json_ws_send((struct jsontree_value *)&PwmTree, "light", pbuf);
break;
#endif
#if PLUG_DEVICE
case SWITCH_STATUS:
json_ws_send((struct jsontree_value *)&StatusTree, "switch", pbuf);
break;
#endif
case INFOMATION:
json_ws_send((struct jsontree_value *)&INFOTree, "info", pbuf);
break;
case WIFI:
json_ws_send((struct jsontree_value *)&wifi_info_tree, "wifi", pbuf);
break;
case CONNECT_STATUS:
json_ws_send((struct jsontree_value *)&con_status_tree, "info", pbuf);
break;
case USER_BIN:
json_ws_send((struct jsontree_value *)&userinfo_tree, "user_info", pbuf);
break;
case SCAN: {
u8 i = 0;
u8 scancount = 0;
struct bss_info *bss = NULL;
// bss = STAILQ_FIRST(pscaninfo->pbss);
bss = bss_head;
if (bss == NULL) {
os_free(pscaninfo);
pscaninfo = NULL;
os_sprintf(pbuf, "{\n\"successful\": false,\n\"data\": null\n}");
} else {
do {
if (pscaninfo->page_sn == pscaninfo->pagenum) {
pscaninfo->page_sn = 0;
os_sprintf(pbuf, "{\n\"successful\": false,\n\"meessage\": \"repeated page\"\n}");
break;
}
scancount = scannum - (pscaninfo->pagenum - 1) * 8;
if (scancount >= 8) {
pscaninfo->data_cnt += 8;
pscaninfo->page_sn = pscaninfo->pagenum;
if (pscaninfo->data_cnt > scannum) {
pscaninfo->data_cnt -= 8;
os_sprintf(pbuf, "{\n\"successful\": false,\n\"meessage\": \"error page\"\n}");
break;
}
json_ws_send((struct jsontree_value *)&scan_tree, "scan", pbuf);
} else {
pscaninfo->data_cnt += scancount;
pscaninfo->page_sn = pscaninfo->pagenum;
if (pscaninfo->data_cnt > scannum) {
pscaninfo->data_cnt -= scancount;
os_sprintf(pbuf, "{\n\"successful\": false,\n\"meessage\": \"error page\"\n}");
break;
}
char *ptrscanbuf = (char *)os_zalloc(jsonSize);
char *pscanbuf = ptrscanbuf;
os_sprintf(pscanbuf, ",\n\"ScanResult\": [\n");
pscanbuf += os_strlen(pscanbuf);
for (i = 0; i < scancount; i ++) {
JSONTREE_OBJECT(page_tree,
JSONTREE_PAIR("page", &scaninfo_tree));
json_ws_send((struct jsontree_value *)&page_tree, "page", pscanbuf);
os_sprintf(pscanbuf + os_strlen(pscanbuf), ",\n");
pscanbuf += os_strlen(pscanbuf);
}
os_sprintf(pscanbuf - 2, "]\n");
JSONTREE_OBJECT(scantree,
JSONTREE_PAIR("TotalPage", &scan_callback),
JSONTREE_PAIR("PageNum", &scan_callback));
JSONTREE_OBJECT(scanres_tree,
JSONTREE_PAIR("Response", &scantree));
JSONTREE_OBJECT(scan_tree,
JSONTREE_PAIR("scan", &scanres_tree));
json_ws_send((struct jsontree_value *)&scan_tree, "scan", pbuf);
os_memcpy(pbuf + os_strlen(pbuf) - 4, ptrscanbuf, os_strlen(ptrscanbuf));
os_sprintf(pbuf + os_strlen(pbuf), "}\n}");
os_free(ptrscanbuf);
}
} while (0);
}
break;
}
default :
break;
}
data_send(ptrespconn, true, pbuf);
os_free(pbuf);
pbuf = NULL;
}
/******************************************************************************
* FunctionName : response_send
* Description : processing the send result
* Parameters : arg -- argument to set for client or server
* responseOK -- true or false
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
response_send(void *arg, bool responseOK)
{
struct espconn *ptrespconn = arg;
data_send(ptrespconn, responseOK, NULL);
}
/******************************************************************************
* FunctionName : json_scan_cb
* Description : processing the scan result
* Parameters : arg -- Additional argument to pass to the callback function
* status -- scan status
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR json_scan_cb(void *arg, STATUS status)
{
pscaninfo->pbss = arg;
if (scannum % 8 == 0) {
pscaninfo->totalpage = scannum / 8;
} else {
pscaninfo->totalpage = scannum / 8 + 1;
}
JSONTREE_OBJECT(totaltree,
JSONTREE_PAIR("TotalPage", &scan_callback));
JSONTREE_OBJECT(totalres_tree,
JSONTREE_PAIR("Response", &totaltree));
JSONTREE_OBJECT(total_tree,
JSONTREE_PAIR("total", &totalres_tree));
bss_temp = bss_head;
while(bss_temp !=NULL) {
bss_head = bss_temp->next.stqe_next;
os_free(bss_temp);
bss_temp = bss_head;
}
bss_head = NULL;
bss_temp = NULL;
bss = STAILQ_FIRST(pscaninfo->pbss);
while(bss != NULL) {
if(bss_temp == NULL){
bss_temp = (struct bss_info *)os_zalloc(sizeof(struct bss_info));
bss_head = bss_temp;
} else {
bss_temp->next.stqe_next = (struct bss_info *)os_zalloc(sizeof(struct bss_info));
bss_temp = bss_temp->next.stqe_next;
}
if(bss_temp == NULL) {
os_printf("malloc scan info failed\n");
break;
} else{
os_memcpy(bss_temp->bssid,bss->bssid,sizeof(bss->bssid));
os_memcpy(bss_temp->ssid,bss->ssid,sizeof(bss->ssid));
bss_temp->authmode = bss->authmode;
bss_temp->rssi = bss->rssi;
bss_temp->channel = bss->channel;
}
bss = STAILQ_NEXT(bss,next);
}
char *pbuf = NULL;
pbuf = (char *)os_zalloc(jsonSize);
json_ws_send((struct jsontree_value *)&total_tree, "total", pbuf);
data_send(pscaninfo->pespconn, true, pbuf);
os_free(pbuf);
}
void ICACHE_FLASH_ATTR
upgrade_check_func(void *arg)
{
struct espconn *ptrespconn = arg;
os_timer_disarm(&upgrade_check_timer);
if(system_upgrade_flag_check() == UPGRADE_FLAG_START) {
response_send(ptrespconn, false);
system_upgrade_deinit();
system_upgrade_flag_set(UPGRADE_FLAG_IDLE);
upgrade_lock = 0;
os_printf("local upgrade failed\n");
} else if( system_upgrade_flag_check() == UPGRADE_FLAG_FINISH ) {
os_printf("local upgrade success\n");
response_send(ptrespconn, true);
upgrade_lock = 0;
} else {
}
}
/******************************************************************************
* FunctionName : upgrade_deinit
* Description : disconnect the connection with the host
* Parameters : bin -- server number
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
LOCAL local_upgrade_deinit(void)
{
if (system_upgrade_flag_check() != UPGRADE_FLAG_START) {
os_printf("system upgrade deinit\n");
system_upgrade_deinit();
}
}
/******************************************************************************
* FunctionName : upgrade_download
* Description : Processing the upgrade data from the host
* Parameters : bin -- server number
* pusrdata -- The upgrade data (or NULL when the connection has been closed!)
* length -- The length of upgrade data
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
local_upgrade_download(void * arg,char *pusrdata, unsigned short length)
{
char *ptr = NULL;
char *ptmp2 = NULL;
char lengthbuffer[32];
static uint32 totallength = 0;
static uint32 sumlength = 0;
static uint32 erase_length = 0;
char A_buf[2] = {0xE9 ,0x03}; char B_buf[2] = {0xEA,0x04};
struct espconn *pespconn = arg;
if (totallength == 0 && (ptr = (char *)os_strstr(pusrdata, "\r\n\r\n")) != NULL &&
(ptr = (char *)os_strstr(pusrdata, "Content-Length")) != NULL) {
ptr = (char *)os_strstr(pusrdata, "Content-Length: ");
if (ptr != NULL) {
ptr += 16;
ptmp2 = (char *)os_strstr(ptr, "\r\n");
if (ptmp2 != NULL) {
os_memset(lengthbuffer, 0, sizeof(lengthbuffer));
os_memcpy(lengthbuffer, ptr, ptmp2 - ptr);
sumlength = atoi(lengthbuffer);
if (sumlength == 0) {
os_timer_disarm(&upgrade_check_timer);
os_timer_setfn(&upgrade_check_timer, (os_timer_func_t *)upgrade_check_func, pespconn);
os_timer_arm(&upgrade_check_timer, 10, 0);
return;
}
} else {
os_printf("sumlength failed\n");
}
} else {
os_printf("Content-Length: failed\n");
}
if (sumlength != 0) {
if (sumlength >= LIMIT_ERASE_SIZE){
system_upgrade_erase_flash(0xFFFF);
erase_length = sumlength - LIMIT_ERASE_SIZE;
} else {
system_upgrade_erase_flash(sumlength);
erase_length = 0;
}
}
ptr = (char *)os_strstr(pusrdata, "\r\n\r\n");
length -= ptr - pusrdata;
length -= 4;
totallength += length;
os_printf("upgrade file download start.\n");
system_upgrade(ptr + 4, length);
} else {
totallength += length;
if (erase_length >= LIMIT_ERASE_SIZE){
system_upgrade_erase_flash(0xFFFF);
erase_length -= LIMIT_ERASE_SIZE;
} else {
system_upgrade_erase_flash(erase_length);
erase_length = 0;
}
system_upgrade(pusrdata, length);
}
if (totallength == sumlength) {
os_printf("upgrade file download finished.\n");
system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
totallength = 0;
sumlength = 0;
upgrade_check_func(pespconn);
os_timer_disarm(&app_upgrade_10s);
os_timer_setfn(&app_upgrade_10s, (os_timer_func_t *)local_upgrade_deinit, NULL);
os_timer_arm(&app_upgrade_10s, 10, 0);
}
}
/******************************************************************************
* FunctionName : webserver_recv
* Description : Processing the received data from the server
* Parameters : arg -- Additional argument to pass to the callback function
* pusrdata -- The received data (or NULL when the connection has been closed!)
* length -- The length of received data
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
webserver_recv(void *arg, char *pusrdata, unsigned short length)
{
URL_Frame *pURL_Frame = NULL;
char *pParseBuffer = NULL;
bool parse_flag = false;
struct espconn *ptrespconn = arg;
if(upgrade_lock == 0){
os_printf("len:%u\n",length);
if(check_data(pusrdata, length) == false)
{
os_printf("goto\n");
goto _temp_exit;
}
parse_flag = save_data(pusrdata, length);
if (parse_flag == false) {
response_send(ptrespconn, false);
}
// os_printf(precvbuffer);
pURL_Frame = (URL_Frame *)os_zalloc(sizeof(URL_Frame));
parse_url(precvbuffer, pURL_Frame);
switch (pURL_Frame->Type) {
case GET:
os_printf("We have a GET request.\n");
if (os_strcmp(pURL_Frame->pSelect, "client") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0) {
if (os_strcmp(pURL_Frame->pFilename, "info") == 0) {
json_send(ptrespconn, INFOMATION);
}
if (os_strcmp(pURL_Frame->pFilename, "status") == 0) {
json_send(ptrespconn, CONNECT_STATUS);
} else if (os_strcmp(pURL_Frame->pFilename, "scan") == 0) {
char *strstr = NULL;
strstr = (char *)os_strstr(pusrdata, "&");
if (strstr == NULL) {
if (pscaninfo == NULL) {
pscaninfo = (scaninfo *)os_zalloc(sizeof(scaninfo));
}
pscaninfo->pespconn = ptrespconn;
pscaninfo->pagenum = 0;
pscaninfo->page_sn = 0;
pscaninfo->data_cnt = 0;
wifi_station_scan(NULL, json_scan_cb);
} else {
strstr ++;
if (os_strncmp(strstr, "page", 4) == 0) {
if (pscaninfo != NULL) {
pscaninfo->pagenum = *(strstr + 5);
pscaninfo->pagenum -= 0x30;
if (pscaninfo->pagenum > pscaninfo->totalpage || pscaninfo->pagenum == 0) {
response_send(ptrespconn, false);
} else {
json_send(ptrespconn, SCAN);
}
} else {
response_send(ptrespconn, false);
}
} else if(os_strncmp(strstr, "finish", 6) == 0){
bss_temp = bss_head;
while(bss_temp != NULL) {
bss_head = bss_temp->next.stqe_next;
os_free(bss_temp);
bss_temp = bss_head;
}
bss_head = NULL;
bss_temp = NULL;
response_send(ptrespconn, true);
} else {
response_send(ptrespconn, false);
}
}
} else {
response_send(ptrespconn, false);
}
} else if (os_strcmp(pURL_Frame->pSelect, "config") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0) {
if (os_strcmp(pURL_Frame->pFilename, "wifi") == 0) {
ap_conf = (struct softap_config *)os_zalloc(sizeof(struct softap_config));
sta_conf = (struct station_config *)os_zalloc(sizeof(struct station_config));
json_send(ptrespconn, WIFI);
os_free(sta_conf);
os_free(ap_conf);
sta_conf = NULL;
ap_conf = NULL;
}
#if PLUG_DEVICE
else if (os_strcmp(pURL_Frame->pFilename, "switch") == 0) {
json_send(ptrespconn, SWITCH_STATUS);
}
#endif
#if LIGHT_DEVICE
else if (os_strcmp(pURL_Frame->pFilename, "light") == 0) {
json_send(ptrespconn, LIGHT_STATUS);
}
#endif
else if (os_strcmp(pURL_Frame->pFilename, "reboot") == 0) {
json_send(ptrespconn, REBOOT);
} else {
response_send(ptrespconn, false);
}
} else if (os_strcmp(pURL_Frame->pSelect, "upgrade") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0) {
if (os_strcmp(pURL_Frame->pFilename, "getuser") == 0) {
json_send(ptrespconn , USER_BIN);
}
} else {
response_send(ptrespconn, false);
}
break;
case POST:
os_printf("We have a POST request.\n");
pParseBuffer = (char *)os_strstr(precvbuffer, "\r\n\r\n");
if (pParseBuffer == NULL) {
break;
}
pParseBuffer += 4;
if (os_strcmp(pURL_Frame->pSelect, "config") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0) {
#if SENSOR_DEVICE
if (os_strcmp(pURL_Frame->pFilename, "sleep") == 0) {
#else
if (os_strcmp(pURL_Frame->pFilename, "reboot") == 0) {
#endif
if (pParseBuffer != NULL) {
if (restart_10ms != NULL) {
os_timer_disarm(restart_10ms);
}
if (rstparm == NULL) {
rstparm = (rst_parm *)os_zalloc(sizeof(rst_parm));
}
rstparm->pespconn = ptrespconn;
#if SENSOR_DEVICE
rstparm->parmtype = DEEP_SLEEP;
#else
rstparm->parmtype = REBOOT;
#endif
if (restart_10ms == NULL) {
restart_10ms = (os_timer_t *)os_malloc(sizeof(os_timer_t));
}
os_timer_setfn(restart_10ms, (os_timer_func_t *)restart_10ms_cb, NULL);
os_timer_arm(restart_10ms, 10, 0); // delay 10ms, then do
response_send(ptrespconn, true);
} else {
response_send(ptrespconn, false);
}
} else if (os_strcmp(pURL_Frame->pFilename, "wifi") == 0) {
if (pParseBuffer != NULL) {
struct jsontree_context js;
user_esp_platform_set_connect_status(DEVICE_CONNECTING);
if (restart_10ms != NULL) {
os_timer_disarm(restart_10ms);
}
if (ap_conf == NULL) {
ap_conf = (struct softap_config *)os_zalloc(sizeof(struct softap_config));
}
if (sta_conf == NULL) {
sta_conf = (struct station_config *)os_zalloc(sizeof(struct station_config));
}
jsontree_setup(&js, (struct jsontree_value *)&wifi_req_tree, json_putchar);
json_parse(&js, pParseBuffer);
if (rstparm == NULL) {
rstparm = (rst_parm *)os_zalloc(sizeof(rst_parm));
}
rstparm->pespconn = ptrespconn;
rstparm->parmtype = WIFI;
if (sta_conf->ssid[0] != 0x00 || ap_conf->ssid[0] != 0x00) {
ap_conf->ssid_hidden = 0;
ap_conf->max_connection = 4;
if (restart_10ms == NULL) {
restart_10ms = (os_timer_t *)os_malloc(sizeof(os_timer_t));
}
os_timer_disarm(restart_10ms);
os_timer_setfn(restart_10ms, (os_timer_func_t *)restart_10ms_cb, NULL);
os_timer_arm(restart_10ms, 10, 0); // delay 10ms, then do
} else {
os_free(ap_conf);
os_free(sta_conf);
os_free(rstparm);
sta_conf = NULL;
ap_conf = NULL;
rstparm =NULL;
}
response_send(ptrespconn, true);
} else {
response_send(ptrespconn, false);
}
}
#if PLUG_DEVICE
else if (os_strcmp(pURL_Frame->pFilename, "switch") == 0) {
if (pParseBuffer != NULL) {
struct jsontree_context js;
jsontree_setup(&js, (struct jsontree_value *)&StatusTree, json_putchar);
json_parse(&js, pParseBuffer);
response_send(ptrespconn, true);
} else {
response_send(ptrespconn, false);
}
}
#endif
#if LIGHT_DEVICE
else if (os_strcmp(pURL_Frame->pFilename, "light") == 0) {
if (pParseBuffer != NULL) {
struct jsontree_context js;
jsontree_setup(&js, (struct jsontree_value *)&PwmTree, json_putchar);
json_parse(&js, pParseBuffer);
os_printf("rsp1:%u\n",PostCmdNeeRsp);
if(PostCmdNeeRsp == 0)
PostCmdNeeRsp = 1;
else
response_send(ptrespconn, true);
} else {
response_send(ptrespconn, false);
}
}
else if (os_strcmp(pURL_Frame->pFilename, "reset") == 0) {
response_send(ptrespconn, true);
extern struct esp_platform_saved_param esp_param;
esp_param.activeflag = 0;
system_param_save_with_protect(ESP_PARAM_START_SEC, &esp_param, sizeof(esp_param));
system_restore();
system_restart();
}
#endif
else {
response_send(ptrespconn, false);
}
}
else if(os_strcmp(pURL_Frame->pSelect, "upgrade") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0){
if (os_strcmp(pURL_Frame->pFilename, "start") == 0){
response_send(ptrespconn, true);
os_printf("local upgrade start\n");
upgrade_lock = 1;
system_upgrade_init();
system_upgrade_flag_set(UPGRADE_FLAG_START);
os_timer_disarm(&upgrade_check_timer);
os_timer_setfn(&upgrade_check_timer, (os_timer_func_t *)upgrade_check_func, NULL);
os_timer_arm(&upgrade_check_timer, 120000, 0);
} else if (os_strcmp(pURL_Frame->pFilename, "reset") == 0) {
response_send(ptrespconn, true);
os_printf("local upgrade restart\n");
system_upgrade_reboot();
} else {
response_send(ptrespconn, false);
}
}else {
response_send(ptrespconn, false);
}
break;
}
if (precvbuffer != NULL){
os_free(precvbuffer);
precvbuffer = NULL;
}
os_free(pURL_Frame);
pURL_Frame = NULL;
_temp_exit:
;
}
else if(upgrade_lock == 1){
local_upgrade_download(ptrespconn,pusrdata, length);
if (precvbuffer != NULL){
os_free(precvbuffer);
precvbuffer = NULL;
}
os_free(pURL_Frame);
pURL_Frame = NULL;
}
}
/******************************************************************************
* FunctionName : webserver_recon
* Description : the connection has been err, reconnection
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
LOCAL ICACHE_FLASH_ATTR
void webserver_recon(void *arg, sint8 err)
{
struct espconn *pesp_conn = arg;
os_printf("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0],
pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port, err);
}
/******************************************************************************
* FunctionName : webserver_recon
* Description : the connection has been err, reconnection
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
LOCAL ICACHE_FLASH_ATTR
void webserver_discon(void *arg)
{
struct espconn *pesp_conn = arg;
os_printf("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0],
pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port);
}
/******************************************************************************
* FunctionName : user_accept_listen
* Description : server listened a connection successfully
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
webserver_listen(void *arg)
{
struct espconn *pesp_conn = arg;
espconn_regist_recvcb(pesp_conn, webserver_recv);
espconn_regist_reconcb(pesp_conn, webserver_recon);
espconn_regist_disconcb(pesp_conn, webserver_discon);
}
/******************************************************************************
* FunctionName : user_webserver_init
* Description : parameter initialize as a server
* Parameters : port -- server port
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_webserver_init(uint32 port)
{
LOCAL struct espconn esp_conn;
LOCAL esp_tcp esptcp;
esp_conn.type = ESPCONN_TCP;
esp_conn.state = ESPCONN_NONE;
esp_conn.proto.tcp = &esptcp;
esp_conn.proto.tcp->local_port = port;
espconn_regist_connectcb(&esp_conn, webserver_listen);
#ifdef SERVER_SSL_ENABLE
espconn_secure_set_default_certificate(default_certificate, default_certificate_len);
espconn_secure_set_default_private_key(default_private_key, default_private_key_len);
espconn_secure_accept(&esp_conn);
#else
espconn_accept(&esp_conn);
#endif
}
Notice: AT added some functions so it's larger than before, if you want to compile it, please compile it as 1024KB or larger flash in compilation STEP 5.
1compile options
(1) COMPILE
Possible value: gcc
Default value:
If not set, use xt-xcc by default.
(2) BOOT
Possible value: none/old/new
none: no need boot
old: use boot_v1.1
new: use boot_v1.2+
Default value: none
(3) APP
Possible value: 0/1/2
0: original mode, generate eagle.app.v6.flash.bin and eagle.app.v6.irom0text.bin
1: generate user1
2: generate user2
Default value: 0
(3) SPI_SPEED
Possible value: 20/26.7/40/80
Default value: 40
(4) SPI_MODE
Possible value: QIO/QOUT/DIO/DOUT
Default value: QIO
(4) SPI_SIZE
Possible value: 0/2/3/4/5/6
Default value: 0
For example:
make COMPILE=gcc BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=QIO SPI_SIZE_MAP=0
2You can also use gen_misc to make and generate specific bin you needed.
Linux: ./gen_misc.sh
Windows: gen_misc.bat
Follow the tips and steps.
\ No newline at end of file
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of object file images to be generated ()
# GEN_BINS - list of binaries to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
TARGET = eagle
#FLAVOR = release
FLAVOR = debug
#EXTRA_CCFLAGS += -u
ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
SPECIAL_MKTARGETS=$(APP_MKTARGETS)
SUBDIRS= \
user
ifdef AT_OPEN_SRC
SUBDIRS += \
at
endif
endif # } PDIR
APPDIR = .
LDDIR = ../ld
CCFLAGS += -Os
TARGET_LDFLAGS = \
-nostdlib \
-Wl,-EL \
--longcalls \
--text-section-literals
ifeq ($(FLAVOR),debug)
TARGET_LDFLAGS += -g -O2
endif
ifeq ($(FLAVOR),release)
TARGET_LDFLAGS += -g -O0
endif
COMPONENTS_eagle.app.v6 = \
user/libuser.a
ifdef AT_OPEN_SRC
COMPONENTS_eagle.app.v6 += \
at/libat.a
endif
LINKFLAGS_eagle.app.v6 = \
-L../lib \
-nostdlib \
-T$(LD_FILE) \
-Wl,--no-check-sections \
-u call_user_start \
-Wl,-static \
-Wl,--start-group \
-lc \
-lgcc \
-lhal \
-lphy \
-lpp \
-lnet80211 \
-llwip \
-lwpa \
-lmain \
-ljson \
-lupgrade \
-lsmartconfig \
$(DEP_LIBS_eagle.app.v6)
ifndef AT_OPEN_SRC
LINKFLAGS_eagle.app.v6 += \
-lat
endif
LINKFLAGS_eagle.app.v6 += \
-Wl,--end-group
DEPENDS_eagle.app.v6 = \
$(LD_FILE) \
$(LDDIR)/eagle.rom.addr.v6.ld
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#UNIVERSAL_TARGET_DEFINES = \
# Other potential configuration flags include:
# -DTXRX_TXBUF_DEBUG
# -DTXRX_RXBUF_DEBUG
# -DWLAN_CONFIG_CCX
CONFIGURATION_DEFINES = -DICACHE_FLASH
ifdef AT_OPEN_SRC
CONFIGURATION_DEFINES += \
-DAT_OPEN_SRC
endif
ifeq ($(APP),0)
else
CONFIGURATION_DEFINES += \
-DAT_UPGRADE_SUPPORT
endif
DEFINES += \
$(UNIVERSAL_TARGET_DEFINES) \
$(CONFIGURATION_DEFINES)
DDEFINES += \
$(UNIVERSAL_TARGET_DEFINES) \
$(CONFIGURATION_DEFINES)
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
.PHONY: FORCE
FORCE:
@echo off
echo gen_misc.bat version 20150511
echo .
echo Please follow below steps(1-5) to generate specific bin(s):
echo STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none)
set input=default
set /p input=enter(0/1/2, default 2):
if %input% equ 0 (
set boot=old
) else (
if %input% equ 1 (
set boot=new
) else (
set boot=none
)
)
echo boot mode: %boot%
echo.
echo STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)
set input=default
set /p input=enter (0/1/2, default 0):
if %input% equ 1 (
if %boot% equ none (
set app=0
echo choose no boot before
echo generate bin: eagle.flash.bin+eagle.irom0text.bin
) else (
set app=1
echo generate bin: user1.bin
)
) else (
if %input% equ 2 (
if %boot% equ none (
set app=0
echo choose no boot before
echo generate bin: eagle.flash.bin+eagle.irom0text.bin
) else (
set app=2
echo generate bin: user2.bin
)
) else (
if %boot% neq none (
set boot=none
echo ignore boot
)
set app=0
echo generate bin: eagle.flash.bin+eagle.irom0text.bin
))
echo.
echo STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)
set input=default
set /p input=enter (0/1/2/3, default 2):
if %input% equ 0 (
set spi_speed=20
) else (
if %input% equ 1 (
set spi_speed=26.7
) else (
if %input% equ 3 (
set spi_speed=80
) else (
set spi_speed=40
)))
echo spi speed: %spi_speed% MHz
echo.
echo STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)
set input=default
set /p input=enter (0/1/2/3, default 0):
if %input% equ 1 (
set spi_mode=QOUT
) else (
if %input% equ 2 (
set spi_mode=DIO
) else (
if %input% equ 3 (
set spi_mode=DOUT
) else (
set spi_mode=QIO
)))
echo spi mode: %spi_mode%
echo.
echo STEP 5: choose flash size and map
echo 0= 512KB( 256KB+ 256KB)
echo 2=1024KB( 512KB+ 512KB)
echo 3=2048KB( 512KB+ 512KB)
echo 4=4096KB( 512KB+ 512KB)
echo 5=2048KB(1024KB+1024KB)
echo 6=4096KB(1024KB+1024KB)
set input=default
set /p input=enter (0/1/2/3/4/5/6, default 0):
if %input% equ 2 (
set spi_size_map=2
echo spi size: 1024KB
echo spi ota map: 512KB + 512KB
) else (
if %input% equ 3 (
set spi_size_map=3
echo spi size: 2048KB
echo spi ota map: 512KB + 512KB
) else (
if %input% equ 4 (
set spi_size_map=4
echo spi size: 4096KB
echo spi ota map: 512KB + 512KB
) else (
if %input% equ 5 (
set spi_size_map=5
echo spi size: 2048KB
echo spi ota map: 1024KB + 1024KB
) else (
if %input% equ 6 (
set spi_size_map=6
echo spi size: 4096KB
echo spi ota map: 1024KB + 1024KB
) else (
set spi_size_map=0
echo spi size: 512KB
echo spi ota map: 256KB + 256KB
)
)
)
)
)
touch user/user_main.c
echo.
echo start...
echo.
make BOOT=%boot% APP=%app% SPI_SPEED=%spi_speed% SPI_MODE=%spi_mode% SPI_SIZE=%spi_size_map%
#!/bin/bash
echo "gen_misc.sh version 20150511"
echo ""
echo "Please follow below steps(1-5) to generate specific bin(s):"
echo "STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none)"
echo "enter(0/1/2, default 2):"
read input
if [ -z "$input" ]; then
boot=none
elif [ $input == 0 ]; then
boot=old
elif [ $input == 1 ]; then
boot=new
else
boot=none
fi
echo "boot mode: $boot"
echo ""
echo "STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)"
echo "enter (0/1/2, default 0):"
read input
if [ -z "$input" ]; then
if [ $boot != none ]; then
boot=none
echo "ignore boot"
fi
app=0
echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
elif [ $input == 1 ]; then
if [ $boot == none ]; then
app=0
echo "choose no boot before"
echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
else
app=1
echo "generate bin: user1.bin"
fi
elif [ $input == 2 ]; then
if [ $boot == none ]; then
app=0
echo "choose no boot before"
echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
else
app=2
echo "generate bin: user2.bin"
fi
else
if [ $boot != none ]; then
boot=none
echo "ignore boot"
fi
app=0
echo "generate bin: eagle.flash.bin+eagle.irom0text.bin"
fi
echo ""
echo "STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)"
echo "enter (0/1/2/3, default 2):"
read input
if [ -z "$input" ]; then
spi_speed=40
elif [ $input == 0 ]; then
spi_speed=20
elif [ $input == 1 ]; then
spi_speed=26.7
elif [ $input == 3 ]; then
spi_speed=80
else
spi_speed=40
fi
echo "spi speed: $spi_speed MHz"
echo ""
echo "STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)"
echo "enter (0/1/2/3, default 0):"
read input
if [ -z "$input" ]; then
spi_mode=QIO
elif [ $input == 1 ]; then
spi_mode=QOUT
elif [ $input == 2 ]; then
spi_mode=DIO
elif [ $input == 3 ]; then
spi_mode=DOUT
else
spi_mode=QIO
fi
echo "spi mode: $spi_mode"
echo ""
echo "STEP 5: choose spi size and map"
echo " 0= 512KB( 256KB+ 256KB)"
echo " 2=1024KB( 512KB+ 512KB)"
echo " 3=2048KB( 512KB+ 512KB)"
echo " 4=4096KB( 512KB+ 512KB)"
echo " 5=2048KB(1024KB+1024KB)"
echo " 6=4096KB(1024KB+1024KB)"
echo "enter (0/2/3/4/5/6, default 0):"
read input
if [ -z "$input" ]; then
spi_size_map=0
echo "spi size: 512KB"
echo "spi ota map: 256KB + 256KB"
elif [ $input == 2 ]; then
spi_size_map=2
echo "spi size: 1024KB"
echo "spi ota map: 512KB + 512KB"
elif [ $input == 3 ]; then
spi_size_map=3
echo "spi size: 2048KB"
echo "spi ota map: 512KB + 512KB"
elif [ $input == 4 ]; then
spi_size_map=4
echo "spi size: 4096KB"
echo "spi ota map: 512KB + 512KB"
elif [ $input == 5 ]; then
spi_size_map=5
echo "spi size: 2048KB"
echo "spi ota map: 1024KB + 1024KB"
elif [ $input == 6 ]; then
spi_size_map=6
echo "spi size: 4096KB"
echo "spi ota map: 1024KB + 1024KB"
else
spi_size_map=0
echo "spi size: 512KB"
echo "spi ota map: 256KB + 256KB"
fi
echo ""
touch user/user_main.c
echo ""
echo "start..."
echo ""
make COMPILE=gcc BOOT=$boot APP=$app SPI_SPEED=$spi_speed SPI_MODE=$spi_mode SPI_SIZE_MAP=$spi_size_map
#ifndef __USER_CONFIG_H__
#define __USER_CONFIG_H__
#define AT_CUSTOM_UPGRADE
#ifdef AT_CUSTOM_UPGRADE
#ifndef AT_UPGRADE_SUPPORT
#error "upgrade is not supported when eagle.flash.bin+eagle.irom0text.bin!!!"
#endif
#endif
#endif
......@@ -12,9 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libsslcrypto.a
GEN_LIBS = libuser.a
endif
......@@ -41,6 +39,7 @@ endif
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
INCLUDES += -I ../../include/ets
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
/******************************************************************************
* Copyright 2015-2018 Espressif Systems (Wuxi)
*
* FileName: user_main.c
*
* Description: entry file of user application
*
* Modification history:
* 2015/3/06, v1.0 create this file.
*******************************************************************************/
#include "c_types.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "osapi.h"
#include "upgrade.h"
#ifdef AT_UPGRADE_SUPPORT
#ifdef AT_CUSTOM_UPGRADE
#define UPGRADE_FRAME "{\"path\": \"/v1/messages/\", \"method\": \"POST\", \"meta\": {\"Authorization\": \"token %s\"},\
\"get\":{\"action\":\"%s\"},\"body\":{\"pre_rom_version\":\"%s\",\"rom_version\":\"%s\"}}\n"
#define pheadbuffer "Connection: keep-alive\r\n\
Cache-Control: no-cache\r\n\
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 \r\n\
Accept: */*\r\n\
Accept-Encoding: gzip,deflate\r\n\
Accept-Language: zh-CN,eb-US;q=0.8\r\n\r\n"
/**/
struct espconn *pespconn = NULL;
struct upgrade_server_info *upServer = NULL;
static os_timer_t at_delay_check;
static struct espconn *pTcpServer = NULL;
static ip_addr_t host_ip;
/******************************************************************************
* FunctionName : user_esp_platform_upgrade_cb
* Description : Processing the downloaded data from the server
* Parameters : pespconn -- the espconn used to connetion with the host
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
at_upDate_rsp(void *arg)
{
struct upgrade_server_info *server = arg;
if(server->upgrade_flag == true)
{
os_printf("device_upgrade_success\r\n");
at_response_ok();
system_upgrade_reboot();
}
else
{
os_printf("device_upgrade_failed\r\n");
at_response_error();
}
os_free(server->url);
server->url = NULL;
os_free(server);
server = NULL;
}
/**
* @brief Tcp client disconnect success callback function.
* @param arg: contain the ip link information
* @retval None
*/
static void ICACHE_FLASH_ATTR
at_upDate_discon_cb(void *arg)
{
struct espconn *pespconn = (struct espconn *)arg;
uint8_t idTemp = 0;
if(pespconn->proto.tcp != NULL)
{
os_free(pespconn->proto.tcp);
}
if(pespconn != NULL)
{
os_free(pespconn);
}
os_printf("disconnect\r\n");
if(system_upgrade_start(upServer) == false)
{
at_response_error();
}
else
{
at_port_print("+CIPUPDATE:4\r\n");
}
}
/**
* @brief Udp server receive data callback function.
* @param arg: contain the ip link information
* @retval None
*/
LOCAL void ICACHE_FLASH_ATTR
at_upDate_recv(void *arg, char *pusrdata, unsigned short len)
{
struct espconn *pespconn = (struct espconn *)arg;
char temp[32] = {0};
uint8_t user_bin[12] = {0};
uint8_t i = 0;
os_timer_disarm(&at_delay_check);
at_port_print("+CIPUPDATE:3\r\n");
upServer = (struct upgrade_server_info *)os_zalloc(sizeof(struct upgrade_server_info));
upServer->upgrade_version[5] = '\0';
upServer->pespconn = pespconn;
os_memcpy(upServer->ip, pespconn->proto.tcp->remote_ip, 4);
upServer->port = pespconn->proto.tcp->remote_port;
upServer->check_cb = at_upDate_rsp;
upServer->check_times = 60000;
if(upServer->url == NULL)
{
upServer->url = (uint8 *) os_zalloc(1024);
}
if(system_upgrade_userbin_check() == UPGRADE_FW_BIN1)
{
os_memcpy(user_bin, "user2.bin", 10);
}
else if(system_upgrade_userbin_check() == UPGRADE_FW_BIN2)
{
os_memcpy(user_bin, "user1.bin", 10);
}
os_sprintf(upServer->url,
"GET /%s HTTP/1.1\r\nHost: "IPSTR"\r\n"pheadbuffer"",
user_bin, IP2STR(upServer->ip));
}
LOCAL void ICACHE_FLASH_ATTR
at_upDate_wait(void *arg)
{
struct espconn *pespconn = arg;
os_timer_disarm(&at_delay_check);
if(pespconn != NULL)
{
espconn_disconnect(pespconn);
}
else
{
at_response_error();
}
}
/******************************************************************************
* FunctionName : user_esp_platform_sent_cb
* Description : Data has been sent successfully and acknowledged by the remote host.
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
at_upDate_sent_cb(void *arg)
{
struct espconn *pespconn = arg;
os_timer_disarm(&at_delay_check);
os_timer_setfn(&at_delay_check, (os_timer_func_t *)at_upDate_wait, pespconn);
os_timer_arm(&at_delay_check, 5000, 0);
os_printf("at_upDate_sent_cb\r\n");
}
/**
* @brief Tcp client connect success callback function.
* @param arg: contain the ip link information
* @retval None
*/
static void ICACHE_FLASH_ATTR
at_upDate_connect_cb(void *arg)
{
struct espconn *pespconn = (struct espconn *)arg;
uint8_t user_bin[9] = {0};
char *temp = NULL;
at_port_print("+CIPUPDATE:2\r\n");
espconn_regist_disconcb(pespconn, at_upDate_discon_cb);
espconn_regist_recvcb(pespconn, at_upDate_recv);////////
espconn_regist_sentcb(pespconn, at_upDate_sent_cb);
temp = (uint8 *) os_zalloc(512);
os_sprintf(temp,"GET /v1/device/rom/?is_format_simple=true HTTP/1.0\r\nHost: "IPSTR"\r\n"pheadbuffer"",
IP2STR(pespconn->proto.tcp->remote_ip));
espconn_sent(pespconn, temp, os_strlen(temp));
os_free(temp);
}
/**
* @brief Tcp client connect repeat callback function.
* @param arg: contain the ip link information
* @retval None
*/
static void ICACHE_FLASH_ATTR
at_upDate_recon_cb(void *arg, sint8 errType)
{
struct espconn *pespconn = (struct espconn *)arg;
at_response_error();
if(pespconn->proto.tcp != NULL)
{
os_free(pespconn->proto.tcp);
}
os_free(pespconn);
os_printf("disconnect\r\n");
if(upServer != NULL)
{
os_free(upServer);
upServer = NULL;
}
at_response_error();
}
/******************************************************************************
* FunctionName : upServer_dns_found
* Description : dns found callback
* Parameters : name -- pointer to the name that was looked up.
* ipaddr -- pointer to an ip_addr_t containing the IP address of
* the hostname, or NULL if the name could not be found (or on any
* other error).
* callback_arg -- a user-specified callback argument passed to
* dns_gethostbyname
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
upServer_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
{
struct espconn *pespconn = (struct espconn *) arg;
// char temp[32];
if(ipaddr == NULL)
{
at_response_error();
return;
}
at_port_print("+CIPUPDATE:1\r\n");
if(host_ip.addr == 0 && ipaddr->addr != 0)
{
if(pespconn->type == ESPCONN_TCP)
{
os_memcpy(pespconn->proto.tcp->remote_ip, &ipaddr->addr, 4);
espconn_regist_connectcb(pespconn, at_upDate_connect_cb);
espconn_regist_reconcb(pespconn, at_upDate_recon_cb);
espconn_connect(pespconn);
}
}
}
void ICACHE_FLASH_ATTR
at_exeCmdCiupdate(uint8_t id)
{
pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn));
pespconn->type = ESPCONN_TCP;
pespconn->state = ESPCONN_NONE;
pespconn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
pespconn->proto.tcp->local_port = espconn_port();
pespconn->proto.tcp->remote_port = 80;
host_ip.addr = ipaddr_addr("192.168.10.9");
at_port_print("+CIPUPDATE:1\r\n");
os_memcpy(pespconn->proto.tcp->remote_ip, &host_ip.addr, 4);
espconn_regist_connectcb(pespconn, at_upDate_connect_cb);
espconn_regist_reconcb(pespconn, at_upDate_recon_cb);
espconn_connect(pespconn);
}
#endif
#endif
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: user_main.c
*
* Description: entry file of user application
*
* Modification history:
* 2015/1/23, v1.0 create this file.
*******************************************************************************/
#include "osapi.h"
#include "at_custom.h"
#include "user_interface.h"
// test :AT+TEST=1,"abc"<,3>
void ICACHE_FLASH_ATTR
at_setupCmdTest(uint8_t id, char *pPara)
{
int result = 0, err = 0, flag = 0;
uint8 buffer[32] = {0};
pPara++; // skip '='
//get the first parameter
// digit
flag = at_get_next_int_dec(&pPara, &result, &err);
// flag must be ture because there are more parameter
if (flag == FALSE) {
at_response_error();
return;
}
if (*pPara++ != ',') { // skip ','
at_response_error();
return;
}
os_sprintf(buffer, "the first parameter:%d\r\n", result);
at_port_print(buffer);
//get the second parameter
// string
at_data_str_copy(buffer, &pPara, 10);
at_port_print("the second parameter:");
at_port_print(buffer);
at_port_print("\r\n");
if (*pPara == ',') {
pPara++; // skip ','
result = 0;
//there is the third parameter
// digit
flag = at_get_next_int_dec(&pPara, &result, &err);
// we donot care of flag
os_sprintf(buffer, "the third parameter:%d\r\n", result);
at_port_print(buffer);
}
if (*pPara != '\r') {
at_response_error();
return;
}
at_response_ok();
}
void ICACHE_FLASH_ATTR
at_testCmdTest(uint8_t id)
{
uint8 buffer[32] = {0};
os_sprintf(buffer, "%s\r\n", "at_testCmdTest");
at_port_print(buffer);
at_response_ok();
}
void ICACHE_FLASH_ATTR
at_queryCmdTest(uint8_t id)
{
uint8 buffer[32] = {0};
os_sprintf(buffer, "%s\r\n", "at_queryCmdTest");
at_port_print(buffer);
at_response_ok();
}
void ICACHE_FLASH_ATTR
at_exeCmdTest(uint8_t id)
{
uint8 buffer[32] = {0};
os_sprintf(buffer, "%s\r\n", "at_exeCmdTest");
at_port_print(buffer);
at_response_ok();
}
extern void at_exeCmdCiupdate(uint8_t id);
at_funcationType at_custom_cmd[] = {
{"+TEST", 5, at_testCmdTest, at_queryCmdTest, at_setupCmdTest, at_exeCmdTest},
#ifdef AT_UPGRADE_SUPPORT
{"+CIUPDATE", 9, NULL, NULL, NULL, at_exeCmdCiupdate}
#endif
};
void user_rf_pre_init(void)
{
}
void user_init(void)
{
char buf[64] = {0};
at_customLinkMax = 5;
at_init();
os_sprintf(buf,"compile time:%s %s",__DATE__,__TIME__);
at_set_custom_info(buf);
at_port_print("\r\nready\r\n");
at_cmd_array_regist(&at_custom_cmd[0], sizeof(at_custom_cmd)/sizeof(at_custom_cmd[0]));
}
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libdriver.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
#include "ets_sys.h"
#include "osapi.h"
#include "driver/gpio16.h"
void ICACHE_FLASH_ATTR
gpio16_output_conf(void)
{
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC to output rtc_gpio0
WRITE_PERI_REG(RTC_GPIO_CONF,
(READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
WRITE_PERI_REG(RTC_GPIO_ENABLE,
(READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe) | (uint32)0x1); //out enable
}
void ICACHE_FLASH_ATTR
gpio16_output_set(uint8 value)
{
WRITE_PERI_REG(RTC_GPIO_OUT,
(READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe) | (uint32)(value & 1));
}
void ICACHE_FLASH_ATTR
gpio16_input_conf(void)
{
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection
WRITE_PERI_REG(RTC_GPIO_CONF,
(READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
WRITE_PERI_REG(RTC_GPIO_ENABLE,
READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable
}
uint8 ICACHE_FLASH_ATTR
gpio16_input_get(void)
{
return (uint8)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1);
}
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: hw_timer.c
*
* Description: hw_timer driver
*
* Modification history:
* 2014/5/1, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#define US_TO_RTC_TIMER_TICKS(t) \
((t) ? \
(((t) > 0x35A) ? \
(((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
0)
#define FRC1_ENABLE_TIMER BIT7
#define FRC1_AUTO_LOAD BIT6
//TIMER PREDIVED MODE
typedef enum {
DIVDED_BY_1 = 0, //timer clock
DIVDED_BY_16 = 4, //divided by 16
DIVDED_BY_256 = 8, //divided by 256
} TIMER_PREDIVED_MODE;
typedef enum { //timer interrupt mode
TM_LEVEL_INT = 1, // level interrupt
TM_EDGE_INT = 0, //edge interrupt
} TIMER_INT_MODE;
typedef enum {
FRC1_SOURCE = 0,
NMI_SOURCE = 1,
} FRC1_TIMER_SOURCE_TYPE;
/******************************************************************************
* FunctionName : hw_timer_arm
* Description : set a trigger timer delay for this timer.
* Parameters : uint32 val :
in autoload mode
50 ~ 0x7fffff; for FRC1 source.
100 ~ 0x7fffff; for NMI source.
in non autoload mode:
10 ~ 0x7fffff;
* Returns : NONE
*******************************************************************************/
void hw_timer_arm(u32 val)
{
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val));
}
static void (* user_hw_timer_cb)(void) = NULL;
/******************************************************************************
* FunctionName : hw_timer_set_func
* Description : set the func, when trigger timer is up.
* Parameters : void (* user_hw_timer_cb_set)(void):
timer callback function,
* Returns : NONE
*******************************************************************************/
void hw_timer_set_func(void (* user_hw_timer_cb_set)(void))
{
user_hw_timer_cb = user_hw_timer_cb_set;
}
static void hw_timer_isr_cb(void)
{
if (user_hw_timer_cb != NULL) {
(*(user_hw_timer_cb))();
}
}
/******************************************************************************
* FunctionName : hw_timer_init
* Description : initilize the hardware isr timer
* Parameters :
FRC1_TIMER_SOURCE_TYPE source_type:
FRC1_SOURCE, timer use frc1 isr as isr source.
NMI_SOURCE, timer use nmi isr as isr source.
u8 req:
0, not autoload,
1, autoload mode,
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type, u8 req)
{
if (req == 1) {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
FRC1_AUTO_LOAD | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
} else {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
}
if (source_type == NMI_SOURCE) {
ETS_FRC_TIMER1_NMI_INTR_ATTACH(hw_timer_isr_cb);
} else {
ETS_FRC_TIMER1_INTR_ATTACH(hw_timer_isr_cb, NULL);
}
TM1_EDGE_INT_ENABLE();
ETS_FRC1_INTR_ENABLE();
}
//-------------------------------Test Code Below--------------------------------------
#if 0
void hw_test_timer_cb(void)
{
static uint16 j = 0;
j++;
if ((WDEV_NOW() - tick_now2) >= 1000000) {
static u32 idx = 1;
tick_now2 = WDEV_NOW();
os_printf("b%u:%d\n", idx++, j);
j = 0;
}
//hw_timer_arm(50);
}
void ICACHE_FLASH_ATTR user_init(void)
{
hw_timer_init(FRC1_SOURCE, 1);
hw_timer_set_func(hw_test_timer_cb);
hw_timer_arm(100);
}
#endif
/*
NOTE:
1 if use nmi source, for autoload timer , the timer setting val can't be less than 100.
2 if use nmi source, this timer has highest priority, can interrupt other isr.
3 if use frc1 source, this timer can't interrupt other isr.
*/
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: i2c_master.c
*
* Description: i2c master API
*
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "driver/i2c_master.h"
LOCAL uint8 m_nLastSDA;
LOCAL uint8 m_nLastSCL;
/******************************************************************************
* FunctionName : i2c_master_setDC
* Description : Internal used function -
* set i2c SDA and SCL bit value for half clk cycle
* Parameters : uint8 SDA
* uint8 SCL
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
i2c_master_setDC(uint8 SDA, uint8 SCL)
{
SDA &= 0x01;
SCL &= 0x01;
m_nLastSDA = SDA;
m_nLastSCL = SCL;
if ((0 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_LOW();
} else if ((0 == SDA) && (1 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_HIGH();
} else if ((1 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_HIGH_SCL_LOW();
} else {
I2C_MASTER_SDA_HIGH_SCL_HIGH();
}
}
/******************************************************************************
* FunctionName : i2c_master_getDC
* Description : Internal used function -
* get i2c SDA bit value
* Parameters : NONE
* Returns : uint8 - SDA bit value
*******************************************************************************/
LOCAL uint8 ICACHE_FLASH_ATTR
i2c_master_getDC(void)
{
uint8 sda_out;
sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
return sda_out;
}
/******************************************************************************
* FunctionName : i2c_master_init
* Description : initilize I2C bus to enable i2c operations
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_init(void)
{
uint8 i;
i2c_master_setDC(1, 0);
i2c_master_wait(5);
// when SCL = 0, toggle SDA to clear up
i2c_master_setDC(0, 0) ;
i2c_master_wait(5);
i2c_master_setDC(1, 0) ;
i2c_master_wait(5);
// set data_cnt to max value
for (i = 0; i < 28; i++) {
i2c_master_setDC(1, 0);
i2c_master_wait(5); // sda 1, scl 0
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
}
// reset all
i2c_master_stop();
return;
}
/******************************************************************************
* FunctionName : i2c_master_gpio_init
* Description : config SDA and SCL gpio to open-drain output mode,
* mux and gpio num defined in i2c_master.h
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_gpio_init(void)
{
ETS_GPIO_INTR_DISABLE() ;
// ETS_INTR_LOCK();
PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC);
PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC);
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SDA_GPIO));
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SCL_GPIO));
I2C_MASTER_SDA_HIGH_SCL_HIGH();
ETS_GPIO_INTR_ENABLE() ;
// ETS_INTR_UNLOCK();
i2c_master_init();
}
/******************************************************************************
* FunctionName : i2c_master_start
* Description : set i2c to send state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_start(void)
{
i2c_master_setDC(1, m_nLastSCL);
i2c_master_wait(5);
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
i2c_master_setDC(0, 1);
i2c_master_wait(5); // sda 0, scl 1
}
/******************************************************************************
* FunctionName : i2c_master_stop
* Description : set i2c to stop sending state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_stop(void)
{
i2c_master_wait(5);
i2c_master_setDC(0, m_nLastSCL);
i2c_master_wait(5); // sda 0
i2c_master_setDC(0, 1);
i2c_master_wait(5); // sda 0, scl 1
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
}
/******************************************************************************
* FunctionName : i2c_master_setAck
* Description : set ack to i2c bus as level value
* Parameters : uint8 level - 0 or 1
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(uint8 level)
{
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5);
i2c_master_setDC(level, 0);
i2c_master_wait(5); // sda level, scl 0
i2c_master_setDC(level, 1);
i2c_master_wait(8); // sda level, scl 1
i2c_master_setDC(level, 0);
i2c_master_wait(5); // sda level, scl 0
i2c_master_setDC(1, 0);
i2c_master_wait(5);
}
/******************************************************************************
* FunctionName : i2c_master_getAck
* Description : confirm if peer send ack
* Parameters : NONE
* Returns : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)
{
uint8 retVal;
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5);
i2c_master_setDC(1, 0);
i2c_master_wait(5);
i2c_master_setDC(1, 1);
i2c_master_wait(5);
retVal = i2c_master_getDC();
i2c_master_wait(5);
i2c_master_setDC(1, 0);
i2c_master_wait(5);
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_checkAck
* Description : get dev response
* Parameters : NONE
* Returns : true : get ack ; false : get nack
*******************************************************************************/
bool ICACHE_FLASH_ATTR
i2c_master_checkAck(void)
{
if(i2c_master_getAck()){
return FALSE;
}else{
return TRUE;
}
}
/******************************************************************************
* FunctionName : i2c_master_send_ack
* Description : response ack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_ack(void)
{
i2c_master_setAck(0x0);
}
/******************************************************************************
* FunctionName : i2c_master_send_nack
* Description : response nack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_nack(void)
{
i2c_master_setAck(0x1);
}
/******************************************************************************
* FunctionName : i2c_master_readByte
* Description : read Byte from i2c bus
* Parameters : NONE
* Returns : uint8 - readed value
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_readByte(void)
{
uint8 retVal = 0;
uint8 k, i;
i2c_master_wait(5);
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5); // sda 1, scl 0
for (i = 0; i < 8; i++) {
i2c_master_wait(5);
i2c_master_setDC(1, 0);
i2c_master_wait(5); // sda 1, scl 0
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
k = i2c_master_getDC();
i2c_master_wait(5);
if (i == 7) {
i2c_master_wait(3); ////
}
k <<= (7 - i);
retVal |= k;
}
i2c_master_setDC(1, 0);
i2c_master_wait(5); // sda 1, scl 0
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_writeByte
* Description : write wrdata value(one byte) into i2c
* Parameters : uint8 wrdata - write value
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(uint8 wrdata)
{
uint8 dat;
sint8 i;
i2c_master_wait(5);
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5);
for (i = 7; i >= 0; i--) {
dat = wrdata >> i;
i2c_master_setDC(dat, 0);
i2c_master_wait(5);
i2c_master_setDC(dat, 1);
i2c_master_wait(5);
if (i == 0) {
i2c_master_wait(3); ////
}
i2c_master_setDC(dat, 0);
i2c_master_wait(5);
}
}
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: key.c
*
* Description: key driver, now can use different gpio and install different function
*
* Modification history:
* 2014/5/1, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "gpio.h"
#include "user_interface.h"
#include "driver/key.h"
LOCAL void key_intr_handler(struct keys_param *keys);
/******************************************************************************
* FunctionName : key_init_single
* Description : init single key's gpio and register function
* Parameters : uint8 gpio_id - which gpio to use
* uint32 gpio_name - gpio mux name
* uint32 gpio_func - gpio function
* key_function long_press - long press function, needed to install
* key_function short_press - short press function, needed to install
* Returns : single_key_param - single key parameter, needed by key init
*******************************************************************************/
struct single_key_param *ICACHE_FLASH_ATTR
key_init_single(uint8 gpio_id, uint32 gpio_name, uint8 gpio_func, key_function long_press, key_function short_press)
{
struct single_key_param *single_key = (struct single_key_param *)os_zalloc(sizeof(struct single_key_param));
single_key->gpio_id = gpio_id;
single_key->gpio_name = gpio_name;
single_key->gpio_func = gpio_func;
single_key->long_press = long_press;
single_key->short_press = short_press;
return single_key;
}
/******************************************************************************
* FunctionName : key_init
* Description : init keys
* Parameters : key_param *keys - keys parameter, which inited by key_init_single
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
key_init(struct keys_param *keys)
{
uint8 i;
ETS_GPIO_INTR_ATTACH(key_intr_handler, keys);
ETS_GPIO_INTR_DISABLE();
for (i = 0; i < keys->key_num; i++) {
keys->single_key[i]->key_level = 1;
PIN_FUNC_SELECT(keys->single_key[i]->gpio_name, keys->single_key[i]->gpio_func);
gpio_output_set(0, 0, 0, GPIO_ID_PIN(keys->single_key[i]->gpio_id));
gpio_register_set(GPIO_PIN_ADDR(keys->single_key[i]->gpio_id), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE)
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE)
| GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE));
//clear gpio14 status
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(keys->single_key[i]->gpio_id));
//enable interrupt
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_NEGEDGE);
}
ETS_GPIO_INTR_ENABLE();
}
/******************************************************************************
* FunctionName : key_5s_cb
* Description : long press 5s timer callback
* Parameters : single_key_param *single_key - single key parameter
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
key_5s_cb(struct single_key_param *single_key)
{
os_timer_disarm(&single_key->key_5s);
// low, then restart
if (0 == GPIO_INPUT_GET(GPIO_ID_PIN(single_key->gpio_id))) {
if (single_key->long_press) {
single_key->long_press();
}
}
}
/******************************************************************************
* FunctionName : key_50ms_cb
* Description : 50ms timer callback to check it's a real key push
* Parameters : single_key_param *single_key - single key parameter
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
key_50ms_cb(struct single_key_param *single_key)
{
os_timer_disarm(&single_key->key_50ms);
// high, then key is up
if (1 == GPIO_INPUT_GET(GPIO_ID_PIN(single_key->gpio_id))) {
os_timer_disarm(&single_key->key_5s);
single_key->key_level = 1;
gpio_pin_intr_state_set(GPIO_ID_PIN(single_key->gpio_id), GPIO_PIN_INTR_NEGEDGE);
if (single_key->short_press) {
single_key->short_press();
}
} else {
gpio_pin_intr_state_set(GPIO_ID_PIN(single_key->gpio_id), GPIO_PIN_INTR_POSEDGE);
}
}
/******************************************************************************
* FunctionName : key_intr_handler
* Description : key interrupt handler
* Parameters : key_param *keys - keys parameter, which inited by key_init_single
* Returns : none
*******************************************************************************/
LOCAL void
key_intr_handler(struct keys_param *keys)
{
uint8 i;
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
for (i = 0; i < keys->key_num; i++) {
if (gpio_status & BIT(keys->single_key[i]->gpio_id)) {
//disable interrupt
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_DISABLE);
//clear interrupt status
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(keys->single_key[i]->gpio_id));
if (keys->single_key[i]->key_level == 1) {
// 5s, restart & enter softap mode
os_timer_disarm(&keys->single_key[i]->key_5s);
os_timer_setfn(&keys->single_key[i]->key_5s, (os_timer_func_t *)key_5s_cb, keys->single_key[i]);
os_timer_arm(&keys->single_key[i]->key_5s, 5000, 0);
keys->single_key[i]->key_level = 0;
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_POSEDGE);
} else {
// 50ms, check if this is a real key up
os_timer_disarm(&keys->single_key[i]->key_50ms);
os_timer_setfn(&keys->single_key[i]->key_50ms, (os_timer_func_t *)key_50ms_cb, keys->single_key[i]);
os_timer_arm(&keys->single_key[i]->key_50ms, 50, 0);
}
}
}
}
#include "driver/spi.h"
#include "driver/spi_overlap.h"
#define CACHE_FLASH_CTRL_REG 0x3ff0000C
#define CACHE_FLUSH_START_BIT BIT0
#define CACHE_EMPTY_FLAG_BIT BIT1
/******************************************************************************
* FunctionName : cache_flush
* Description : clear all the cpu cache data for stability test.
*******************************************************************************/
void cache_flush(void)
{
while(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT) {
CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT);
SET_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT);
}
while(!(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT));
CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT);
}
/******************************************************************************
* FunctionName : spi_master_init
* Description : SPI master initial function for common byte units transmission
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_master_init(uint8 spi_no)
{
uint32 regvalue;
if(spi_no>1) return; //handle invalid input number
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
WRITE_PERI_REG(SPI_CLOCK(spi_no),
((3&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
((1&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
((3&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
}
/******************************************************************************
* FunctionName : spi_lcd_9bit_write
* Description : SPI 9bits transmission function for driving LCD TM035PDZV36
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 high_bit - first high bit of the data, 0 is for "0",the other value 1-255 is for "1"
* uint8 low_8bit- the rest 8bits of the data.
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit)
{
uint32 regvalue;
uint8 bytetemp;
if(spi_no>1) return; //handle invalid input number
if(high_bit) bytetemp=(low_8bit>>1)|0x80;
else bytetemp=(low_8bit>>1)&0x7f;
regvalue= ((8&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit
if(low_8bit&0x01) regvalue|=BIT15; //write the 9th bit
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR); //waiting for spi module available
WRITE_PERI_REG(SPI_USER2(spi_no), regvalue); //write command and command length into spi reg
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); //transmission start
// while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
}
/******************************************************************************
* FunctionName : spi_mast_byte_write
* Description : SPI master 1 byte transmission function
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 data- transmitted data
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_mast_byte_write(uint8 spi_no,uint8 data)
{
uint32 regvalue;
if(spi_no>1) return; //handle invalid input number
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_MISO);
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
// bit15-0 is cmd value.
WRITE_PERI_REG(SPI_USER2(spi_no),
((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)data));
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
}
/******************************************************************************
* FunctionName : spi_byte_write_espslave
* Description : SPI master 1 byte transmission function for esp8266 slave,
* transmit 1byte data to esp8266 slave buffer needs 16bit transmission ,
* first byte is command 0x04 to write slave buffer, second byte is data
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 data- transmitted data
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_byte_write_espslave(uint8 spi_no,uint8 data)
{
uint32 regvalue;
if(spi_no>1) return; //handle invalid input number
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO|SPI_USR_ADDR|SPI_USR_DUMMY);
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
// bit15-0 is cmd value.
//0x70000000 is for 8bits cmd, 0x04 is eps8266 slave write cmd value
WRITE_PERI_REG(SPI_USER2(spi_no),
((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|4);
WRITE_PERI_REG(SPI_W0(spi_no), (uint32)(data));
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
}
/******************************************************************************
* FunctionName : spi_byte_read_espslave
* Description : SPI master 1 byte read function for esp8266 slave,
* read 1byte data from esp8266 slave buffer needs 16bit transmission ,
* first byte is command 0x06 to read slave buffer, second byte is recieved data
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8* data- recieved data address
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_byte_read_espslave(uint8 spi_no,uint8 *data)
{
uint32 regvalue;
if(spi_no>1) return; //handle invalid input number
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_ADDR|SPI_USR_DUMMY);
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
// bit15-0 is cmd value.
//0x70000000 is for 8bits cmd, 0x06 is eps8266 slave read cmd value
WRITE_PERI_REG(SPI_USER2(spi_no),
((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|6);
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
*data=(uint8)(READ_PERI_REG(SPI_W0(spi_no))&0xff);
}
/******************************************************************************
* FunctionName : spi_slave_init
* Description : SPI slave mode initial funtion, including mode setting,
* IO setting, transmission interrupt opening, interrupt function registration
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 data_len - read&write data pack length,using byte as unit,the range is 1-32
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_slave_init(uint8 spi_no,uint8 data_len)
{
uint32 regvalue;
uint32 data_bit_len;
if(spi_no>1)
return; //handle invalid input number
if(data_len<=1) data_bit_len=7;
else if(data_len>=32) data_bit_len=0xff;
else data_bit_len=(data_len<<3)-1;
//clear bit9,bit8 of reg PERIPHS_IO_MUX
//bit9 should be cleared when HSPI clock doesn't equal CPU clock
//bit8 should be cleared when SPI clock doesn't equal CPU clock
////WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9//TEST
if(spi_no==SPI){
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
}else if(spi_no==HSPI){
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
}
//regvalue=READ_PERI_REG(SPI_FLASH_SLAVE(spi_no));
//slave mode,slave use buffers which are register "SPI_FLASH_C0~C15", enable trans done isr
//set bit 30 bit 29 bit9,bit9 is trans done isr mask
SET_PERI_REG_MASK( SPI_SLAVE(spi_no),
SPI_SLAVE_MODE|SPI_SLV_WR_RD_BUF_EN|
SPI_SLV_WR_BUF_DONE_EN|SPI_SLV_RD_BUF_DONE_EN|
SPI_SLV_WR_STA_DONE_EN|SPI_SLV_RD_STA_DONE_EN|
SPI_TRANS_DONE_EN);
//disable general trans intr
//CLEAR_PERI_REG_MASK(SPI_SLAVE(spi_no),SPI_TRANS_DONE_EN);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);//disable flash operation mode
SET_PERI_REG_MASK(SPI_USER(spi_no),SPI_USR_MISO_HIGHPART);//SLAVE SEND DATA BUFFER IN C8-C15
//////**************RUN WHEN SLAVE RECIEVE*******************///////
//tow lines below is to configure spi timing.
SET_PERI_REG_MASK(SPI_CTRL2(spi_no),(0x2&SPI_MOSI_DELAY_NUM)<<SPI_MOSI_DELAY_NUM_S) ;//delay num
os_printf("SPI_CTRL2 is %08x\n",READ_PERI_REG(SPI_CTRL2(spi_no)));
WRITE_PERI_REG(SPI_CLOCK(spi_no), 0);
/////***************************************************//////
//set 8 bit slave command length, because slave must have at least one bit addr,
//8 bit slave+8bit addr, so master device first 2 bytes can be regarded as a command
//and the following bytes are datas,
//32 bytes input wil be stored in SPI_FLASH_C0-C7
//32 bytes output data should be set to SPI_FLASH_C8-C15
WRITE_PERI_REG(SPI_USER2(spi_no), (0x7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S); //0x70000000
//set 8 bit slave recieve buffer length, the buffer is SPI_FLASH_C0-C7
//set 8 bit slave status register, which is the low 8 bit of register "SPI_FLASH_STATUS"
SET_PERI_REG_MASK(SPI_SLAVE1(spi_no), ((data_bit_len&SPI_SLV_BUF_BITLEN)<< SPI_SLV_BUF_BITLEN_S)|
((0x7&SPI_SLV_STATUS_BITLEN)<<SPI_SLV_STATUS_BITLEN_S)|
((0x7&SPI_SLV_WR_ADDR_BITLEN)<<SPI_SLV_WR_ADDR_BITLEN_S)|
((0x7&SPI_SLV_RD_ADDR_BITLEN)<<SPI_SLV_RD_ADDR_BITLEN_S));
SET_PERI_REG_MASK(SPI_PIN(spi_no),BIT19);//BIT19
//maybe enable slave transmission liston
SET_PERI_REG_MASK(SPI_CMD(spi_no),SPI_USR);
//register level2 isr function, which contains spi, hspi and i2s events
ETS_SPI_INTR_ATTACH(spi_slave_isr_handler,NULL);
//enable level2 isr, which contains spi, hspi and i2s events
ETS_SPI_INTR_ENABLE();
}
/* =============================================================================================
* code below is for spi slave r/w testcase with 2 r/w state lines connected to the spi master mcu
* replace with your own process functions
* find "add system_os_post here" in spi_slave_isr_handler.
* =============================================================================================
*/
#ifdef SPI_SLAVE_DEBUG
/******************************************************************************
* FunctionName : hspi_master_readwrite_repeat
* Description : SPI master test function for reading and writing esp8266 slave buffer,
the function uses HSPI module
*******************************************************************************/
os_timer_t timer2;
void hspi_master_readwrite_repeat(void)
{
static uint8 data=0;
uint8 temp;
os_timer_disarm(&timer2);
spi_byte_read_espslave(HSPI,&temp);
temp++;
spi_byte_write_espslave(HSPI,temp);
os_timer_setfn(&timer2, (os_timer_func_t *)hspi_master_readwrite_repeat, NULL);
os_timer_arm(&timer2, 500, 0);
}
#endif
/******************************************************************************
* FunctionName : spi_slave_isr_handler
* Description : SPI interrupt function, SPI HSPI and I2S interrupt can trig this function
some basic operation like clear isr flag has been done,
and it is availible for adding user coder in the funtion
* Parameters : void *para- function parameter address, which has been registered in function spi_slave_init
*******************************************************************************/
#include "gpio.h"
#include "user_interface.h"
#include "mem.h"
static uint8 spi_data[32] = {0};
static uint8 idx = 0;
static uint8 spi_flg = 0;
#define SPI_MISO
#define SPI_QUEUE_LEN 8
os_event_t * spiQueue;
#define MOSI 0
#define MISO 1
#define STATUS_R_IN_WR 2
#define STATUS_W 3
#define TR_DONE_ALONE 4
#define WR_RD 5
#define DATA_ERROR 6
#define STATUS_R_IN_RD 7
//init the two intr line of slave
//gpio0: wr_ready ,and
//gpio2: rd_ready , controlled by slave
void ICACHE_FLASH_ATTR
gpio_init()
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4);
GPIO_OUTPUT_SET(0, 1);
GPIO_OUTPUT_SET(2, 0);
//GPIO_OUTPUT_SET(4, 1);
}
void spi_slave_isr_handler(void *para)
{
uint32 regvalue,calvalue;
static uint8 state =0;
uint32 recv_data,send_data;
if(READ_PERI_REG(0x3ff00020)&BIT4){
//following 3 lines is to clear isr signal
CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI), 0x3ff);
}else if(READ_PERI_REG(0x3ff00020)&BIT7){ //bit7 is for hspi isr,
regvalue=READ_PERI_REG(SPI_SLAVE(HSPI));
CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
SPI_TRANS_DONE_EN|
SPI_SLV_WR_STA_DONE_EN|
SPI_SLV_RD_STA_DONE_EN|
SPI_SLV_WR_BUF_DONE_EN|
SPI_SLV_RD_BUF_DONE_EN);
SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_SYNC_RESET);
CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
SPI_TRANS_DONE|
SPI_SLV_WR_STA_DONE|
SPI_SLV_RD_STA_DONE|
SPI_SLV_WR_BUF_DONE|
SPI_SLV_RD_BUF_DONE);
SET_PERI_REG_MASK(SPI_SLAVE(HSPI),
SPI_TRANS_DONE_EN|
SPI_SLV_WR_STA_DONE_EN|
SPI_SLV_RD_STA_DONE_EN|
SPI_SLV_WR_BUF_DONE_EN|
SPI_SLV_RD_BUF_DONE_EN);
if(regvalue&SPI_SLV_WR_BUF_DONE){
GPIO_OUTPUT_SET(0, 0);
idx=0;
while(idx<8){
recv_data=READ_PERI_REG(SPI_W0(HSPI)+(idx<<2));
spi_data[idx<<2] = recv_data&0xff;
spi_data[(idx<<2)+1] = (recv_data>>8)&0xff;
spi_data[(idx<<2)+2] = (recv_data>>16)&0xff;
spi_data[(idx<<2)+3] = (recv_data>>24)&0xff;
idx++;
}
//add system_os_post here
GPIO_OUTPUT_SET(0, 1);
}
if(regvalue&SPI_SLV_RD_BUF_DONE){
//it is necessary to call GPIO_OUTPUT_SET(2, 1), when new data is preped in SPI_W8-15 and needs to be sended.
GPIO_OUTPUT_SET(2, 0);
//add system_os_post here
//system_os_post(USER_TASK_PRIO_1,WR_RD,regvalue);
}
}else if(READ_PERI_REG(0x3ff00020)&BIT9){ //bit7 is for i2s isr,
}
}
#ifdef SPI_SLAVE_DEBUG
void ICACHE_FLASH_ATTR
set_miso_data()
{
if(GPIO_INPUT_GET(2)==0){
WRITE_PERI_REG(SPI_W8(HSPI),0x05040302);
WRITE_PERI_REG(SPI_W9(HSPI),0x09080706);
WRITE_PERI_REG(SPI_W10(HSPI),0x0d0c0b0a);
WRITE_PERI_REG(SPI_W11(HSPI),0x11100f0e);
WRITE_PERI_REG(SPI_W12(HSPI),0x15141312);
WRITE_PERI_REG(SPI_W13(HSPI),0x19181716);
WRITE_PERI_REG(SPI_W14(HSPI),0x1d1c1b1a);
WRITE_PERI_REG(SPI_W15(HSPI),0x21201f1e);
GPIO_OUTPUT_SET(2, 1);
}
}
void ICACHE_FLASH_ATTR
disp_spi_data()
{
uint8 i = 0;
for(i=0;i<32;i++){
os_printf("data %d : 0x%02x\n\r",i,spi_data[i]);
}
//os_printf("d31:0x%02x\n\r",spi_data[31]);
}
void ICACHE_FLASH_ATTR
spi_task(os_event_t *e)
{
uint8 data;
switch(e->sig){
case MOSI:
disp_spi_data();
break;
case STATUS_R_IN_WR :
os_printf("SR ERR in WRPR,Reg:%08x \n",e->par);
break;
case STATUS_W:
os_printf("SW ERR,Reg:%08x\n",e->par);
break;
case TR_DONE_ALONE:
os_printf("TD ALO ERR,Reg:%08x\n",e->par);
break;
case WR_RD:
os_printf("WR&RD ERR,Reg:%08x\n",e->par);
break;
case DATA_ERROR:
os_printf("Data ERR,Reg:%08x\n",e->par);
break;
case STATUS_R_IN_RD :
os_printf("SR ERR in RDPR,Reg:%08x\n",e->par);
break;
default:
break;
}
}
void ICACHE_FLASH_ATTR
spi_task_init(void)
{
spiQueue = (os_event_t*)os_malloc(sizeof(os_event_t)*SPI_QUEUE_LEN);
system_os_task(spi_task,USER_TASK_PRIO_1,spiQueue,SPI_QUEUE_LEN);
}
os_timer_t spi_timer_test;
void ICACHE_FLASH_ATTR
spi_test_init()
{
os_printf("spi init\n\r");
spi_slave_init(HSPI);
os_printf("gpio init\n\r");
gpio_init();
os_printf("spi task init \n\r");
spi_task_init();
#ifdef SPI_MISO
os_printf("spi miso init\n\r");
set_miso_data();
#endif
//os_timer_disarm(&spi_timer_test);
//os_timer_setfn(&spi_timer_test, (os_timer_func_t *)set_miso_data, NULL);//wjl
//os_timer_arm(&spi_timer_test,50,1);
}
#endif
#include "driver/spi_overlap.h"
#include "driver/spi.h"
#include "gpio.h"
#define SPI_FLASH_READ_MODE_MASK 0x196000
#define WAIT_HSPI_IDLE() while(READ_PERI_REG(SPI_EXT2(HSPI))||(READ_PERI_REG(SPI_CMD(HSPI))&0xfffc0000));
#define CONF_HSPI_CLK_DIV(div) WRITE_PERI_REG(SPI_CLOCK(HSPI), (((div<<1)+1)<<12)+(div<<6)+(div<<1)+1)
#define HSPI_FALLING_EDGE_SAMPLE() SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE)
#define HSPI_RISING_EDGE_SAMPLE() CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE)
#define ACTIVE_HSPI_CS0 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS0_DIS);\
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS1_DIS |SPI_CS2_DIS)
#define ACTIVE_HSPI_CS1 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS1_DIS);\
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS0_DIS |SPI_CS2_DIS)
#define ACTIVE_HSPI_CS2 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS2_DIS);\
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS0_DIS |SPI_CS1_DIS)
#define ENABLE_HSPI_DEV_CS() PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2)
#define DISABLE_HSPI_DEV_CS() GPIO_OUTPUT_SET(15, 1);\
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15)
struct hspi_device_register hspi_dev_reg;
/******************************************************************************
* FunctionName : hspi_overlap_init
* Description : enable hspi and spi module overlap mode
*******************************************************************************/
void ICACHE_FLASH_ATTR
hspi_overlap_init(void)
{
//hspi overlap to spi, two spi masters on cspi
SET_PERI_REG_MASK(HOST_INF_SEL, reg_cspi_overlap);
//set higher priority for spi than hspi
SET_PERI_REG_MASK(SPI_EXT3(SPI),0x1);
SET_PERI_REG_MASK(SPI_EXT3(HSPI),0x3);
SET_PERI_REG_MASK(SPI_USER(HSPI), BIT(5));
}
/******************************************************************************
* FunctionName : hspi_overlap_deinit
* Description : recover hspi and spi module from overlap mode
*******************************************************************************/
void ICACHE_FLASH_ATTR
hspi_overlap_deinit(void)
{
//hspi overlap to spi, two spi masters on cspi
CLEAR_PERI_REG_MASK(HOST_INF_SEL, reg_cspi_overlap);
//set higher priority for spi than hspi
CLEAR_PERI_REG_MASK(SPI_EXT3(SPI),0x1);
CLEAR_PERI_REG_MASK(SPI_EXT3(HSPI),0x3);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), BIT(5));
}
/******************************************************************************
* FunctionName : spi_reg_backup
* Description : backup SPI normal operation register value and disable CPU cache to modify some flash registers.
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_reg_backup(uint8 spi_no,uint32* backup_mem)
{
if(spi_no>1) return; //handle invalid input number
backup_mem[PERIPHS_IO_MUX_BACKUP] =READ_PERI_REG(PERIPHS_IO_MUX);
backup_mem[SPI_USER_BACKUP] =READ_PERI_REG(SPI_USER(spi_no));
backup_mem[SPI_CTRL_BACKUP] =READ_PERI_REG(SPI_CTRL(spi_no));
backup_mem[SPI_CLOCK_BACKUP] =READ_PERI_REG(SPI_CLOCK(spi_no));
backup_mem[SPI_USER1_BACKUP] =READ_PERI_REG(SPI_USER1(spi_no));
backup_mem[SPI_USER2_BACKUP] =READ_PERI_REG(SPI_USER2(spi_no));
backup_mem[SPI_CMD_BACKUP] =READ_PERI_REG(SPI_CMD(spi_no));
backup_mem[SPI_PIN_BACKUP] =READ_PERI_REG(SPI_PIN(spi_no));
backup_mem[SPI_SLAVE_BACKUP] =READ_PERI_REG(SPI_SLAVE(spi_no));
}
/******************************************************************************
* FunctionName : spi_reg_recover
* Description : recover SPI normal operation register value and enable CPU cache.
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
*******************************************************************************/
void ICACHE_FLASH_ATTR
spi_reg_recover(uint8 spi_no,uint32* backup_mem)
{
if(spi_no>1) return; //handle invalid input number
// WRITE_PERI_REG(PERIPHS_IO_MUX, backup_mem[PERIPHS_IO_MUX_BACKUP]);
WRITE_PERI_REG(SPI_USER(spi_no), backup_mem[SPI_USER_BACKUP]);
WRITE_PERI_REG(SPI_CTRL(spi_no), backup_mem[SPI_CTRL_BACKUP]);
WRITE_PERI_REG(SPI_CLOCK(spi_no), backup_mem[SPI_CLOCK_BACKUP]);
WRITE_PERI_REG(SPI_USER1(spi_no), backup_mem[SPI_USER1_BACKUP]);
WRITE_PERI_REG(SPI_USER2(spi_no), backup_mem[SPI_USER2_BACKUP]);
WRITE_PERI_REG(SPI_CMD(spi_no), backup_mem[SPI_CMD_BACKUP]);
WRITE_PERI_REG(SPI_PIN(spi_no), backup_mem[SPI_PIN_BACKUP]);
// WRITE_PERI_REG(SPI_SLAVE(spi_no), backup_mem[SPI_SLAVE_BACKUP]);
}
void ICACHE_FLASH_ATTR
hspi_master_dev_init(uint8 dev_no,uint8 clk_polar,uint8 clk_div)
{
uint32 regtemp;
if((dev_no>3)||(clk_polar>1)||(clk_div>0x1f))
{
os_printf("hspi_master_dev_init parameter is out of range!\n\r");
return;
}
WAIT_HSPI_IDLE();
if(!hspi_dev_reg.hspi_reg_backup_flag){
if(READ_PERI_REG(PERIPHS_IO_MUX)&BIT8){
hspi_dev_reg.spi_io_80m=1;
SET_PERI_REG_MASK(SPI_CLOCK(HSPI),SPI_CLK_EQU_SYSCLK);
}else{
hspi_dev_reg.spi_io_80m=0;
CLEAR_PERI_REG_MASK(SPI_CLOCK(HSPI),SPI_CLK_EQU_SYSCLK);
}
regtemp=READ_PERI_REG(SPI_CTRL(SPI))&SPI_FLASH_READ_MODE_MASK;
CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_FLASH_READ_MODE_MASK);
SET_PERI_REG_MASK(SPI_CTRL(HSPI), regtemp);
spi_reg_backup(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
spi_master_init(HSPI);
spi_reg_backup(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
hspi_dev_reg.hspi_reg_backup_flag=1;
// spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
hspi_dev_reg.selected_dev_num=HSPI_IDLE;
}
hspi_dev_reg.hspi_dev_conf[dev_no].active=1;
hspi_dev_reg.hspi_dev_conf[dev_no].clk_div=clk_div;
hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar=clk_polar;
switch(dev_no){
case HSPI_CS_DEV :
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX, BIT9);
break;
case SPI_CS1_DEV :
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_SPI_CS1);
if(hspi_dev_reg.spi_io_80m){
os_printf("SPI CS1 device must work at 80Mhz");
}
break;
case SPI_CS2_DEV :
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_SPI_CS2);
if(hspi_dev_reg.spi_io_80m){
os_printf("SPI CS2 device must work at 80Mhz");
}
break;
default: break;
}
}
void ICACHE_FLASH_ATTR
hspi_dev_sel(uint8 dev_no)
{
uint32 regval;
if(dev_no>3){
os_printf("hspi_dev_sel parameter is out of range!\n\r");
return;
}
if(!hspi_dev_reg.hspi_dev_conf[dev_no].active){
os_printf("device%d has not been initialized!\n\r",dev_no);
return;
}
switch(hspi_dev_reg.selected_dev_num){
case HSPI_CS_DEV:
if((dev_no==SPI_CS1_DEV)||(dev_no==SPI_CS2_DEV)){
WAIT_HSPI_IDLE();
DISABLE_HSPI_DEV_CS();
hspi_overlap_init();
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
else {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
if(dev_no==SPI_CS1_DEV) {ACTIVE_HSPI_CS1;}
else {ACTIVE_HSPI_CS2;}
}
else if(dev_no==SPI_CS0_FLASH){
WAIT_HSPI_IDLE();
DISABLE_HSPI_DEV_CS();
hspi_overlap_init();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
HSPI_RISING_EDGE_SAMPLE();
ACTIVE_HSPI_CS0 ;
}
break;
case SPI_CS1_DEV:
if(dev_no==SPI_CS2_DEV){
WAIT_HSPI_IDLE();
if(!hspi_dev_reg.spi_io_80m) {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
ACTIVE_HSPI_CS2;
}
else if(dev_no==SPI_CS0_FLASH){
WAIT_HSPI_IDLE();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
HSPI_RISING_EDGE_SAMPLE();
ACTIVE_HSPI_CS0;
}
else if(dev_no==HSPI_CS_DEV){
WAIT_HSPI_IDLE();
ENABLE_HSPI_DEV_CS();
hspi_overlap_deinit();
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
ACTIVE_HSPI_CS0;
}
break;
case SPI_CS2_DEV:
if(dev_no==SPI_CS1_DEV){
WAIT_HSPI_IDLE();
if(!hspi_dev_reg.spi_io_80m) {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
ACTIVE_HSPI_CS1;
}
else if(dev_no==SPI_CS0_FLASH){
WAIT_HSPI_IDLE();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
HSPI_RISING_EDGE_SAMPLE();
ACTIVE_HSPI_CS0;
}
else if(dev_no==HSPI_CS_DEV){
WAIT_HSPI_IDLE();
ENABLE_HSPI_DEV_CS();
hspi_overlap_deinit();
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
ACTIVE_HSPI_CS0;
}
break;
case SPI_CS0_FLASH:
if((dev_no==SPI_CS1_DEV)||(dev_no==SPI_CS2_DEV)){
WAIT_HSPI_IDLE();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
else {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
if(dev_no==SPI_CS1_DEV) {ACTIVE_HSPI_CS1;}
else {ACTIVE_HSPI_CS2;}
}
else if(dev_no==HSPI_CS_DEV){
WAIT_HSPI_IDLE();
ENABLE_HSPI_DEV_CS();
hspi_overlap_deinit();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
ACTIVE_HSPI_CS0;
}
break;
default:
if((dev_no==SPI_CS1_DEV)||(dev_no==SPI_CS2_DEV)){
WAIT_HSPI_IDLE();
DISABLE_HSPI_DEV_CS();
hspi_overlap_init();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
else {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
if(dev_no==SPI_CS1_DEV) {ACTIVE_HSPI_CS1;}
else {ACTIVE_HSPI_CS2;}
}
else if(dev_no==SPI_CS0_FLASH){
WAIT_HSPI_IDLE();
DISABLE_HSPI_DEV_CS();
hspi_overlap_init();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
HSPI_RISING_EDGE_SAMPLE();
ACTIVE_HSPI_CS0 ;
}
else if(dev_no==HSPI_CS_DEV){
WAIT_HSPI_IDLE();
ENABLE_HSPI_DEV_CS();
hspi_overlap_deinit();
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
else {HSPI_RISING_EDGE_SAMPLE();}
ACTIVE_HSPI_CS0;
}
break;
}
hspi_dev_reg.selected_dev_num=dev_no;
}
/******************************************************************************
* FunctionName : spi_read_data
* Description : use hspi to read flash data for stability test
* Parameters : SpiFlashChip * spi-- flash parameter structure pointer
* uint32 flash_addr--flash start address
* uint32 * addr_dest--start address for preped destination memory space
* uint32 byte_length--length of the data which needs to be read from flash
*******************************************************************************/
SpiFlashOpResult ICACHE_FLASH_ATTR
hspi_overlap_read_flash_data(SpiFlashChip * spi, uint32 flash_addr, uint32 * addr_dest, uint32 byte_length)
{
uint32 temp_addr,reg_tmp;
sint32 temp_length;
uint8 i;
uint8 remain_word_num;
hspi_dev_sel(SPI_CS0_FLASH);
//address range check
if ((flash_addr+byte_length) > (spi->chip_size))
{
return SPI_FLASH_RESULT_ERR;
}
temp_addr = flash_addr;
temp_length = byte_length;
while(temp_length > 0)
{
if(temp_length >= SPI_BUFF_BYTE_NUM)
{
// reg_tmp=((temp_addr&0xff)<<16)|(temp_addr&0xff00)|((temp_addr&0xff0000)>>16)|(SPI_BUFF_BYTE_NUM << SPI_FLASH_BYTES_LEN);
reg_tmp= temp_addr |(SPI_BUFF_BYTE_NUM<< SPI_FLASH_BYTES_LEN) ;
WRITE_PERI_REG(SPI_ADDR(HSPI), reg_tmp);
WRITE_PERI_REG(SPI_CMD(HSPI), SPI_FLASH_READ);
while(READ_PERI_REG(SPI_CMD(HSPI)) != 0);
for(i=0; i<(SPI_BUFF_BYTE_NUM>>2);i++)
{
*addr_dest++ = READ_PERI_REG(SPI_W0(HSPI)+i*4);
}
temp_length = temp_length - SPI_BUFF_BYTE_NUM;
temp_addr = temp_addr + SPI_BUFF_BYTE_NUM;
}
else
{
WRITE_PERI_REG(SPI_ADDR(HSPI), temp_addr |(temp_length << SPI_FLASH_BYTES_LEN ));
WRITE_PERI_REG(SPI_CMD(HSPI), SPI_FLASH_READ);
while(READ_PERI_REG(SPI_CMD(HSPI)) != 0);
remain_word_num = (0== (temp_length&0x3))? (temp_length>>2) : (temp_length>>2)+1;
for (i=0; i<remain_word_num; i++)
{
*addr_dest++ = READ_PERI_REG(SPI_W0(HSPI)+i*4);
}
temp_length = 0;
}
}
return SPI_FLASH_RESULT_OK;
}
void ICACHE_FLASH_ATTR
hspi_overlap_flash_init(void)
{
hspi_master_dev_init(SPI_CS0_FLASH,0,0);
spi_flash_set_read_func(hspi_overlap_read_flash_data);
}
\ No newline at end of file
/*
* 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"
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
LOCAL struct UartBuffer* pTxBuffer = NULL;
LOCAL struct UartBuffer* pRxBuffer = NULL;
/*uart demo with a system task, to output what uart receives*/
/*this is a example to process uart data from task,please change the priority to fit your application task if exists*/
/*it might conflict with your task, if so,please arrange the priority of different task, or combine it to a different event in the same task. */
#define uart_recvTaskPrio 0
#define uart_recvTaskQueueLen 10
os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen];
#define DBG
#define DBG1 uart1_sendStr_no_wait
#define DBG2 os_printf
LOCAL void uart0_rx_intr_handler(void *para);
/******************************************************************************
* 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){
//set rx fifo trigger
WRITE_PERI_REG(UART_CONF1(uart_no),
((100 & 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 : uart1_tx_one_char
* Description : Internal used function
* Use uart1 interface to transfer one char
* Parameters : uint8 TxChar - character to tx
* Returns : OK
*******************************************************************************/
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 : uart1_write_char
* Description : Internal used function
* Do some special deal while tx char is '\r' or '\n'
* Parameters : char c - character to tx
* Returns : NONE
*******************************************************************************/
LOCAL 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);
}
}
//os_printf output to fifo or to the tx buffer
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_no_wait(UART0, '\r');
uart_tx_one_char_no_wait(UART0, '\n');
}else if (c == '\r'){
}
else{
uart_tx_one_char_no_wait(UART0, c);
}
#endif
}
/******************************************************************************
* FunctionName : uart0_tx_buffer
* Description : use uart0 to transfer buffer
* Parameters : uint8 *buf - point to send buffer
* uint16 len - buffer len
* Returns :
*******************************************************************************/
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]);
}
}
/******************************************************************************
* FunctionName : uart0_sendStr
* Description : use uart0 to transfer buffer
* Parameters : uint8 *buf - point to send buffer
* uint16 len - buffer len
* Returns :
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart0_sendStr(const char *str)
{
while(*str){
uart_tx_one_char(UART0, *str++);
}
}
void at_port_print(const char *str) __attribute__((alias("uart0_sendStr")));
/******************************************************************************
* 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
*******************************************************************************/
LOCAL void
uart0_rx_intr_handler(void *para)
{
/* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
* uart1 and uart0 respectively
*/
uint8 RcvChar;
uint8 uart_no = UART0;//UartDev.buff_uart_no;
uint8 fifo_len = 0;
uint8 buf_idx = 0;
uint8 temp,cnt;
//RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;
/*ATTENTION:*/
/*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/
/*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */
/*IF NOT , POST AN EVENT AND PROCESS IN SYSTEM TASK */
if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)){
DBG1("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)){
DBG("f");
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
system_os_post(uart_recvTaskPrio, 0, 0);
}else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)){
DBG("t");
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
system_os_post(uart_recvTaskPrio, 0, 0);
}else if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)){
DBG("e");
/* to output uart data from uart buffer directly in empty interrupt handler*/
/*instead of processing in system event, in order not to wait for current task/function to quit */
/*ATTENTION:*/
/*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/
/*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */
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);
}else if(UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST)){
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR);
DBG1("RX OVF!!\r\n");
}
}
/******************************************************************************
* FunctionName : uart_init
* Description : user interface for init uart
* Parameters : UartBautRate uart0_br - uart0 bautrate
* UartBautRate uart1_br - uart1 bautrate
* Returns : NONE
*******************************************************************************/
#if UART_SELFTEST&UART_BUFF_EN
os_timer_t buff_timer_t;
void ICACHE_FLASH_ATTR
uart_test_rx()
{
uint8 uart_buf[128]={0};
uint16 len = 0;
len = rx_buff_deq(uart_buf, 128 );
tx_buff_enq(uart_buf,len);
}
#endif
LOCAL void ICACHE_FLASH_ATTR ///////
uart_recvTask(os_event_t *events)
{
if(events->sig == 0){
#if UART_BUFF_EN
Uart_rx_buff_enq();
#else
uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
uint8 d_tmp = 0;
uint8 idx=0;
for(idx=0;idx<fifo_len;idx++) {
d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
uart_tx_one_char(UART0, d_tmp);
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
uart_rx_intr_enable(UART0);
#endif
}else if(events->sig == 1){
#if UART_BUFF_EN
//already move uart buffer output to uart empty interrupt
//tx_start_uart_buffer(UART0);
#else
#endif
}
}
void ICACHE_FLASH_ATTR
uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
{
/*this is a example to process uart data from task,please change the priority to fit your application task if exists*/
system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen); //demo with a task to process the uart data
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
#if UART_BUFF_EN
pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE);
pRxBuffer = Uart_Buf_Init(UART_RX_BUFFER_SIZE);
#endif
/*option 1: use default print, output from uart0 , will wait some time if fifo is full */
//do nothing...
/*option 2: output from uart1,uart1 output will not wait , just for output debug info */
/*os_printf output uart data via uart1(GPIO2)*/
//os_install_putc1((void *)uart1_write_char); //use this one to output debug information via uart1 //
/*option 3: output from uart0 will skip current byte if fifo is full now... */
/*see uart0_write_char_no_wait:you can output via a buffer or output directly */
/*os_printf output uart data via uart0 or uart buffer*/
//os_install_putc1((void *)uart0_write_char_no_wait); //use this to print via uart0
#if UART_SELFTEST&UART_BUFF_EN
os_timer_disarm(&buff_timer_t);
os_timer_setfn(&buff_timer_t, uart_test_rx , NULL); //a demo to process the data in uart rx buffer
os_timer_arm(&buff_timer_t,10,1);
#endif
}
void ICACHE_FLASH_ATTR
uart_reattach()
{
uart_init(BIT_RATE_115200, BIT_RATE_115200);
}
/******************************************************************************
* 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;
}
STATUS uart0_tx_one_char_no_wait(uint8 TxChar)
{
uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(UART0))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT);
if (fifo_cnt < 126) {
WRITE_PERI_REG(UART_FIFO(UART0) , TxChar);
}
return OK;
}
/******************************************************************************
* FunctionName : uart1_sendStr_no_wait
* Description : uart tx a string without waiting for every char, used for print debug info which can be lost
* Parameters : const char *str - string to be sent
* Returns : NONE
*******************************************************************************/
void uart1_sendStr_no_wait(const char *str)
{
while(*str){
uart_tx_one_char_no_wait(UART1, *str++);
}
}
#if UART_BUFF_EN
/******************************************************************************
* FunctionName : Uart_Buf_Init
* Description : tx buffer enqueue: fill a first linked buffer
* Parameters : char *pdata - data point to be enqueue
* Returns : NONE
*******************************************************************************/
struct UartBuffer* ICACHE_FLASH_ATTR
Uart_Buf_Init(uint32 buf_size)
{
uint32 heap_size = system_get_free_heap_size();
if(heap_size <=buf_size){
DBG1("no buf for uart\n\r");
return NULL;
}else{
DBG("test heap size: %d\n\r",heap_size);
struct UartBuffer* pBuff = (struct UartBuffer* )os_malloc(sizeof(struct UartBuffer));
pBuff->UartBuffSize = buf_size;
pBuff->pUartBuff = (uint8*)os_malloc(pBuff->UartBuffSize);
pBuff->pInPos = pBuff->pUartBuff;
pBuff->pOutPos = pBuff->pUartBuff;
pBuff->Space = pBuff->UartBuffSize;
pBuff->BuffState = OK;
pBuff->nextBuff = NULL;
pBuff->TcpControl = RUN;
return pBuff;
}
}
//copy uart buffer
LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len)
{
if(data_len == 0) return ;
uint16 tail_len = pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos ;
if(tail_len >= data_len){ //do not need to loop back the queue
os_memcpy(pCur->pInPos , pdata , data_len );
pCur->pInPos += ( data_len );
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize );
pCur->Space -=data_len;
}else{
os_memcpy(pCur->pInPos, pdata, tail_len);
pCur->pInPos += ( tail_len );
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize );
pCur->Space -=tail_len;
os_memcpy(pCur->pInPos, pdata+tail_len , data_len-tail_len);
pCur->pInPos += ( data_len-tail_len );
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize );
pCur->Space -=( data_len-tail_len);
}
}
/******************************************************************************
* FunctionName : uart_buf_free
* Description : deinit of the tx buffer
* Parameters : struct UartBuffer* pTxBuff - tx buffer struct pointer
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart_buf_free(struct UartBuffer* pBuff)
{
os_free(pBuff->pUartBuff);
os_free(pBuff);
}
//rx buffer dequeue
uint16 ICACHE_FLASH_ATTR
rx_buff_deq(char* pdata, uint16 data_len )
{
uint16 buf_len = (pRxBuffer->UartBuffSize- pRxBuffer->Space);
uint16 tail_len = pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize - pRxBuffer->pOutPos ;
uint16 len_tmp = 0;
len_tmp = ((data_len > buf_len)?buf_len:data_len);
if(pRxBuffer->pOutPos <= pRxBuffer->pInPos){
os_memcpy(pdata, pRxBuffer->pOutPos,len_tmp);
pRxBuffer->pOutPos+= len_tmp;
pRxBuffer->Space += len_tmp;
}else{
if(len_tmp>tail_len){
os_memcpy(pdata, pRxBuffer->pOutPos, tail_len);
pRxBuffer->pOutPos += tail_len;
pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize );
pRxBuffer->Space += tail_len;
os_memcpy(pdata+tail_len , pRxBuffer->pOutPos, len_tmp-tail_len);
pRxBuffer->pOutPos+= ( len_tmp-tail_len );
pRxBuffer->pOutPos= (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize );
pRxBuffer->Space +=( len_tmp-tail_len);
}else{
//os_printf("case 3 in rx deq\n\r");
os_memcpy(pdata, pRxBuffer->pOutPos, len_tmp);
pRxBuffer->pOutPos += len_tmp;
pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize );
pRxBuffer->Space += len_tmp;
}
}
if(pRxBuffer->Space >= UART_FIFO_LEN){
uart_rx_intr_enable(UART0);
}
return len_tmp;
}
//move data from uart fifo to rx buffer
void Uart_rx_buff_enq()
{
uint8 fifo_len,buf_idx;
uint8 fifo_data;
#if 1
fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
if(fifo_len >= pRxBuffer->Space){
os_printf("buf full!!!\n\r");
}else{
buf_idx=0;
while(buf_idx < fifo_len){
buf_idx++;
fifo_data = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
*(pRxBuffer->pInPos++) = fifo_data;
if(pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)){
pRxBuffer->pInPos = pRxBuffer->pUartBuff;
}
}
pRxBuffer->Space -= fifo_len ;
if(pRxBuffer->Space >= UART_FIFO_LEN){
//os_printf("after rx enq buf enough\n\r");
uart_rx_intr_enable(UART0);
}
}
#endif
}
//fill the uart tx buffer
void ICACHE_FLASH_ATTR
tx_buff_enq(char* pdata, uint16 data_len )
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
if(pTxBuffer == NULL){
DBG1("\n\rnull, create buffer struct\n\r");
pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE);
if(pTxBuffer!= NULL){
Uart_Buf_Cpy(pTxBuffer , pdata, data_len );
}else{
DBG1("uart tx MALLOC no buf \n\r");
}
}else{
if(data_len <= pTxBuffer->Space){
Uart_Buf_Cpy(pTxBuffer , pdata, data_len);
}else{
DBG1("UART TX BUF FULL!!!!\n\r");
}
}
#if 0
if(pTxBuffer->Space <= URAT_TX_LOWER_SIZE){
set_tcp_block();
}
#endif
SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S);
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
}
//--------------------------------
LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no)
{
uint8 i;
for(i = 0; i<data_len;i++){
WRITE_PERI_REG(UART_FIFO(uart_no) , *(pTxBuff->pOutPos++));
if(pTxBuff->pOutPos == (pTxBuff->pUartBuff + pTxBuff->UartBuffSize)){
pTxBuff->pOutPos = pTxBuff->pUartBuff;
}
}
pTxBuff->pOutPos = (pTxBuff->pUartBuff + (pTxBuff->pOutPos - pTxBuff->pUartBuff) % pTxBuff->UartBuffSize );
pTxBuff->Space += data_len;
}
/******************************************************************************
* FunctionName : tx_start_uart_buffer
* Description : get data from the tx buffer and fill the uart tx fifo, co-work with the uart fifo empty interrupt
* Parameters : uint8 uart_no - uart port num
* Returns : NONE
*******************************************************************************/
void tx_start_uart_buffer(uint8 uart_no)
{
uint8 tx_fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT;
uint8 fifo_remain = UART_FIFO_LEN - tx_fifo_len ;
uint8 len_tmp;
uint16 tail_ptx_len,head_ptx_len,data_len;
//struct UartBuffer* pTxBuff = *get_buff_prt();
if(pTxBuffer){
data_len = (pTxBuffer->UartBuffSize - pTxBuffer->Space);
if(data_len > fifo_remain){
len_tmp = fifo_remain;
tx_fifo_insert( pTxBuffer,len_tmp,uart_no);
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
}else{
len_tmp = data_len;
tx_fifo_insert( pTxBuffer,len_tmp,uart_no);
}
}else{
DBG1("pTxBuff null \n\r");
}
}
#endif
void uart_rx_intr_disable(uint8 uart_no)
{
#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
}
void uart_rx_intr_enable(uint8 uart_no)
{
#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
}
//========================================================
LOCAL void
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
UART_SetWordLength(uint8 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(uint8 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(uint8 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(uint8 uart_no, UartParityMode Parity_mode)
{
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY |UART_PARITY_EN);
if(Parity_mode==NONE_BITS){
}else{
SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode|UART_PARITY_EN);
}
}
void ICACHE_FLASH_ATTR
UART_SetBaudrate(uint8 uart_no,uint32 baud_rate)
{
uart_div_modify(uart_no, UART_CLK_FREQ /baud_rate);
}
void ICACHE_FLASH_ATTR
UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh)
{
if(flow_ctrl&USART_HardwareFlowControl_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_HardwareFlowControl_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(uint8 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;
}
WRITE_PERI_REG(0X60000914, 0X73);//WTD
}
}
bool ICACHE_FLASH_ATTR
UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us)
{
uint32 t_start = system_get_time();
uint8 tx_fifo_len;
uint32 tx_buff_len;
while(1){
tx_fifo_len =( (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT);
if(pTxBuffer){
tx_buff_len = ((pTxBuffer->UartBuffSize)-(pTxBuffer->Space));
}else{
tx_buff_len = 0;
}
if( tx_fifo_len==0 && tx_buff_len==0){
return TRUE;
}
if( system_get_time() - t_start > time_out_us){
return FALSE;
}
WRITE_PERI_REG(0X60000914, 0X73);//WTD
}
}
void ICACHE_FLASH_ATTR
UART_ResetFifo(uint8 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(uint8 uart_no,uint32 clr_mask)
{
WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
}
void ICACHE_FLASH_ATTR
UART_SetIntrEna(uint8 uart_no,uint32 ena_mask)
{
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
}
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);
}
}
//========================================================
/*test code*/
void ICACHE_FLASH_ATTR
uart_init_2(UartBautRate uart0_br, UartBautRate uart1_br)
{
// rom use 74880 baut_rate, here reinitialize
UartDev.baut_rate = uart0_br;
UartDev.exist_parity = STICK_PARITY_EN;
UartDev.parity = EVEN_BITS;
UartDev.stop_bits = ONE_STOP_BIT;
UartDev.data_bits = EIGHT_BITS;
uart_config(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
// install uart1 putc callback
os_install_putc1((void *)uart1_write_char);//print output at UART1
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment