Commit of ESP8266 board specific source files.

This commit is contained in:
Neil Kolban 2015-09-27 09:16:33 -05:00
parent 32a66b2a1c
commit 4eeb12d292
18 changed files with 4728 additions and 0 deletions

View File

@ -0,0 +1,949 @@
#include <c_types.h>
#include <user_interface.h>
#include <mem.h>
#include <osapi.h>
#include <ping.h>
#include <espconn.h>
#include <espmissingincludes.h>
#include <driver/uart.h>
#define ESP8266_ON_ACCESS_POINTS "#accessPoints"
#define _GCC_WRAP_STDINT_H
typedef long long int64_t;
#include "jswrap_esp8266.h"
#include "jsinteractive.h" // Pull inn the jsiConsolePrint function
#include "network.h"
#include "network_esp8266.h"
#include "jswrap_net.h"
// Forward declaration of functions.
static void scanCB(void *arg, STATUS status);
static void wifiEventHandler(System_Event_t *event);
static void ipAddrToString(struct ip_addr addr, char *string);
static char *nullTerminateString(char *target, char *source, int sourceLength);
static void setupJsNetwork();
static void pingRecvCB();
static JsVar *jsScanCallback;
static JsVar *jsWiFiEventCallback;
// A callback function to be invoked when we have an IP address.
static JsVar *jsGotIpCallback;
static JsVar *jsPingCallback;
// Global data structure for ping request
static struct ping_option pingOpt;
// Let's define the JavaScript class that will contain our `world()` method. We'll call it `Hello`
/*JSON{
"type" : "class",
"class" : "ESP8266WiFi"
}*/
/**
* \brief Connect the station to an access point.
* - `ssid` - The network id of the access point.
* - `password` - The password to use to connect to the access point.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "connect",
"generate" : "jswrap_ESP8266WiFi_connect",
"params" : [
["ssid","JsVar","The network SSID"],
["password","JsVar","The password to the access point"],
["gotIpCallback", "JsVar", "An optional callback invoked when we have an IP"]
]
}*/
void jswrap_ESP8266WiFi_connect(JsVar *jsv_ssid, JsVar *jsv_password, JsVar *gotIpCallback) {
// Check that the ssid and password values aren't obviously in error.
if (jsv_ssid == NULL || !jsvIsString(jsv_ssid)) {
jsExceptionHere(JSET_ERROR, "No SSID.");
return;
}
if (jsv_password == NULL || !jsvIsString(jsv_password)) {
jsExceptionHere(JSET_ERROR, "No password.");
return;
}
// Check that if a callback function was supplied that we actually have a callback function.
if (gotIpCallback != NULL && !jsvIsUndefined(gotIpCallback) && !jsvIsFunction(gotIpCallback)) {
gotIpCallback = NULL;
jsExceptionHere(JSET_ERROR, "A callback function was supplied that is not a function.");
return;
}
if (jsvIsUndefined(gotIpCallback) || jsvIsNull(gotIpCallback)) {
gotIpCallback = NULL;
}
// Set the global which is the gotIP callback
if (jsGotIpCallback != NULL) {
jsvUnLock(jsGotIpCallback);
jsGotIpCallback = NULL;
}
if (gotIpCallback != NULL) {
jsGotIpCallback = jsvLockAgainSafe(gotIpCallback);
}
// Create strings from the JsVars for the ESP8266 API calls.
char ssid[33];
int len = jsvGetString(jsv_ssid, ssid, sizeof(ssid)-1);
ssid[len]='\0';
char password[65];
len = jsvGetString(jsv_password, password, sizeof(password)-1);
password[len]='\0';
jsiConsolePrintf("jswrap_ESP8266WiFi_connect: %s - %s\r\n", ssid, password);
// Set the WiFi mode of the ESP8266
wifi_set_opmode_current(STATION_MODE);
struct station_config stationConfig;
memset(&stationConfig, 0, sizeof(stationConfig));
os_strncpy((char *)stationConfig.ssid, ssid, 32);
if (password != NULL) {
os_strncpy((char *)stationConfig.password, password, 64);
} else {
os_strcpy((char *)stationConfig.password, "");
}
// Set the WiFi configuration
wifi_station_set_config(&stationConfig);
// Register the event handler
wifi_set_event_handler_cb(wifiEventHandler);
wifi_station_connect();
} // End of jswrap_ESP8266WiFi_connect
/**
* \brief Become an access point.
* When we call this function we are instructing the ESP8266 to set itself up as an
* access point to allow other WiFi stations to connect to it. In order to be an access
* point, the ESP8266 needs to know the SSID it should use as well as the password used
* to allow clients to connect.
*
* Parameters:
* - `jsv_ssid` - The network identity that the access point will advertize itself as.
* - `jsv_password` - The password a station will need to connect to the
* access point.
*
* Notes:
* - How about if the password is not supplied, NULL or empty then we set ourselves
* up using an Open authentication mechanism?
* - Add support for hidden SSIDs.
*
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "beAccessPoint",
"generate" : "jswrap_ESP8266WiFi_beAccessPoint",
"params" : [
["jsv_ssid","JsVar","The network SSID"],
["jsv_password","JsVar","The password to allow stations to connect to the access point"]
]
}*/
void jswrap_ESP8266WiFi_beAccessPoint(
JsVar *jsv_ssid, //!< The network identity that the access point will advertize itself as.
JsVar *jsv_password //!< The password a station will need to connect to the access point.
) {
// Validate that the SSID and password are somewhat useful.
if (jsv_ssid == NULL || !jsvIsString(jsv_ssid)) {
jsExceptionHere(JSET_ERROR, "No SSID.");
return;
}
if (jsv_password == NULL || !jsvIsString(jsv_password)) {
jsExceptionHere(JSET_ERROR, "No password.");
return;
}
// Create strings from the JsVars for the ESP8266 API calls.
char ssid[33];
int len = jsvGetString(jsv_ssid, ssid, sizeof(ssid)-1);
ssid[len]='\0';
char password[65];
len = jsvGetString(jsv_password, password, sizeof(password)-1);
password[len]='\0';
// Define that we are in Soft AP mode.
wifi_set_opmode_current(SOFTAP_MODE);
// Build our SoftAP configuration details
struct softap_config softApConfig;
memset(&softApConfig, 0, sizeof(softApConfig));
os_strcpy((char *)softApConfig.ssid, ssid);
os_strcpy((char *)softApConfig.password, password);
softApConfig.ssid_len = 0; // Null terminated SSID
softApConfig.authmode = AUTH_WPA2_PSK;
softApConfig.ssid_hidden = 0; // Not hidden.
softApConfig.max_connection = 4; // Maximum number of connections.
// Set the WiFi configuration.
int rc = wifi_softap_set_config_current(&softApConfig);
if (rc != 1) {
jsExceptionHere(JSET_ERROR, "Error setting ESP8266 softap config.");
}
} // End of jswrap_ESP8266WiFi_beAccessPoint
/**
* \brief Determine the list of access points available to us.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getAccessPoints",
"generate" : "jswrap_ESP8266WiFi_getAccessPoints",
"params" : [
["callback","JsVar","Function to call back when access points retrieved."]
]
}*/
void jswrap_ESP8266WiFi_getAccessPoints(
JsVar *callback //!< Function to call back when access points retrieved.
) {
jsiConsolePrint("> ESP8266WiFi_getAccessPoints\n");
if (callback == NULL || !jsvIsFunction(callback)) {
jsExceptionHere(JSET_ERROR, "No callback.");
return;
}
// Save the callback for the scan
jsScanCallback = jsvLockAgainSafe(callback);
// Ask the ESP8266 to perform a network scan after first entering
// station mode. This will result in an eventual callback which is where
// Ensure we are in station mode
wifi_set_opmode_current(STATION_MODE);
// Request a scan of the network calling "scanCB" on completion
wifi_station_scan(NULL, scanCB);
jsiConsolePrint("< ESP8266WiFi_getAccessPoints\n");
} // End of jswrap_ESP8266WiFi_getAccessPoints
/**
* \brief Disconnect the station from the access point.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "disconnect",
"generate" : "jswrap_ESP8266WiFi_disconnect"
}*/
void jswrap_ESP8266WiFi_disconnect() {
wifi_station_disconnect();
} // End of jswrap_ESP8266WiFi_disconnect
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "restart",
"generate" : "jswrap_ESP8266WiFi_restart"
}*/
void jswrap_ESP8266WiFi_restart() {
system_restart();
} // End of jswrap_ESP8266WiFi_restart
/**
* \brief Register a callback function that will be invoked when a WiFi event is detected.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "onWiFiEvent",
"generate" : "jswrap_ESP8266WiFi_onWiFiEvent",
"params" : [
["callback","JsVar","WiFi event callback"]
]
}*/
void jswrap_ESP8266WiFi_onWiFiEvent(
JsVar *callback //!< WiFi event callback.
) {
// If the callback is null
if (callback == NULL || jsvIsNull(callback)) {
if (jsWiFiEventCallback != NULL) {
jsvUnLock(jsWiFiEventCallback);
}
jsWiFiEventCallback = NULL;
return;
}
if (!jsvIsFunction(callback)) {
jsExceptionHere(JSET_ERROR, "No callback.");
return;
}
// We are about to save a new global WiFi even callback handler. If we have previously
// had one, we need to unlock it so that we don't leak memory.
if (jsWiFiEventCallback != NULL) {
jsvUnLock(jsWiFiEventCallback);
}
// Save the global WiFi event callback handler.
jsWiFiEventCallback = jsvLockAgainSafe(callback);
// Register
wifi_set_event_handler_cb(wifiEventHandler);
} // End of jswrap_ESP8266WiFi_onWiFiEvent
/**
* \brief Set whether or not the ESP8266 will perform an auto connect on startup.
* A value of true means it will while a value of false means it won't.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "setAutoConnect",
"generate" : "jswrap_ESP8266WiFi_setAutoConnect",
"params" : [
["autoconnect","JsVar","True if we wish to auto connect."]
]
}*/
void jswrap_ESP8266WiFi_setAutoConnect(
JsVar *autoconnect //!< True if we wish to auto connect.
) {
os_printf("Auto connect is: %d\n", (int)autoconnect);
// Check that we have been passed a boolean ... if not, nothing to do here.
if (!jsvIsBoolean(autoconnect)) {
return;
}
uint8 newValue = jsvGetBool(autoconnect);
os_printf("New value: %d\n", newValue);
os_printf("jswrap_ESP8266WiFi_setAutoConnect -> Something breaks here :-(\n");
uart_rx_intr_disable(0);
wifi_station_set_auto_connect(newValue);
uart_rx_intr_disable(1);
os_printf("Autoconnect changed\n");
} // End of jswrap_ESP8266WiFi_setAutoconnect
/**
* \brief Retrieve whether or not the ESP8266 will perform an auto connect on startup.
* A value of 1 means it will while a value of zero means it won't.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getAutoConnect",
"generate" : "jswrap_ESP8266WiFi_getAutoConnect",
"return" : ["JsVar","A boolean representing our auto connect status"]
}*/
JsVar *jswrap_ESP8266WiFi_getAutoConnect() {
uint8 result = wifi_station_get_auto_connect();
return jsvNewFromBool(result);
} // End of jswrap_ESP8266WiFi_getAutoconnect
/**
* \brief Retrieve the reset information that is stored when event the ESP8266 resets.
* The result will be a JS object containing the details.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getRstInfo",
"generate" : "jswrap_ESP8266WiFi_getRstInfo",
"return" : ["JsVar","A Restart Object"],
"return_object" : "Restart"
}*/
JsVar *jswrap_ESP8266WiFi_getRstInfo() {
struct rst_info* info = system_get_rst_info();
JsVar *restartInfo = jspNewObject(NULL, "Restart");
jsvUnLock(jsvObjectSetChild(restartInfo, "reason", jsvNewFromInteger(info->reason)));
jsvUnLock(jsvObjectSetChild(restartInfo, "exccause", jsvNewFromInteger(info->exccause)));
jsvUnLock(jsvObjectSetChild(restartInfo, "epc1", jsvNewFromInteger(info->epc1)));
jsvUnLock(jsvObjectSetChild(restartInfo, "epc2", jsvNewFromInteger(info->epc2)));
jsvUnLock(jsvObjectSetChild(restartInfo, "epc3", jsvNewFromInteger(info->epc3)));
jsvUnLock(jsvObjectSetChild(restartInfo, "excvaddr", jsvNewFromInteger(info->excvaddr)));
jsvUnLock(jsvObjectSetChild(restartInfo, "depc", jsvNewFromInteger(info->depc)));
return restartInfo;
} // End of jswrap_ESP8266WiFi_getRstInfo
/**
* \brief Return an object that contains details about the state of the ESP8266.
* - `sdkVersion` - Version of the SDK.
* - `cpuFrequency` - CPU operating frequency.
* - `freeHeap` - Amount of free heap.
* - `maxCon` - Maximum number of concurrent connections.
*
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getState",
"generate" : "jswrap_ESP8266WiFi_getState",
"return" : ["JsVar","The state of the ESP8266"],
"return_object" : "ESP8266State"
}*/
JsVar *jswrap_ESP8266WiFi_getState() {
// Create a new variable and populate it with the properties of the ESP8266 that we
// wish to return.
JsVar *esp8266State = jspNewObject(NULL, "ESP8266State");
jsvUnLock(jsvObjectSetChild(esp8266State, "sdkVersion", jsvNewFromString(system_get_sdk_version())));
jsvUnLock(jsvObjectSetChild(esp8266State, "cpuFrequency", jsvNewFromInteger(system_get_cpu_freq())));
jsvUnLock(jsvObjectSetChild(esp8266State, "freeHeap", jsvNewFromInteger(system_get_free_heap_size())));
jsvUnLock(jsvObjectSetChild(esp8266State, "maxCon", jsvNewFromInteger(espconn_tcp_get_max_con())));
return esp8266State;
} // End of jswrap_ESP8266WiFi_getState
/**
* \brief Return the value of an integer representation (4 bytes) of IP address
* as a string.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getAddressAsString",
"generate" : "jswrap_ESP8266WiFi_getAddressAsString",
"params" : [
["address","JsVar","An integer value representing an IP address."]
],
"return" : ["JsVar","A String"]
}*/
JsVar *jswrap_ESP8266WiFi_getAddressAsString(
JsVar *address //!< An integer value representing an IP address.
) {
if (!jsvIsInt(address)) {
jsExceptionHere(JSET_ERROR, "No SSID.");
return NULL;
}
uint32 iAddress = (uint32)jsvGetInteger(address);
return networkGetAddressAsString((uint8 *)&iAddress, 4, 10, '.');
} // End of jswrap_ESP8266WiFi_getAddressAsString
/**
* \brief Retrieve the IP information about this network interface and return a JS
* object that contains its details.
* The object will have the following properties defined upon it:
* - `ip` - The IP address of the interface.
* - `netmask` - The netmask of the interface.
* - `gw` - The gateway to reach when transmitting through the interface.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getIPInfo",
"generate" : "jswrap_ESP8266WiFi_getIPInfo",
"return" : ["JsVar","A IPInfo Object"],
"return_object" : "IPInfo"
}*/
JsVar *jswrap_ESP8266WiFi_getIPInfo() {
struct ip_info info;
wifi_get_ip_info(0, &info);
JsVar *ipInfo = jspNewObject(NULL, "Restart");
jsvUnLock(jsvObjectSetChild(ipInfo, "ip", jsvNewFromInteger(info.ip.addr)));
jsvUnLock(jsvObjectSetChild(ipInfo, "netmask", jsvNewFromInteger(info.netmask.addr)));
jsvUnLock(jsvObjectSetChild(ipInfo, "gw", jsvNewFromInteger(info.gw.addr)));
return ipInfo;
} // End of jswrap_ESP8266WiFi_getIPInfo
/**
* \brief Query the station configuration and return a JS object that represents the
* current settings.
* The object will have the following properties:
*
* - `ssid` - The network identity of the access point
* - `password` - The password to use to connect to the access point
*
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getStationConfig",
"generate" : "jswrap_ESP8266WiFi_getStationConfig",
"return" : ["JsVar","A Station Config"],
"return_object" : "StationConfig"
}*/
JsVar *jswrap_ESP8266WiFi_getStationConfig() {
struct station_config config;
wifi_station_get_config(&config);
JsVar *jsConfig = jspNewObject(NULL, "StationConfig");
//char ssid[33];
//nullTerminateString(ssid, (char *)config.ssid, 32);
jsvUnLock(jsvObjectSetChild(jsConfig, "ssid", jsvNewFromString((char *)config.ssid)));
//char password[65];
//nullTerminateString(password, (char *)config.password, 64);
jsvUnLock(jsvObjectSetChild(jsConfig, "password", jsvNewFromString((char *)config.password)));
return jsConfig;
} // End of jswrap_ESP8266WiFi_getStationConfig
/**
* \brief Determine the list of connected stations and return them.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getConnectedStations",
"generate" : "jswrap_ESP8266WiFi_getConnectedStations",
"return" : ["JsVar","An array of connected stations."]
}*/
JsVar *jswrap_ESP8266WiFi_getConnectedStations() {
uint8 stationCount = wifi_softap_get_station_num();
struct station_info *stationInfo = wifi_softap_get_station_info();
JsVar *jsArray = jsvNewArray(NULL, 0);
if (stationInfo != NULL) {
while (stationInfo != NULL) {
os_printf("Station IP: %d.%d.%d.%d\n", IP2STR(&(stationInfo->ip)));
JsVar *jsStation = jsvNewWithFlags(JSV_OBJECT);
jsvUnLock(jsvObjectSetChild(jsStation, "ip", jsvNewFromInteger(stationInfo->ip.addr)));
jsvArrayPush(jsArray, jsStation);
stationInfo = STAILQ_NEXT(stationInfo, next);
}
wifi_softap_free_station_info();
}
return jsArray;
} // End of jswrap_ESP8266WiFi_getConnectedStations
/**
* \brief Get the signal strength.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getRSSI",
"generate" : "jswrap_ESP8266WiFi_getRSSI",
"return" : ["JsVar","An integer representing the signal strength."]
}*/
JsVar *jswrap_ESP8266WiFi_getRSSI() {
int rssi = wifi_station_get_rssi();
return jsvNewFromInteger(rssi);
} // End of jswrap_ESP8266WiFi_getRSSI
/**
* \brief Initialize the ESP8266 environment.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "init",
"generate" : "jswrap_ESP8266WiFi_init"
}*/
void jswrap_ESP8266WiFi_init() {
os_printf("> jswrap_ESP8266WiFi_init\n");
netInit_esp8266_board();
setupJsNetwork();
networkState = NETWORKSTATE_ONLINE;
os_printf("< jswrap_ESP8266WiFi_init\n");
} // End of jswrap_ESP8266WiFi_init
/**
* Return the ESP8266 connection status.
* This is an integer value defined as:
* - 0 - STATION_IDLE
* - 1 - STATION_CONNECTING
* - 2 - STATION_WRONG_PASSWORD
* - 3 - STATION_NO_AP_FOUND
* - 4 - STATION_CONNECT_FAIL
* - 5 - STATION_GOT_IP
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "getConnectStatus",
"generate" : "jswrap_ESP8266WiFi_getConnectStatus",
"return" : ["JsVar","A connection status"]
}
Retrieve the connection status. The return is an object that contains:
* status - The status code from ESP8266
* statusMsg - The description of the code
*/
JsVar *jswrap_ESP8266WiFi_getConnectStatus() {
// Ask ESP8266 for the connection status
uint8 status = wifi_station_get_connect_status();
// Create a JS variable to return
JsVar *var = jsvNewWithFlags(JSV_OBJECT);
// Populate the return JS variable with a property called "status"
JsVar *jsStatus = jsvNewFromInteger(status);
//jsvUnLock(jsStatus);
jsvUnLock(jsvObjectSetChild(var, "status", jsStatus));
// Populate the return JS variable with a property called "statusMsg"
char *statusMsg;
switch(status) {
case STATION_IDLE:
statusMsg = "STATION_IDLE";
break;
case STATION_CONNECTING:
statusMsg = "STATION_CONNECTING";
break;
case STATION_WRONG_PASSWORD:
statusMsg = "STATION_WRONG_PASSWORD";
break;
case STATION_NO_AP_FOUND:
statusMsg = "STATION_NO_AP_FOUND";
break;
case STATION_CONNECT_FAIL:
statusMsg = "STATION_CONNECT_FAIL";
break;
case STATION_GOT_IP:
statusMsg = "STATION_GOT_IP";
break;
default:
statusMsg = "*** Unknown ***";
}
JsVar *jsStatusMsg = jsvNewFromString(statusMsg);
//jsvUnLock(jsStatusMsg);
jsvUnLock(jsvObjectSetChild(var, "statusMsg", jsStatusMsg));
//jsvUnLock(var);
return var;
} // End of jswrap_ESP8266WiFi_getConnectStatus
/**
* Test: Perform a socket connection to a partner system.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "socketConnect",
"generate" : "jswrap_ESP8266WiFi_socketConnect",
"params" : [
["options","JsVar","Some kind of options."],
["callback","JsVar","Some kind of callback."]
],
"return" : ["JsVar","A connection object"]
}*/
JsVar *jswrap_ESP8266WiFi_socketConnect(
JsVar *options, //!< Some kind of options.
JsVar *callback //!< Some kind of callback.
) {
os_printf("Network state = %d\n", networkState);
JsVar *ret = jswrap_net_connect(options, callback, ST_NORMAL);
return ret;
} // End of jswrap_ESP8266WiFi_socketConnect
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "socketEnd",
"generate" : "jswrap_ESP8266WiFi_socketEnd",
"params" : [
["socket","JsVar","The socket to be closed."],
["data","JsVar","Optional data to be sent before close."]
]
}*/
void jswrap_ESP8266WiFi_socketEnd(
JsVar *socket, //!< The socket to be closed.
JsVar *data //!< Optional data to be sent before close.
) {
jswrap_net_socket_end(socket, data);
} // End of jswrap_ESP8266WiFi_socketEnd
/**
* \brief Perform a network ping request.
* The parameter can be either a String or a numeric IP address.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "ping",
"generate" : "jswrap_ESP8266WiFi_ping",
"params" : [
["ipAddr","JsVar","A string or integer representation of an IP address."],
["pingCallback", "JsVar", "Optional callback function."]
]
}*/
void jswrap_ESP8266WiFi_ping(
JsVar *ipAddr, //!< A string or integer representation of an IP address.
JsVar *pingCallback //!< Optional callback function.
) {
// If the parameter is a string, get the IP address from the string
// representation.
if (jsvIsString(ipAddr)) {
char ipString[20];
int len = jsvGetString(ipAddr, ipString, sizeof(ipString)-1);
ipString[len] = '\0';
pingOpt.ip = networkParseIPAddress(ipString);
if (pingOpt.ip == 0) {
jsExceptionHere(JSET_ERROR, "Not a valid IP address.");
return;
}
} else
// If the parameter is an integer, treat it as an IP address.
if (jsvIsInt(ipAddr)) {
pingOpt.ip = jsvGetInteger(ipAddr);
} else
// The parameter was neither a string nor an IP address and hence we don't
// know how to get the IP address of the partner to ping so throw an
// exception.
{
jsExceptionHere(JSET_ERROR, "IP address must be string or integer.");
return;
}
if (jsvIsUndefined(pingCallback) || jsvIsNull(pingCallback)) {
if (jsPingCallback != NULL) {
jsvUnLock(jsPingCallback);
}
jsPingCallback = NULL;
} else if (!jsvIsFunction(pingCallback)) {
jsExceptionHere(JSET_ERROR, "Callback is not a function.");
return;
} else {
if (jsPingCallback != NULL) {
jsvUnLock(jsPingCallback);
}
jsPingCallback = pingCallback;
jsvLockAgainSafe(jsPingCallback);
}
// We now have an IP address to ping ... so ping.
memset(&pingOpt, 0, sizeof(pingOpt));
pingOpt.count = 5;
pingOpt.recv_function = pingRecvCB;
ping_start(&pingOpt);
} // End of jswrap_ESP8266WiFi_ping
/**
* \brief Dump the data in the socket.
*/
/*JSON{
"type" : "staticmethod",
"class" : "ESP8266WiFi",
"name" : "dumpSocket",
"generate" : "jswrap_ESP8266WiFi_dumpSocket",
"params" : [
["socketId","JsVar","The socket to be dumped."]
]
}*/
void jswrap_ESP8266WiFi_dumpSocket(
JsVar *socketId //!< The socket to be dumped.
) {
esp8266_dumpSocket(jsvGetInteger(socketId)-1);
} // End of jswrap_ESP8266WiFi_dumpSocket
/**
* \brief Null terminate a string.
*/
static char *nullTerminateString(char *target, char *source, int sourceLength) {
os_strncpy(target, source, sourceLength);
target[sourceLength-1] = '\0';
return target;
}
/**
*
*/
static void setupJsNetwork() {
JsNetwork net;
networkCreate(&net, JSNETWORKTYPE_ESP8266_BOARD);
networkSet(&net);
} // End of setupJsNetwork
/**
* \brief Handle receiving a response from a ping reply.
* If a callback function has been supplied we invoked that callback by queuing it for future
* execution. A parameter is supplied to the callback which is a JavaScript object that contains:
* - totalCount
* - totalBytes
* - totalTime
* - respTime
* - seqNo
* - timeoutCount
* - bytes
* - error
*/
static void pingRecvCB(void *pingOpt, void *pingResponse) {
struct ping_resp *pingResp = (struct ping_resp *)pingResponse;
os_printf("Received a ping response!\n");
if (jsPingCallback != NULL) {
JsVar *jsPingResponse = jspNewObject(NULL, "PingResponse");
jsvUnLock(jsvObjectSetChild(jsPingResponse, "totalCount", jsvNewFromInteger(pingResp->total_count)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "totalBytes", jsvNewFromInteger(pingResp->total_bytes)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "totalTime", jsvNewFromInteger(pingResp->total_time)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "respTime", jsvNewFromInteger(pingResp->resp_time)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "seqNo", jsvNewFromInteger(pingResp->seqno)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "timeoutCount", jsvNewFromInteger(pingResp->timeout_count)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "bytes", jsvNewFromInteger(pingResp->bytes)));
jsvUnLock(jsvObjectSetChild(jsPingResponse, "error", jsvNewFromInteger(pingResp->ping_err)));
JsVar *params[1];
params[0] = jsPingResponse;
jsiQueueEvents(NULL, jsPingCallback, params, 1);
} // End of we have a callback function
} // End of pingRecvCB
/**
* \brief Callback function that is invoked at the culmination of a scan.
*/
static void scanCB(void *arg, STATUS status) {
/**
* Create a JsVar that is an array of JS objects where each JS object represents a
* retrieved access point set of information. The structure of a record will be:
* o authMode
* o isHidden
* o rssi
* o channel
* o ssid
* When the array has been built, invoke the callback function passing in the array
* of records.
*/
// Create the Empty JS array that will be passed as a parameter to the callback.
JsVar *accessPointArray = jsvNewArray(NULL, 0);
struct bss_info *bssInfo;
bssInfo = (struct bss_info *)arg;
// skip the first in the chain … it is invalid
bssInfo = STAILQ_NEXT(bssInfo, next);
while(bssInfo != NULL) {
// Add a new object to the JS array that will be passed as a parameter to
// the callback. The ESP8266 bssInfo structure contains the following:
// ---
// uint8 bssid[6]
// uint8 ssid[32]
// uint8 channel
// sint8 rssi The received signal strength indication
// AUTH_MODE authmode
// Open = 0
// WEP = 1
// WPA_PSK = 2
// WPA2_PSK = 3
// WPA_WPA2_PSK = 4
// uint8 is_hidden
// sint16 freq_offset
// ---
// Create, populate and add a child ...
JsVar *currentAccessPoint = jspNewObject(NULL, "AccessPoint");
jsvUnLock(jsvObjectSetChild(currentAccessPoint, "rssi", jsvNewFromInteger(bssInfo->rssi)));
jsvUnLock(jsvObjectSetChild(currentAccessPoint, "channel", jsvNewFromInteger(bssInfo->channel)));
jsvUnLock(jsvObjectSetChild(currentAccessPoint, "authMode", jsvNewFromInteger(bssInfo->authmode)));
jsvUnLock(jsvObjectSetChild(currentAccessPoint, "isHidden", jsvNewFromBool(bssInfo->is_hidden)));
// The SSID may **NOT** be NULL terminated ... so handle that.
char ssid[sizeof(bssInfo->ssid) + 1];
os_strncpy((char *)ssid, (char *)bssInfo->ssid, sizeof(bssInfo->ssid));
ssid[sizeof(ssid)-1] = '\0';
jsvUnLock(jsvObjectSetChild(currentAccessPoint, "ssid", jsvNewFromString(ssid)));
// Add the new record to the array
jsvArrayPush(accessPointArray, currentAccessPoint);
os_printf("ssid: %s\n", bssInfo->ssid);
bssInfo = STAILQ_NEXT(bssInfo, next);
} // End of loop over the records.
// We have now completed the scan callback, so now we can invoke the JS callback.
JsVar *params[1];
params[0] = accessPointArray;
jsiQueueEvents(NULL, jsScanCallback, params, 1);
jsvUnLock(jsScanCallback);
} // End of scanCB
/**
* \brief Invoke the JavaScript callback to notify the program that an ESP8266
* WiFi event has occurred.
*/
static void sendWifiEvent(uint32 eventType, JsVar *details) {
// We need to check that we actually have an event callback handler because
// it might have been disabled/removed.
if (jsWiFiEventCallback != NULL) {
// Build a callback event.
JsVar *params[2];
params[0] = jsvNewFromInteger(eventType);
params[1] = details;
jsiQueueEvents(NULL, jsWiFiEventCallback, params, 2);
}
if (jsGotIpCallback != NULL && eventType == EVENT_STAMODE_GOT_IP) {
JsVar *params[2];
params[0] = jsvNewFromInteger(eventType);
params[1] = details;
jsiQueueEvents(NULL, jsGotIpCallback, params, 2);
// Once we have registered the callback, we can unlock and release
// the variable as we are only calling it once.
//jsvUnLock(jsGotIpCallback);
//jsGotIpCallback = NULL;
}
} // End of sendWifiEvent
/**
* \brief ESP8266 WiFi Event handler.
* This function is called by the ESP8266
* environment when significant events happend related to the WiFi environment.
* The event handler is registered with a call to wifi_set_event_handler_cb()
* that is provided by the ESP8266 SDK.
*/
static void wifiEventHandler(System_Event_t *event) {
switch(event->event) {
case EVENT_STAMODE_CONNECTED:
os_printf("Event: EVENT_STAMODE_CONNECTED\n");
sendWifiEvent(event->event, jsvNewNull());
break;
case EVENT_STAMODE_DISCONNECTED:
os_printf("Event: EVENT_STAMODE_DISCONNECTED\n");
JsVar *details = jspNewObject(NULL, "EventDetails");
jsvObjectSetChild(details, "reason", jsvNewFromInteger(event->event_info.disconnected.reason));
char ssid[33];
memcpy(ssid, event->event_info.disconnected.ssid, event->event_info.disconnected.ssid_len);
ssid[ event->event_info.disconnected.ssid_len] = '\0';
sendWifiEvent(event->event, details);
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
os_printf("Event: EVENT_STAMODE_AUTHMODE_CHANGE\n");
sendWifiEvent(event->event, jsvNewNull());
break;
case EVENT_STAMODE_GOT_IP:
os_printf("Event: EVENT_STAMODE_GOT_IP\n");
sendWifiEvent(event->event, jsvNewNull());
break;
case EVENT_SOFTAPMODE_STACONNECTED:
os_printf("Event: EVENT_SOFTAPMODE_STACONNECTED\n");
sendWifiEvent(event->event, jsvNewNull());
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
os_printf("Event: EVENT_SOFTAPMODE_STADISCONNECTED\n");
sendWifiEvent(event->event, jsvNewNull());
break;
default:
os_printf("Unexpected event: %d\n", event->event);
sendWifiEvent(event->event, jsvNewNull());
break;
}
} // End of wifiEventHandler
/**
* \brief Write an IP address as a dotted decimal string.
*/
// Note: This may be a duplicate ... it appears that we may have an existing function
// in network.c which does exactly this and more!!
//
static void ipAddrToString(struct ip_addr addr, char *string) {
os_sprintf(string, "%d.%d.%d.%d", ((char *)&addr)[0], ((char *)&addr)[1], ((char *)&addr)[2], ((char *)&addr)[3]);
} // End of ipAddrToString
// End of file

