January 12, 2015, 12:36 am
The following code for the esp8266 shows how you might write to the user flash area and implement a simple key/value store. I wouldn’t use this for anything, but the example may be instructive.
The memory map of the esp8266 isn’t yet fully understood, but there appears to be a user writable area at the location identified as 0x3C00. All flash reads/writes are executed via the library functions spi_flash_xxx. I assume this region of flash is marked for user applications only, and there’s no possibility of user code overflowing into this area. I don’t know how large this region is. If you know, please comment below or send me an email.
I’ve also noticed someone here disabling UART interrupts during flash writes using ETS_UART_INTR_DISABLE() and ETS_UART_INTR_ENABLE(). I’m not doing this in the code below, but it is possibly important to do so.
#include "flash.h"
ICACHE_FLASH_ATTR static char *find_key(const char *key,char *settings) {
int n;
for(n=0;n<1024;n+=128) {
if(strcmp(key,settings+n) == 0) return settings+n;
}
return 0;
}
ICACHE_FLASH_ATTR static char *find_free(char *settings) {
int n;
for(n=0;n<1024;n+=128) {
if(settings[n] == 0) return settings+n;
}
return 0;
}
ICACHE_FLASH_ATTR void flash_erase_all() {
char settings[1024];
int n;
for(n=0;n<1024;n++) settings[n]=0;
spi_flash_erase_sector(0x3C);
spi_flash_write(0x3C000,settings,1024);
}
ICACHE_FLASH_ATTR int flash_key_value_set(const char *key,const char *value) {
if(strlen(key) > 64) return 1;
if(strlen(value) > 64) return 1;
char settings[1024];
spi_flash_read(0x3C000, (uint32 *) settings, 1024);
char *location = find_key(key,settings);
if(location == NULL) {
location = find_free(settings);
}
if(location == NULL) return 0;
strcpy(location,key);
strcpy(location+64,value);
spi_flash_erase_sector(0x3C);
spi_flash_write(0x3C000,settings,1024);
return 1;
}
ICACHE_FLASH_ATTR int flash_key_value_get(char *key,char *value) {
if(strlen(key) > 64) return 0;
if(strlen(value) > 64) return 0;
char settings[1024];
spi_flash_read(0x3C000, (uint32 *) settings, 1024);
char *location = find_key(key,settings);
if(location == NULL) value[0]=0;
strcpy(value,location+64);
return 1;
}
This is a continuation of my notes on the esp8266 microcontroller, you can find a complete list of my esp8266 posts here
January 11, 2015, 12:33 am
I’ve been working on some code that accepts incoming connections on the esp8266, if your looking for a full HTTP server take a look at sprite_tm’s code. But these are my notes on accepting a TCP connection.
As with TCP transmissions, you register a bunch of callbacks which process connections. So the first step is to initialize the TCP system with your connect callback:
#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
static struct espconn httpconfig_conn;
static esp_tcp httpconfig_tcp_conn;
void ICACHE_FLASH_ATTR httpconfig_conn_init() {
httpconfig_conn.type=ESPCONN_TCP;
httpconfig_conn.state=ESPCONN_NONE;
httpconfig_tcp_conn.local_port=80;
httpconfig_conn.proto.tcp=&httpconfig_tcp_conn;
espconn_regist_connectcb(&httpconfig_conn, httpconfig_connected_cb);
espconn_accept(&httpconfig_conn);
}
When a connection is received on the specified port, httpconfig_connected_cb will be called. In this function you can send data to the client, and register other functions to trigger when data is received/disconnect etc.
static void ICACHE_FLASH_ATTR httpconfig_recv_cb(void *arg, char *data, unsigned short len) {
struct espconn *conn=(struct espconn *)arg;
espconn_disconnect(conn);
}
static void ICACHE_FLASH_ATTR httpconfig_recon_cb(void *arg, sint8 err) {
}
static void ICACHE_FLASH_ATTR httpconfig_discon_cb(void *arg) {
}
static void ICACHE_FLASH_ATTR httpconfig_sent_cb(void *arg) {
}
static void ICACHE_FLASH_ATTR httpconfig_connected_cb(void *arg) {
struct espconn *conn=arg;
espconn_regist_recvcb (conn, httpconfig_recv_cb);
espconn_regist_reconcb (conn, httpconfig_recon_cb);
espconn_regist_disconcb(conn, httpconfig_discon_cb);
espconn_regist_sentcb (conn, httpconfig_sent_cb);
char *transmission = "OK\r\n\r\nOK!\n";
sint8 d = espconn_sent(conn,transmission,strlen(transmission));
}
I currently don’t fully understand what the reconnect callback does. If you know, please mail me.
January 10, 2015, 1:51 am


I’ve been putting together a small carrier board to allow a esp8266 board to sit on an XBee connector. The design is shown above (as yet untested). The gerbers and Kicad design files are available for download below.
XBee_esp8266 Gerbers
Kicad files (and gerbers)
UPDATE: The first rev of these boards came though, I’ll be needing to update the design. The esp1 faces in the opposite direction to what I’d like. The serial TX and RX connections are connected the wrong way to the FTDI header (which doesn’t matter too much as it’s just there for debugging). The fit into the XBee header also seems poor, I’m not sure if this is just because I’ve killed the header I’m using by jamming 2.54mm pins into it. Here the a couple of pics in any case:


UPDATE: Sent out a rev with the header flipped. Wanted to get it out before I go away to China. Here are the pics:


And the new gerbers: gerbers
UPDATE2: The new boards came back, and I’ve now tested them all looks good! Pics below:


This is a continuation of my notes on the esp8266 microcontroller, you can find a complete list of my esp8266 posts here
January 9, 2015, 10:11 pm
The following code, when used in user_init() will enable the internal pullup on GPIO0 and read it’s value. Unfortunately GPIO0 (and GPIO2) when held low at boot put the device into a non-running mode (firmware update), I’ve also been unsuccessful in using the internal pulldowns on these pins. This means these pins can not be used for user mode selection at boot, using the internal pullup/down resistors. And unfortunately, those are the only GPIOs available on the simplest modules. It maybe possible if an external pulldown is installed.
gpio_init();
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO0_U);
os_delay_us(10000);
int config = GPIO_INPUT_GET(0);//GPIO_ID_PIN(PERIPHS_IO_MUX_GPIO0_U));
char buffer[30];
os_sprintf(buffer,"config: %d",config);
This is a continuation of my notes on the esp8266 microcontroller, you can find a complete list of my esp8266 posts here