Another gotcha with the ESP8266 non-OS SDK—
Before sending data over a TCP connection, you must register a callback function to handle “data successfully sent” events before calling espconn_connect() or espconn_send(). Although this strict requirement isn’t highlighted in the documentation, a fatal exception will reset the ESP8266 when this callback is not specified.
You register the callback function with espconn_regist_sentcb(). The signature of the function is void (espconn_sent_callback)(void *), and the parameter is a pointer to the struct espconn used for sending the data.
Example:
static ICACHE_FLASH_ATTR void espconn_sent2(void *arg)
{
struct espconn *espconn = (struct espconn *)arg;
os_printf("Sent data\r\n");
state_current = IDLE;
}
static ICACHE_FLASH_ATTR void espconn_received(void *arg, char *pdata, unsigned short len)
{
struct espconn *espconn = (struct espconn *)arg;
os_printf("Received data: %s\r\n", pdata);
state_current = IDLE;
}
void tcp_connect()
{
struct espconn *espconn = (struct espconn *)os_zalloc(sizeof(struct espconn));
espconn->type = ESPCONN_TCP;
espconn->state = ESPCONN_NONE;
espconn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
os_memcpy(espconn->proto.tcp->remote_ip, &addr->addr, 4);
espconn->proto.tcp->remote_port = 80;
espconn_regist_connectcb(espconn, espconn_connected);
espconn_regist_reconcb(espconn, espconn_reconnect);
// IMPORTANT! These callbacks must be registered.
espconn_regist_sentcb(espconn, espconn_sent2);
espconn_regist_recvcb(espconn, espconn_received);
espconn_set_opt(espconn, ESPCONN_NODELAY | ESPCONN_KEEPALIVE);
sint8 result = espconn_connect(espconn);
os_printf("Connection result: %d\r\n", result);
}