View File

@ -0,0 +1,34 @@
/*
* jswrap_ESP8266WiFi.h
*
* Created on: Aug 26, 2015
* Author: kolban
*/
#ifndef LIBS_NETWORK_ESP8266_JSWRAP_ESP8266_H_
#define LIBS_NETWORK_ESP8266_JSWRAP_ESP8266_H_
#include "jsvar.h"
void jswrap_ESP8266WiFi_connect(JsVar *jsv_ssid, JsVar *jsv_password, JsVar *gotIpCallback);
void jswrap_ESP8266WiFi_getAccessPoints(JsVar *callback);
void jswrap_ESP8266WiFi_disconnect();
void jswrap_ESP8266WiFi_restart();
JsVar *jswrap_ESP8266WiFi_getRstInfo();
JsVar *jswrap_ESP8266WiFi_getIPInfo();
void jswrap_ESP8266WiFi_setAutoConnect(JsVar *autoconnect);
JsVar *jswrap_ESP8266WiFi_getAutoConnect();
JsVar *jswrap_ESP8266WiFi_getStationConfig();
void jswrap_ESP8266WiFi_onWiFiEvent(JsVar *callback);
JsVar *jswrap_ESP8266WiFi_getAddressAsString(JsVar *address);
void jswrap_ESP8266WiFi_init();
JsVar *jswrap_ESP8266WiFi_getConnectStatus();
JsVar *jswrap_ESP8266WiFi_socketConnect(JsVar *options, JsVar *callback);
void jswrap_ESP8266WiFi_socketEnd(JsVar *socket, JsVar *data);
void jswrap_ESP8266WiFi_ping(JsVar *ipAddr, JsVar *pingCallback);
void jswrap_ESP8266WiFi_beAccessPoint(JsVar *jsv_ssid, JsVar *jsv_password);
JsVar *jswrap_ESP8266WiFi_getConnectedStations();
JsVar *jswrap_ESP8266WiFi_getRSSI();
JsVar *jswrap_ESP8266WiFi_getState();
void jswrap_ESP8266WiFi_dumpSocket(JsVar *socketId);
#endif /* LIBS_NETWORK_ESP8266_JSWRAP_ESP8266_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
/*
* network_esp8266_board.h
*
* Created on: Aug 29, 2015
* Author: kolban
*/
#ifndef LIBS_NETWORK_ESP8266_NETWORK_ESP8266_H_
#define LIBS_NETWORK_ESP8266_NETWORK_ESP8266_H_
#include "network.h"
void netInit_esp8266_board();
void netSetCallbacks_esp8266_board(JsNetwork *net);
void esp8266_dumpSocket(int socketId);
int net_ESP8266_BOARD_accept(JsNetwork *net, int serverSckt);
int net_ESP8266_BOARD_recv(JsNetwork *net, int sckt, void *buf, size_t len);
int net_ESP8266_BOARD_send(JsNetwork *net, int sckt, const void *buf, size_t len);
void net_ESP8266_BOARD_idle(JsNetwork *net);
bool net_ESP8266_BOARD_checkError(JsNetwork *net);
int net_ESP8266_BOARD_createSocket(JsNetwork *net, uint32_t ipAddress, unsigned short port);
void net_ESP8266_BOARD_closeSocket(JsNetwork *net, int sckt);
void net_ESP8266_BOARD_gethostbyname(JsNetwork *net, char *hostName, uint32_t *outIp);
#endif /* LIBS_NETWORK_ESP8266_NETWORK_ESP8266_H_ */

View File

@ -0,0 +1,17 @@
/*
* ESP8266_board.h
*
* Created on: Aug 25, 2015
* Author: kolban
*/
#ifndef TARGETS_ESP8266_ESP8266_BOARD_H_
#define TARGETS_ESP8266_ESP8266_BOARD_H_
#include <user_interface.h>
// Define the task ids for the APP event handler
#define TASK_APP_MAINLOOP ((os_signal_t)1)
#define TASK_APP_RX_DATA ((os_signal_t)2)
#define TASK_APP_QUEUE USER_TASK_PRIO_1
#endif /* TARGETS_ESP8266_ESP8266_BOARD_H_ */

View File

@ -0,0 +1,2 @@
# ESP8266
This is where documentation on the ESP8266 target will be provided.

View File

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

View File

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

View File

@ -0,0 +1,211 @@
/* This linker script generated from xt-genldscripts.tpp for LSP . */
/* Linker Script for ld -N */
MEMORY
{
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40210000, len = 0x60000
}
PHDRS
{
dport0_0_phdr PT_LOAD;
dram0_0_phdr PT_LOAD;
dram0_0_bss_phdr PT_LOAD;
iram1_0_phdr PT_LOAD;
irom0_0_phdr PT_LOAD;
}
/* Default entry point: */
ENTRY(call_user_start)
EXTERN(_DebugExceptionVector)
EXTERN(_DoubleExceptionVector)
EXTERN(_KernelExceptionVector)
EXTERN(_NMIExceptionVector)
EXTERN(_UserExceptionVector)
PROVIDE(_memmap_vecbase_reset = 0x40000000);
/* Various memory-map dependent cache attribute settings: */
_memmap_cacheattr_wb_base = 0x00000110;
_memmap_cacheattr_wt_base = 0x00000110;
_memmap_cacheattr_bp_base = 0x00000220;
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
_memmap_cacheattr_wb_trapnull = 0x2222211F;
_memmap_cacheattr_wba_trapnull = 0x2222211F;
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
_memmap_cacheattr_wt_trapnull = 0x2222211F;
_memmap_cacheattr_bp_trapnull = 0x2222222F;
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
_memmap_cacheattr_wb_allvalid = 0x22222112;
_memmap_cacheattr_wt_allvalid = 0x22222112;
_memmap_cacheattr_bp_allvalid = 0x22222222;
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
SECTIONS
{
.dport0.rodata : ALIGN(4)
{
_dport0_rodata_start = ABSOLUTE(.);
*(.dport0.rodata)
*(.dport.rodata)
_dport0_rodata_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.dport0.literal : ALIGN(4)
{
_dport0_literal_start = ABSOLUTE(.);
*(.dport0.literal)
*(.dport.literal)
_dport0_literal_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.dport0.data : ALIGN(4)
{
_dport0_data_start = ABSOLUTE(.);
*(.dport0.data)
*(.dport.data)
_dport0_data_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.data : ALIGN(4)
{
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_phdr
.rodata : ALIGN(4)
{
_rodata_start = ABSOLUTE(.);
*(.sdk.version)
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame)
/* C++ constructor and destructor tables, properly ordered: */
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
. = ALIGN(4); /* this table MUST be 4-byte aligned */
_bss_table_start = ABSOLUTE(.);
LONG(_bss_start)
LONG(_bss_end)
_bss_table_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_phdr
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
_heap_start = ABSOLUTE(.);
/* _stack_sentry = ALIGN(0x8); */
} >dram0_0_seg :dram0_0_bss_phdr
/* __stack = 0x3ffc8000; */
.text : ALIGN(4)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.UserEnter.text)
. = ALIGN(16);
*(.DebugExceptionVector.text)
. = ALIGN(16);
*(.NMIExceptionVector.text)
. = ALIGN(16);
*(.KernelExceptionVector.text)
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
*(.UserExceptionVector.text)
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
*(.DoubleExceptionVector.text)
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_etext = .;
} >iram1_0_seg :iram1_0_phdr
.lit4 : ALIGN(4)
{
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
} >iram1_0_seg :iram1_0_phdr
.irom0.text : ALIGN(4)
{
_irom0_text_start = ABSOLUTE(.);
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
_irom0_text_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr
}
/* get ROM code address */
INCLUDE "../ld/eagle.rom.addr.v6.ld"

View File

@ -0,0 +1,69 @@
#include <ets_sys.h>
#include <osapi.h>
#include <os_type.h>
#include <user_interface.h>
#include <espconn.h>
#include <gpio.h>
#include <mem.h>
#include <espmissingincludes.h>
#define _GCC_WRAP_STDINT_H
typedef long long int64_t;
#include "jsutils.h"
/**
* \brief Convert an ESP8266 error code to a string.
* Given an ESP8266 network error code, return a string representation
* of the meaning of that code.
* \return A string representation of an error code.
*/
const char *esp8266_errorToString(
sint8 err //!< The error code to be transformed to a string.
) {
switch(err) {
case ESPCONN_MEM:
return "ESPCONN_MEM";
case ESPCONN_TIMEOUT:
return "ESPCONN_TIMEOUT";
case ESPCONN_RTE:
return "ESPCONN_RTE";
case ESPCONN_INPROGRESS:
return "ESPCONN_INPROGRESS";
case ESPCONN_ABRT:
return "ESPCONN_ABRT";
case ESPCONN_RST:
return "ESPCONN_RST";
case ESPCONN_CLSD:
return "ESPCONN_CLSD";
case ESPCONN_CONN:
return "ESPCONN_CONN";
case ESPCONN_ARG:
return "ESPCONN_ARG";
case ESPCONN_ISCONN:
return "ESPCONN_ISCONN";
case ESPCONN_HANDSHAKE:
return "ESPCONN_HANDSHAKE";
default:
return "Unknown error";
}
} // End of errorToString
/**
* \brief Write a buffer of data to the console.
* The buffer is pointed to by the buffer
* parameter and will be written for the length parameter. This is useful because
* unlike a string, the data does not have to be NULL terminated.
*/
void esp8266_board_writeString(
uint8 *buffer, //!< The start of the buffer to write.
size_t length //!< The length of the buffer to write.
) {
assert(length==0 || buffer != NULL);
for (size_t i=0; i<length; i++) {
os_printf("%c", buffer[i]);
}
} // End of esp8266_board_writeString
// End of file

View File

@ -0,0 +1,15 @@
/*
* esp8266_board_utils.h
*
* Created on: Sep 3, 2015
* Author: kolban
*/
#ifndef TARGETS_ESP8266_ESP8266_BOARD_UTILS_H_
#define TARGETS_ESP8266_ESP8266_BOARD_UTILS_H_
// Return a string representation of an ESP8266 error.
const char *esp8266_errorToString(sint8 err);
void esp8266_board_writeString(uint8 *buffer, size_t length);
#endif /* TARGETS_ESP8266_ESP8266_BOARD_UTILS_H_ */

View File

@ -0,0 +1,91 @@
#ifndef ESPMISSINGINCLUDES_H
#define ESPMISSINGINCLUDES_H
#include <user_interface.h>
#include <eagle_soc.h>
//Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere.
//MOST OF THESE ARE GUESSED! but they seem to work and shut up the compiler.
typedef struct espconn espconn;
bool wifi_station_set_hostname(char *);
char *wifi_station_get_hostname(void);
int atoi(const char *nptr);
void ets_install_putc1(void *routine); // necessary for #define os_xxx -> ets_xxx
void ets_isr_attach(int intr, void *handler, void *arg);
void ets_isr_mask(unsigned intr);
void ets_isr_unmask(unsigned intr);
int ets_memcmp(const void *s1, const void *s2, size_t n);
void *ets_memcpy(void *dest, const void *src, size_t n);
void *ets_memset(void *s, int c, size_t n);
int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int ets_str2macaddr(void *, void *);
int ets_strcmp(const char *s1, const char *s2);
char *ets_strcpy(char *dest, const char *src);
size_t ets_strlen(const char *s);
int ets_strncmp(const char *s1, const char *s2, int len);
char *ets_strncpy(char *dest, const char *src, size_t n);
char *ets_strstr(const char *haystack, const char *needle);
void ets_timer_arm_new(ETSTimer *a, int b, int c, int isMstimer);
void ets_timer_disarm(ETSTimer *a);
void ets_timer_setfn(ETSTimer *t, ETSTimerFunc *fn, void *parg);
void ets_update_cpu_frequency(int freqmhz);
#ifdef SDK_DBG
#define DEBUG_SDK true
#else
#define DEBUG_SDK false
#endif
int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4)));
int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2)));
#undef os_printf
#define os_printf(format, ...) do {\
system_set_os_print(true); \
os_printf_plus(format, ## __VA_ARGS__); \
system_set_os_print(DEBUG_SDK); \
} while(0)
// memory allocation functions are "different" due to memory debugging functionality
// added in SDK 1.4.0
void vPortFree(void *ptr, char * file, int line);
void *pvPortMalloc(size_t xWantedSize, char * file, int line);
void *pvPortZalloc(size_t, char * file, int line);
void *vPortMalloc(size_t xWantedSize);
void pvPortFree(void *ptr);
void *pvPortRealloc(void *pv, size_t size, char * file, int line);
void uart_div_modify(int no, unsigned int freq);
uint32 system_get_time();
int rand(void);
void ets_bzero(void *s, size_t n);
void ets_delay_us(int ms);
// disappeared in SDK 1.1.0:
#define os_timer_done ets_timer_done
#define os_timer_handler_isr ets_timer_handler_isr
#define os_timer_init ets_timer_init
// This is not missing in SDK 1.1.0 but causes a parens error
#undef PIN_FUNC_SELECT
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \
WRITE_PERI_REG(PIN_NAME, \
(READ_PERI_REG(PIN_NAME) & ~(PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S)) \
|( (((FUNC&BIT2)<<2)|(FUNC&0x3))<<PERIPHS_IO_MUX_FUNC_S) ); \
} while (0)
// Shortcuts for memory functions
//#define os_malloc pvPortMalloc // defined in SDK 1.4.0 onwards
//#define os_free vPortFree // defined in SDK 1.4.0 onwards
//#define os_zalloc pvPortZalloc // defined in SDK 1.4.0 onwards
//uint8 wifi_get_opmode(void); // defined in SDK 1.0.0 onwards
//int os_random(); // defined in SDK 1.1.0 onwards
#endif

View File

@ -0,0 +1,561 @@
#include <ets_sys.h>
#include <osapi.h>
#include <os_type.h>
#include <c_types.h>
#include <user_interface.h>
#include <espconn.h>
#include <gpio.h>
#include <mem.h>
#include <espmissingincludes.h>
#include <driver/uart.h>
//#define FAKE_STDLIB
#define _GCC_WRAP_STDINT_H
typedef long long int64_t;
#include "jshardware.h"
#include "jsutils.h"
#include "jsparse.h"
#include "jsinteractive.h"
// The maximum time that we can safely delay/block without risking a watch dog
// timer error or other undesirable WiFi interaction. The time is measured in
// microseconds.
#define MAX_SLEEP_TIME_US 10000
/**
* Transmit all the characters in the transmit buffer.
*
*/
void esp8266_uartTransmitAll(IOEventFlags device) {
// Get the next character to transmit. We will have reached the end when
// the value of the character to transmit is -1.
int c = jshGetCharToTransmit(device);
while (c >= 0) {
uart_tx_one_char(0, c);
c = jshGetCharToTransmit(device);
} // No more characters to transmit
} // End of esp8266_transmitAll
// ----------------------------------------------------------------------------
IOEventFlags pinToEVEXTI(Pin pin) {
return (IOEventFlags) 0;
}
/**
* Initialize the ESP8266 hardware environment.
*/
void jshInit() {
// A call to jshInitDevices is architected as something we have to do.
jshInitDevices();
} // End of jshInit
void jshReset() {
// TODO
} // End of jshReset
void jshKill() {
// TODO
} // End of jshKill
/**
* Hardware idle processing.
*/
void jshIdle() {
} // End of jshIdle
// ----------------------------------------------------------------------------
int jshGetSerialNumber(unsigned char *data, int maxChars) {
const char *code = "ESP8266";
strncpy((char *) data, code, maxChars);
return strlen(code);
} // End of jshSerialNumber
// ----------------------------------------------------------------------------
void jshInterruptOff() {
// TODO
} // End of jshInterruptOff
void jshInterruptOn() {
// TODO
} // End of jshInterruptOn
/**
* Delay (blocking) for the supplied number of microseconds.
* Note that for the ESP8266 we must NOT CPU block for more than
* 10 milliseconds or else we may starve the WiFi subsystem.
*/
void jshDelayMicroseconds(int microsec) {
// Get the current time
/*
uint32 endTime = system_get_time() + microsec;
while ((endTime - system_get_time()) > 10000) {
os_delay_us(10000);
system_soft_wdt_feed();
}
int lastDelta = endTime - system_get_time();
if (lastDelta > 0) {
os_delay_us(lastDelta);
}
*/
// This is a place holder implementation. We can and must do better
// than this. This fails because we will sleep too long. We will sleep
// for the given number of microseconds PLUS multiple calls back to the
// WiFi environment.
int count = microsec / MAX_SLEEP_TIME_US;
for (int i=0; i<count; i++) {
os_delay_us(MAX_SLEEP_TIME_US);
// We may have a problem here. It was my understanding that system_soft_wdt_feed() fed
// the underlying OS but this appears not to be the case and all it does is prevent a
// watchdog timer from firing. What that means is that we may very well loose network
// connectivity because we are not servicing the housekeeping. This might be one of those
// locations where we need to look at a callback or some kind of yield technology.
system_soft_wdt_feed();
microsec -= MAX_SLEEP_TIME_US;
}
assert(microsec < MAX_SLEEP_TIME_US);
if (microsec > 0) {
os_delay_us(microsec);
}
/*
if (0 < microsec) {
os_delay_us(microsec);
}
*/
} // End of jshDelayMicroseconds
static uint8_t PERIPHS[] = {
PERIPHS_IO_MUX_GPIO0_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_U0TXD_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_GPIO2_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_U0RXD_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_GPIO4_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_GPIO5_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_SD_CLK_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_SD_DATA0_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_SD_DATA1_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_SD_DATA2_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_SD_DATA3_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_SD_CMD_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_MTDI_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_MTCK_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_MTMS_U - PERIPHS_IO_MUX,
PERIPHS_IO_MUX_MTDO_U - PERIPHS_IO_MUX };
#define FUNC_SPI 1
#define FUNC_GPIO 3
#define FUNC_UART 4
static uint8_t pinFunction(JshPinState state) {
switch (state) {
case JSHPINSTATE_GPIO_OUT:
case JSHPINSTATE_GPIO_OUT_OPENDRAIN:
case JSHPINSTATE_GPIO_IN:
case JSHPINSTATE_GPIO_IN_PULLUP:
case JSHPINSTATE_GPIO_IN_PULLDOWN:
return FUNC_GPIO;
case JSHPINSTATE_USART_OUT:
case JSHPINSTATE_USART_IN:
return FUNC_UART;
case JSHPINSTATE_I2C:
return FUNC_SPI;
case JSHPINSTATE_AF_OUT:
case JSHPINSTATE_AF_OUT_OPENDRAIN:
case JSHPINSTATE_DAC_OUT:
case JSHPINSTATE_ADC_IN:
default:
return 0;
}
} // End of pinFunction
/**
* \brief Set the state of the specific pin.
*
* The possible states are:
*
* JSHPINSTATE_UNDEFINED
* JSHPINSTATE_GPIO_OUT
* JSHPINSTATE_GPIO_OUT_OPENDRAIN
* JSHPINSTATE_GPIO_IN
* JSHPINSTATE_GPIO_IN_PULLUP
* JSHPINSTATE_GPIO_IN_PULLDOWN
* JSHPINSTATE_ADC_IN
* JSHPINSTATE_AF_OUT
* JSHPINSTATE_AF_OUT_OPENDRAIN
* JSHPINSTATE_USART_IN
* JSHPINSTATE_USART_OUT
* JSHPINSTATE_DAC_OUT
* JSHPINSTATE_I2C
*/
void jshPinSetState(Pin pin, //!< The pin to have its state changed.
JshPinState state //!< The new desired state of the pin.
) {
jsiConsolePrintf("ESP8266: jshPinSetState %d, %d\n", pin, state);
assert(pin < 16);
int periph = PERIPHS_IO_MUX + PERIPHS[pin];
// Disable the pin's pull-up.
PIN_PULLUP_DIS(periph);
//PIN_PULLDWN_DIS(periph);
uint8_t primary_func =
pin < 6 ?
(PERIPHS_IO_MUX_U0TXD_U == pin
|| PERIPHS_IO_MUX_U0RXD_U == pin) ?
FUNC_UART : FUNC_GPIO
: 0;
uint8_t select_func = pinFunction(state);
PIN_FUNC_SELECT(periph, primary_func == select_func ? 0 : select_func);
switch (state) {
case JSHPINSTATE_GPIO_OUT:
case JSHPINSTATE_GPIO_OUT_OPENDRAIN:
//case JSHPINSTATE_AF_OUT:
//case JSHPINSTATE_AF_OUT_OPENDRAIN:
//case JSHPINSTATE_USART_OUT:
//case JSHPINSTATE_DAC_OUT:
gpio_output_set(0, 1 << pin, 1 << pin, 0);
break;
case JSHPINSTATE_GPIO_IN_PULLUP:
PIN_PULLUP_EN(periph);
//case JSHPINSTATE_GPIO_IN_PULLDOWN: if (JSHPINSTATE_GPIO_IN_PULLDOWN == pin) PIN_PULLDWN_EN(periph);
case JSHPINSTATE_GPIO_IN:
gpio_output_set(0, 0, 0, 1 << pin);
break;
case JSHPINSTATE_ADC_IN:
case JSHPINSTATE_USART_IN:
case JSHPINSTATE_I2C:
PIN_PULLUP_EN(periph);
break;
default:
break;
}
} // End of jshPinSetState
/**
* \brief Return the current state of the selected pin.
* \return The current state of the selected pin.
*/
JshPinState jshPinGetState(Pin pin) {
jsiConsolePrintf("ESP8266: jshPinGetState %d\n", pin);
return JSHPINSTATE_UNDEFINED;
} // End of jshPinGetState
/**
* \brief Set the value of the corresponding pin.
*/
void jshPinSetValue(Pin pin, //!< The pin to have its value changed.
bool value //!< The new value of the pin.
) {
jsiConsolePrintf("ESP8266: jshPinSetValue %d, %d\n", pin, value);
GPIO_OUTPUT_SET(pin, value);
} // End of jshPinSetValue
/**
* \brief Get the value of the corresponding pin.
* \return The current value of the pin.
*/
bool jshPinGetValue(Pin pin //!< The pin to have its value read.
) {
jsiConsolePrintf("ESP8266: jshPinGetValue %d, %d\n", pin, GPIO_INPUT_GET(pin));
return GPIO_INPUT_GET(pin);
} // End of jshPinGetValue
bool jshIsDeviceInitialised(IOEventFlags device) {
jsiConsolePrintf("ESP8266: jshIsDeviceInitialised %d\n", device);
return true;
} // End of jshIsDeviceInitialised
bool jshIsUSBSERIALConnected() {
jsiConsolePrintf("ESP8266: jshIsUSBSERIALConnected\n");
return true;
} // End of jshIsUSBSERIALConnected
JsSysTime jshGetTimeFromMilliseconds(JsVarFloat ms) {
// jsiConsolePrintf("jshGetTimeFromMilliseconds %d, %f\n", (JsSysTime)(ms * 1000.0), ms);
return (JsSysTime) (ms * 1000.0 + 0.5);
} // End of jshGetTimeFromMilliseconds
/**
* Given a time in microseconds, get us the value in milliseconds (float)
*/
JsVarFloat jshGetMillisecondsFromTime(JsSysTime time) {
// jsiConsolePrintf("jshGetMillisecondsFromTime %d, %f\n", time, (JsVarFloat)time / 1000.0);
return (JsVarFloat) time / 1000.0;
} // End of jshGetMillisecondsFromTime
/**
* Return the current time in microseconds.
*/
JsSysTime jshGetSystemTime() { // in us
return system_get_time();
} // End of jshGetSystemTime
/**
* Set the current time in microseconds.
*/
void jshSetSystemTime(JsSysTime time) {
os_printf("ESP8266: jshSetSystemTime: %d\n", time);
} // End of jshSetSystemTime
// ----------------------------------------------------------------------------
JsVarFloat jshPinAnalog(Pin pin) {
jsiConsolePrintf("ESP8266: jshPinAnalog: %d\n", pin);
return (JsVarFloat) system_adc_read();
} // End of jshPinAnalog
int jshPinAnalogFast(Pin pin) {
jsiConsolePrintf("ESP8266: jshPinAnalogFast: %d\n", pin);
return NAN;
} // End of jshPinAnalogFast
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used
jsiConsolePrintf("ESP8266: jshPinAnalogOutput: %d, %d, %d\n", pin, (int)value, (int)freq);
//pwm_set(pin, value < 0.0f ? 0 : 255.0f < value ? 255 : (uint8_t)value);
return 0;
} // End of jshPinAnalogOutput
void jshSetOutputValue(JshPinFunction func, int value) {
jsiConsolePrintf("ESP8266: jshSetOutputValue %d %d\n", func, value);
} // End of jshSetOutputValue
void jshEnableWatchDog(JsVarFloat timeout) {
jsiConsolePrintf("ESP8266: jshEnableWatchDog %0.3f\n", timeout);
} // End of jshEnableWatchDog
bool jshGetWatchedPinState(IOEventFlags device) {
jsiConsolePrintf("ESP8266: jshGetWatchedPinState %d", device);
return false;
} // End of jshGetWatchedPinState
/**
* \brief Set the value of the pin to be the value supplied and then wait for
* a given period and set the pin value again to be the opposite.
*/
void jshPinPulse(Pin pin, //!< The pin to be pulsed.
bool value, //!< The value to be pulsed into the pin.
JsVarFloat time //!< The period in milliseconds to hold the pin.
) {
if (jshIsPinValid(pin)) {
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
jshPinSetValue(pin, value);
jshDelayMicroseconds(jshGetTimeFromMilliseconds(time));
jshPinSetValue(pin, !value);
} else
jsError("Invalid pin!");
} // End of jshPinPulse
bool jshCanWatch(Pin pin) {
return false;
} // End of jshCanWatch
IOEventFlags jshPinWatch(Pin pin, bool shouldWatch) {
if (jshIsPinValid(pin)) {
} else
jsError("Invalid pin!");
return EV_NONE;
} // End of jshPinWatch
JshPinFunction jshGetCurrentPinFunction(Pin pin) {
//os_printf("jshGetCurrentPinFunction %d\n", pin);
return JSH_NOTHING;
} // End of jshGetCurrentPinFunction
bool jshIsEventForPin(IOEvent *event, Pin pin) {
return IOEVENTFLAGS_GETTYPE(event->flags) == pinToEVEXTI(pin);
} // End of jshIsEventForPin
void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
} // End of jshUSARTSetup
/**
* Kick a device into action (if required). For instance we may need
* to set up interrupts. In this ESP8266 implementation, we transmit all the
* data that can be found associated with the device.
*/
void jshUSARTKick(IOEventFlags device) {
esp8266_uartTransmitAll(device);
} // End of jshUSARTKick
void jshSPISetup(IOEventFlags device, JshSPIInfo *inf) {
} // End of jshSPISetup
/** Send data through the given SPI device (if data>=0), and return the result
* of the previous send (or -1). If data<0, no data is sent and the function
* waits for data to be returned */
int jshSPISend(IOEventFlags device, int data) {
return NAN;
} // End of jshSPISend
/** Send 16 bit data through the given SPI device. */
void jshSPISend16(IOEventFlags device, int data) {
jshSPISend(device, data >> 8);
jshSPISend(device, data & 255);
} // End of jshSPISend16
/** Set whether to send 16 bits or 8 over SPI */
void jshSPISet16(IOEventFlags device, bool is16) {
} // End of jshSPISet16
/** Wait until SPI send is finished, */
void jshSPIWait(IOEventFlags device) {
} // End of jshSPIWait
void jshI2CSetup(IOEventFlags device, JshI2CInfo *inf) {
} // End of jshI2CSetup
void jshI2CWrite(IOEventFlags device, unsigned char address, int nBytes,
const unsigned char *data, bool sendStop) {
} // End of jshI2CWrite
void jshI2CRead(IOEventFlags device, unsigned char address, int nBytes,
unsigned char *data, bool sendStop) {
} // End of jshI2CRead
/**
* \brief Save what is in RAM to flash.
* See also `jshLoadFromFlash`.
*/
void jshSaveToFlash() {
os_printf("ESP8266: jshSaveToFlash\n");
} // End of jshSaveToFlash
void jshLoadFromFlash() {
os_printf("ESP8266: jshLoadFromFlash\n");
} // End of jshLoadFromFlash
bool jshFlashContainsCode() {
os_printf("ESP8266: jshFlashContainsCode\n");
return false;
} // End of jshFlashContainsCode
/// Enter simple sleep mode (can be woken up by interrupts). Returns true on success
bool jshSleep(JsSysTime timeUntilWake) {
int time = (int) timeUntilWake;
// os_printf("jshSleep %d\n", time);
jshDelayMicroseconds(time);
return true;
} // End of jshSleep
void jshUtilTimerDisable() {
os_printf("ESP8266: jshUtilTimerDisable\n");
} // End of jshUtilTimerDisable
void jshUtilTimerReschedule(JsSysTime period) {
os_printf("ESP8266: jshUtilTimerReschedule %d\n", period);
} // End of jshUtilTimerReschedule
void jshUtilTimerStart(JsSysTime period) {
os_printf("ESP8266: jshUtilTimerStart %d\n", period);
} // End of jshUtilTimerStart
JsVarFloat jshReadTemperature() {
return NAN;
} // End of jshReadTemperature
JsVarFloat jshReadVRef() {
return NAN;
} // End of jshReadVRef
unsigned int jshGetRandomNumber() {
return rand();
} // End of jshGetRandomNumber
/**
* \brief Read data from flash memory into the buffer.
*
*/
void jshFlashRead(
void *buf, //!< buffer to read into
uint32_t addr, //!< Flash address to read from
uint32_t len //!< Length of data to read
) {
os_printf("ESP8266: jshFlashRead: buf=0x%x for len=%d from flash addr=0x%x\n", buf, len, addr);
} // End of jshFlashRead
/**
* \brief Write data to flash memory from the buffer.
*/
void jshFlashWrite(
void *buf, //!< Buffer to write from
uint32_t addr, //!< Flash address to write into
uint32_t len //!< Length of data to write
) {
os_printf("ESP8266: jshFlashWrite: buf=0x%x for len=%d into flash addr=0x%x\n", buf, len, addr);
} // End of jshFlashWrite
/**
* \brief Return start address and size of the flash page the given address resides in. Returns false if no page.
*/
bool jshFlashGetPage(
uint32_t addr, //!<
uint32_t *startAddr, //!<
uint32_t *pageSize //!<
) {
os_printf("ESP8266: jshFlashGetPage: addr=0x%x, startAddr=0x%x, pageSize=%d\n", addr, startAddr, pageSize);
return false;
} // End of jshFlashGetPage
/**
* \brief Erase the flash page containing the address.
*/
void jshFlashErasePage(
uint32_t addr //!<
) {
os_printf("ESP8266: jshFlashErasePage: addr=0x%x\n", addr);
} // End of jshFlashErasePage
/** Set whether to use the receive interrupt or not */
void jshSPISetReceive(IOEventFlags device, bool isReceive) {
} // End of jshSPISetReceive
/**
* Callback for end of runtime. This should never be called and has been
* added to satisfy the linker.
*/
void _exit(int status) {
} // End of _exit
// End of file

25
targets/esp8266/telnet.h Normal file
View File

@ -0,0 +1,25 @@
/*
* This file is part of Espruino/ESP8266, a JavaScript interpreter for ESP8266
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef USER_TELNET_H_
#define USER_TELNET_H_
/**
* Register a telnet serever listener on port 23 to handle incoming telnet client
* connections. The parameter called pLineCB is a pointer to a callback function
* that should be called when we have received a link of input.
*/
void telnet_startListening(void (*lineCB)(char *arg));
/**
* Send the string passed as a parameter to the telnet client.
*/
void telnet_send(char *text);
#endif /* USER_TELNET_H_ */

View File

@ -0,0 +1,94 @@
/*
* This file is part of Espruino/ESP8266, a JavaScript interpreter for ESP8266
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
//#include "espmissingincludes.h"
#include <ets_sys.h>
#include <osapi.h>
#include <os_type.h>
#include <user_interface.h>
#include <espconn.h>
#include <mem.h>
#include <telnet.h>
#define MAXLINE 200
static char line[MAXLINE];
static struct espconn conn1;
static esp_tcp tcp1;
static bool discard;
static void (*lineCB)(char *);
static struct espconn *pTelnetClientConn;
/**
* Callback invoked when a new TCP/IP connection has been formed.
* o arg - This is a pointer to the struct espconn that reflects this entry.
*/
static void connectCB(void *arg) {
struct espconn *pConn = (struct espconn *)arg;
// By default, an ESP TCP connection times out after 10 seconds
// Change to the max value.
espconn_regist_time(pConn, 7200, 1);
os_printf("Connect cb!!\n");
strcpy(line, "");
discard = false;
pTelnetClientConn = pConn;
} // End of connectCB
static void disconnectCB(void *arg) {
os_printf("Disconnect cb!!\n");
} // End of disconnectCB
static void receiveCB(void *arg, char *pData, unsigned short len) {
//os_printf("Receive cb!! len=%d\n", len);
if (strlen(line) + len >= MAXLINE) {
discard = true;
strcpy(line, "");
}
strncat(line, pData, len);
if (strstr(line, "\r\n") != NULL) {
if (discard) {
os_printf("Discarded ... line too long");
discard = false;
} else {
//os_printf("Found: %s", line);
(*lineCB)(line);
}
strcpy(line, "");
} else {
//os_printf("Not found, current='%s'\n", line);
}
} // End of receiveCB
/**
* Register a telnet serever listener on port 23 to handle incoming telnet client
* connections. The parameter called pLineCB is a pointer to a callback function
* that should be called when we have received a link of input.
*/
void telnet_startListening(void (*plineCB)(char *)) {
lineCB= plineCB;
tcp1.local_port = 23;
conn1.type = ESPCONN_TCP;
conn1.state = ESPCONN_NONE;
conn1.proto.tcp = &tcp1;
espconn_regist_connectcb(&conn1, connectCB);
espconn_regist_disconcb(&conn1, disconnectCB);
espconn_regist_recvcb(&conn1, receiveCB);
espconn_accept(&conn1);
os_printf("Now listening for telnet client connection ...\n");
} // End of telnet_startListening
/**
* Send the string passed as a parameter to the telnet client.
*/
void telnet_send(char *text) {
espconn_sent(pTelnetClientConn, (uint8_t *)text, strlen(text));
} // End of telnet_send
// End of file

821
targets/esp8266/uart.c Normal file
View File

@ -0,0 +1,821 @@
/*
* 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"
#include "espmissingincludes.h"
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
LOCAL struct UartBuffer* pTxBuffer = NULL;
LOCAL struct UartBuffer* pRxBuffer = NULL;
#define MAX_RX_BUFFER 500
static char rxBuffer[MAX_RX_BUFFER];
static int rxBufferLen = 0;
int getRXBuffer(char *pBuffer, int bufferLen) {
if (rxBufferLen > bufferLen) {
memcpy(pBuffer,rxBuffer, bufferLen);
memcpy(rxBuffer, rxBuffer+bufferLen, rxBufferLen-bufferLen);
rxBufferLen = rxBufferLen - bufferLen;
return bufferLen;
}
int sizeReturned = rxBufferLen;
memcpy(pBuffer, rxBuffer, rxBufferLen);
rxBufferLen = 0;
return sizeReturned;
} // End of getRXBuffer
/*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 2
#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;
// Uncomment the following line to local echo
//uart_tx_one_char(UART0, d_tmp);
if (rxBufferLen < MAX_RX_BUFFER) {
rxBuffer[rxBufferLen] = d_tmp;
rxBufferLen++;
}
}
if (fifo_len > 0) {
system_os_post(1, 2, 0);
}
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
}
/**
* Discard any data in the RX buffer.
*/
int uart_rx_discard() {
int oldRxBufferLen = rxBufferLen;
rxBufferLen = 0;
return oldRxBufferLen;
} // End of uart_rx_discard

View File

@ -0,0 +1,15 @@
/*
* This file is part of Espruino/ESP8266, a JavaScript interpreter for ESP8266
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef TARGETS_ESP8266_USER_CONFIG_H_
#define TARGETS_ESP8266_USER_CONFIG_H_
#endif /* TARGETS_ESP8266_USER_CONFIG_H_ */

232
targets/esp8266/user_main.c Normal file
View File

@ -0,0 +1,232 @@
/*
* This file is part of Espruino/ESP8266, a JavaScript interpreter for ESP8266
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <user_interface.h>
#include <osapi.h>
#include <driver/uart.h>
#include <telnet.h>
#include <espmissingincludes.h>
//#define FAKE_STDLIB
#define _GCC_WRAP_STDINT_H
typedef long long int64_t;
#include <jsdevices.h>
#include <jsinteractive.h>
#include <jswrap_esp8266.h>
#include "ESP8266_board.h"
// --- Constants
// The size of the task queue
#define TASK_QUEUE_LENGTH 10
// Should we introduce a ticker to say we are still alive?
//#define EPS8266_BOARD_HEARTBEAT
// --- Forward definitions
static void mainLoop();
// --- File local variables
// The task queue for the app
static os_event_t taskAppQueue[TASK_QUEUE_LENGTH];
// Flag indicating whether or not main loop processing is suspended.
static bool suspendMainLoopFlag = false;
// Time structure for main loop time suspension.
static os_timer_t mainLoopSuspendTimer;
// --- Functions
/**
* \brief Dump the ESP8266 restart information.
* This is purely for debugging.
* When an ESP8266 crashes, before it ends, it records its exception information.
* This function retrieves that data and logs it.
*/
static void dumpRestart() {
struct rst_info *rstInfo = system_get_rst_info();
os_printf("Restart info:\n");
os_printf(" reason: %d\n", rstInfo->reason);
os_printf(" exccause: %x\n", rstInfo->exccause);
os_printf(" epc1: %x\n", rstInfo->epc1);
os_printf(" epc2: %x\n", rstInfo->epc2);
os_printf(" epc3: %x\n", rstInfo->epc3);
os_printf(" excvaddr: %x\n", rstInfo->excvaddr);
os_printf(" depc: %x\n", rstInfo->depc);
} // End of dump_restart
/**
* \brief Queue a task for the main loop.
*/
static void queueTaskMainLoop() {
system_os_post(TASK_APP_QUEUE, TASK_APP_MAINLOOP, 0);
} // End of queueMainLoop
/**
* \brief Suspend processing the main loop for a period of time.
*/
void suspendMainLoop(
uint32 interval //!<
) {
suspendMainLoopFlag = true;
os_timer_arm(&mainLoopSuspendTimer, interval, 0 /* No repeat */);
} // End of suspendMainLoop
/**
* \brief Enable main loop processing.
*/
static void enableMainLoop() {
suspendMainLoopFlag = false;
queueTaskMainLoop();
} // End of enableMainLoop
/**
* \brief The event handler for ESP8266 tasks as created by system_os_post() on the TASK_APP_QUEUE.
*/
static void eventHandler(
os_event_t *pEvent //!<
) {
switch (pEvent->sig) {
// Handle the main loop event.
case TASK_APP_MAINLOOP:
mainLoop();
break;
// Handle the event to process received data.
case TASK_APP_RX_DATA:
{
// Get the data from the UART RX buffer. If the size of the returned data is
// not zero, then push it onto the Espruino processing queue for characters.
char pBuffer[100];
int size = getRXBuffer(pBuffer, sizeof(pBuffer));
if (size > 0) {
jshPushIOCharEvents(jsiGetConsoleDevice(), pBuffer, size);
}
}
break;
// Handle the unknown event type.
default:
os_printf("user_main: eventHandler: Unknown task type: %d",
pEvent->sig);
break;
}
} // End of eventHandler
/**
* \brief A callback function to be invoked when a line has been entered on the telnet client.
* Here we want to pass that line to the JS parser for processing.
*/
static void telnetLineCB(char *line) {
jsiConsolePrintf("LineCB: %s", line);
// Pass the line to the interactive module ...
jshPushIOCharEvents(jsiGetConsoleDevice(), line, strlen(line));
//jspEvaluate(line, true);
//jsiDumpState();
telnet_send("JS> ");
} // End of lineCB
/**
* When we have been allocated a TCP/IP address, this function is called back. Obviously
* there is little we can do at the network level until we have an IP.
*/
static void gotIpCallback() {
telnet_startListening(telnetLineCB);
} // End of gotIpCallback
/**
* \brief Perform the main loop processing.
* This is where work is performed
* as often as possible.
*/
static void mainLoop() {
if (suspendMainLoopFlag == true) {
return;
}
jsiLoop();
#ifdef EPS8266_BOARD_HEARTBEAT
if (system_get_time() - lastTime > 1000 * 1000 * 5) {
lastTime = system_get_time();
os_printf("tick: %d\n", jshGetSystemTime());
}
#endif
// Setup for another callback
queueTaskMainLoop();
} // End of mainLoop
/**
* The ESP8266 provides a mechanism to register a callback that is invoked when initialization
* of the ESP8266 is complete. This is the implementation of that callback. At this point
* we can assume that the ESP8266 is fully ready to do work for us.
*/
static void initDone() {
os_printf("initDone invoked\n");
// Discard any junk data in the input as this is a boot.
//uart_rx_discard();
jshInit(); // Initialize the hardware
jsvInit(); // Initialize the variables
jsiInit(false); // Initialize the interactive subsystem
// Register the event handlers.
system_os_task(eventHandler, TASK_APP_QUEUE, taskAppQueue, TASK_QUEUE_LENGTH);
// At this point, our JavaScript environment should be up and running.
// Initialize the networking subsystem.
jswrap_ESP8266WiFi_init();
// Post the first event to get us going.
queueTaskMainLoop();
return;
} // End of initDone
/**
* This is a required function needed for ESP8266 SDK. In 99.999% of the instances, this function
* needs to be present but have no body. It isn't 100% known what this function does other than
* provide an architected callback during initializations. However, its purpose is unknown.
*/
void user_rf_pre_init() {
} // End of user_rf_pre_init
/**
* \brief The main entry point in an ESP8266 application.
* It is where the logic of ESP8266 starts.
*/
void user_init() {
// Initialize the UART devices
uart_init(BIT_RATE_115200, BIT_RATE_115200);
UART_SetPrintPort(1);
// Dump the restart exception information.
dumpRestart();
// Register the ESP8266 initialization callback.
system_init_done_cb(initDone);
// Do NOT attempt to auto connect to an access point.
//wifi_station_set_auto_connect(0);
os_timer_setfn(&mainLoopSuspendTimer, enableMainLoop, NULL);
} // End of user_init
// End of file