The driver for the ESP32 WiFi module

The ESP32 WiFi driver for Mbed OS

The Mbed OS driver for the ESP32 WiFi module.

Firmware version

How to write mbed-os compatible firmware : https://github.com/d-kato/GR-Boards_ESP32_Serial_Bridge

Restrictions

  • Setting up an UDP server is not possible
  • The serial port does not have hardware flow control enabled. The AT command set does not either have a way to limit the download rate. Therefore, downloading anything larger than the serial port input buffer is unreliable. An application should be able to read fast enough to stay ahead of the network. This affects mostly the TCP protocol where data would be lost with no notification. On UDP, this would lead to only packet losses which the higher layer protocol should recover from.

Committer:
dkato
Date:
Mon Jul 02 02:21:21 2018 +0000
Revision:
1:5d78eedef723
Parent:
0:92d12d355ba9
Synchronized with git revision 5407cadab12f6c2a07348950b2fcde42b9d7a050

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:92d12d355ba9 1 /* ESP32 implementation of NetworkInterfaceAPI
dkato 0:92d12d355ba9 2 * Copyright (c) 2015 ARM Limited
dkato 0:92d12d355ba9 3 * Copyright (c) 2017 Renesas Electronics Corporation
dkato 0:92d12d355ba9 4 *
dkato 0:92d12d355ba9 5 * Licensed under the Apache License, Version 2.0 (the "License");
dkato 0:92d12d355ba9 6 * you may not use this file except in compliance with the License.
dkato 0:92d12d355ba9 7 * You may obtain a copy of the License at
dkato 0:92d12d355ba9 8 *
dkato 0:92d12d355ba9 9 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:92d12d355ba9 10 *
dkato 0:92d12d355ba9 11 * Unless required by applicable law or agreed to in writing, software
dkato 0:92d12d355ba9 12 * distributed under the License is distributed on an "AS IS" BASIS,
dkato 0:92d12d355ba9 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:92d12d355ba9 14 * See the License for the specific language governing permissions and
dkato 0:92d12d355ba9 15 * limitations under the License.
dkato 0:92d12d355ba9 16 */
dkato 0:92d12d355ba9 17
dkato 0:92d12d355ba9 18 #include <string.h>
dkato 0:92d12d355ba9 19 #include "ESP32Stack.h"
dkato 0:92d12d355ba9 20
dkato 0:92d12d355ba9 21 // ESP32Stack implementation
dkato 1:5d78eedef723 22 ESP32Stack::ESP32Stack(PinName en, PinName io0, PinName tx, PinName rx, bool debug,
dkato 1:5d78eedef723 23 PinName rts, PinName cts, int baudrate)
dkato 0:92d12d355ba9 24 {
dkato 1:5d78eedef723 25 _esp = ESP32::getESP32Inst(en, io0, tx, rx, debug, rts, cts, baudrate);
dkato 0:92d12d355ba9 26 memset(_local_ports, 0, sizeof(_local_ports));
dkato 0:92d12d355ba9 27 }
dkato 0:92d12d355ba9 28
dkato 0:92d12d355ba9 29 struct esp32_socket {
dkato 0:92d12d355ba9 30 int id;
dkato 0:92d12d355ba9 31 nsapi_protocol_t proto;
dkato 0:92d12d355ba9 32 bool connected;
dkato 0:92d12d355ba9 33 SocketAddress addr;
dkato 0:92d12d355ba9 34 int keepalive; // TCP
dkato 0:92d12d355ba9 35 bool accept_id;
dkato 0:92d12d355ba9 36 bool tcp_server;
dkato 0:92d12d355ba9 37 };
dkato 0:92d12d355ba9 38
dkato 0:92d12d355ba9 39 int ESP32Stack::socket_open(void **handle, nsapi_protocol_t proto)
dkato 0:92d12d355ba9 40 {
dkato 0:92d12d355ba9 41 // Look for an unused socket
dkato 0:92d12d355ba9 42 int id = _esp->get_free_id();
dkato 0:92d12d355ba9 43
dkato 0:92d12d355ba9 44 if (id == -1) {
dkato 0:92d12d355ba9 45 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 46 }
dkato 0:92d12d355ba9 47
dkato 0:92d12d355ba9 48 struct esp32_socket *socket = new struct esp32_socket;
dkato 0:92d12d355ba9 49 if (!socket) {
dkato 0:92d12d355ba9 50 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 51 }
dkato 0:92d12d355ba9 52
dkato 0:92d12d355ba9 53 socket->id = id;
dkato 0:92d12d355ba9 54 socket->proto = proto;
dkato 0:92d12d355ba9 55 socket->connected = false;
dkato 0:92d12d355ba9 56 socket->keepalive = 0;
dkato 0:92d12d355ba9 57 socket->accept_id = false;
dkato 0:92d12d355ba9 58 socket->tcp_server = false;
dkato 0:92d12d355ba9 59 *handle = socket;
dkato 0:92d12d355ba9 60 return 0;
dkato 0:92d12d355ba9 61 }
dkato 0:92d12d355ba9 62
dkato 0:92d12d355ba9 63 int ESP32Stack::socket_close(void *handle)
dkato 0:92d12d355ba9 64 {
dkato 0:92d12d355ba9 65 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 66 int err = 0;
dkato 0:92d12d355ba9 67
dkato 0:92d12d355ba9 68 if (!socket) {
dkato 0:92d12d355ba9 69 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 70 }
dkato 0:92d12d355ba9 71
dkato 0:92d12d355ba9 72 if (!_esp->close(socket->id, socket->accept_id)) {
dkato 0:92d12d355ba9 73 err = NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 74 }
dkato 0:92d12d355ba9 75
dkato 0:92d12d355ba9 76 if (socket->tcp_server) {
dkato 0:92d12d355ba9 77 _esp->del_server();
dkato 0:92d12d355ba9 78 }
dkato 0:92d12d355ba9 79 _local_ports[socket->id] = 0;
dkato 0:92d12d355ba9 80
dkato 0:92d12d355ba9 81 delete socket;
dkato 0:92d12d355ba9 82 return err;
dkato 0:92d12d355ba9 83 }
dkato 0:92d12d355ba9 84
dkato 0:92d12d355ba9 85 int ESP32Stack::socket_bind(void *handle, const SocketAddress &address)
dkato 0:92d12d355ba9 86 {
dkato 0:92d12d355ba9 87 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 88
dkato 0:92d12d355ba9 89 if (!socket) {
dkato 0:92d12d355ba9 90 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 91 }
dkato 0:92d12d355ba9 92
dkato 0:92d12d355ba9 93 if (socket->proto == NSAPI_UDP) {
dkato 0:92d12d355ba9 94 if(address.get_addr().version != NSAPI_UNSPEC) {
dkato 0:92d12d355ba9 95 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 96 }
dkato 0:92d12d355ba9 97
dkato 0:92d12d355ba9 98 for(int id = 0; id < ESP32::SOCKET_COUNT; id++) {
dkato 0:92d12d355ba9 99 if(_local_ports[id] == address.get_port() && id != socket->id) { // Port already reserved by another socket
dkato 0:92d12d355ba9 100 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 101 } else if (id == socket->id && socket->connected) {
dkato 0:92d12d355ba9 102 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 103 }
dkato 0:92d12d355ba9 104 }
dkato 0:92d12d355ba9 105 _local_ports[socket->id] = address.get_port();
dkato 0:92d12d355ba9 106 return 0;
dkato 0:92d12d355ba9 107 }
dkato 0:92d12d355ba9 108
dkato 0:92d12d355ba9 109 socket->addr = address;
dkato 0:92d12d355ba9 110 return 0;
dkato 0:92d12d355ba9 111 }
dkato 0:92d12d355ba9 112
dkato 0:92d12d355ba9 113 int ESP32Stack::socket_listen(void *handle, int backlog)
dkato 0:92d12d355ba9 114 {
dkato 0:92d12d355ba9 115 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 116
dkato 0:92d12d355ba9 117 (void)backlog;
dkato 0:92d12d355ba9 118
dkato 0:92d12d355ba9 119 if (!socket) {
dkato 0:92d12d355ba9 120 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 121 }
dkato 0:92d12d355ba9 122
dkato 0:92d12d355ba9 123 if (socket->proto != NSAPI_TCP) {
dkato 0:92d12d355ba9 124 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 125 }
dkato 0:92d12d355ba9 126
dkato 0:92d12d355ba9 127 if (!_esp->cre_server(socket->addr.get_port())) {
dkato 0:92d12d355ba9 128 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 129 }
dkato 0:92d12d355ba9 130
dkato 0:92d12d355ba9 131 socket->tcp_server = true;
dkato 0:92d12d355ba9 132 return 0;
dkato 0:92d12d355ba9 133 }
dkato 0:92d12d355ba9 134
dkato 0:92d12d355ba9 135 int ESP32Stack::socket_connect(void *handle, const SocketAddress &addr)
dkato 0:92d12d355ba9 136 {
dkato 0:92d12d355ba9 137 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 138
dkato 0:92d12d355ba9 139 if (!socket) {
dkato 0:92d12d355ba9 140 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 141 }
dkato 0:92d12d355ba9 142
dkato 0:92d12d355ba9 143 if (socket->proto == NSAPI_UDP) {
dkato 0:92d12d355ba9 144 if (!_esp->open("UDP", socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id])) {
dkato 0:92d12d355ba9 145 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 146 }
dkato 0:92d12d355ba9 147 } else {
dkato 0:92d12d355ba9 148 if (!_esp->open("TCP", socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) {
dkato 0:92d12d355ba9 149 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 150 }
dkato 0:92d12d355ba9 151 }
dkato 0:92d12d355ba9 152
dkato 0:92d12d355ba9 153 socket->connected = true;
dkato 0:92d12d355ba9 154 return 0;
dkato 0:92d12d355ba9 155 }
dkato 0:92d12d355ba9 156
dkato 0:92d12d355ba9 157 int ESP32Stack::socket_accept(void *server, void **socket, SocketAddress *addr)
dkato 0:92d12d355ba9 158 {
dkato 0:92d12d355ba9 159 struct esp32_socket *socket_new = new struct esp32_socket;
dkato 0:92d12d355ba9 160 int id;
dkato 0:92d12d355ba9 161
dkato 0:92d12d355ba9 162 if (!socket_new) {
dkato 0:92d12d355ba9 163 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 164 }
dkato 0:92d12d355ba9 165
dkato 0:92d12d355ba9 166 if (!_esp->accept(&id)) {
dkato 0:92d12d355ba9 167 delete socket_new;
dkato 0:92d12d355ba9 168 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 169 }
dkato 0:92d12d355ba9 170
dkato 0:92d12d355ba9 171 socket_new->id = id;
dkato 0:92d12d355ba9 172 socket_new->proto = NSAPI_TCP;
dkato 0:92d12d355ba9 173 socket_new->connected = true;
dkato 0:92d12d355ba9 174 socket_new->accept_id = true;
dkato 0:92d12d355ba9 175 socket_new->tcp_server = false;
dkato 0:92d12d355ba9 176 *socket = socket_new;
dkato 0:92d12d355ba9 177
dkato 0:92d12d355ba9 178 return 0;
dkato 0:92d12d355ba9 179 }
dkato 0:92d12d355ba9 180
dkato 0:92d12d355ba9 181 int ESP32Stack::socket_send(void *handle, const void *data, unsigned size)
dkato 0:92d12d355ba9 182 {
dkato 0:92d12d355ba9 183 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 184
dkato 0:92d12d355ba9 185 if (!socket) {
dkato 0:92d12d355ba9 186 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 187 }
dkato 0:92d12d355ba9 188
dkato 0:92d12d355ba9 189 if (!_esp->send(socket->id, data, size)) {
dkato 0:92d12d355ba9 190 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 191 }
dkato 0:92d12d355ba9 192
dkato 0:92d12d355ba9 193 return size;
dkato 0:92d12d355ba9 194 }
dkato 0:92d12d355ba9 195
dkato 0:92d12d355ba9 196 int ESP32Stack::socket_recv(void *handle, void *data, unsigned size)
dkato 0:92d12d355ba9 197 {
dkato 0:92d12d355ba9 198 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 199
dkato 0:92d12d355ba9 200 if (!socket) {
dkato 0:92d12d355ba9 201 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 202 }
dkato 0:92d12d355ba9 203
dkato 0:92d12d355ba9 204 int32_t recv = _esp->recv(socket->id, data, size);
dkato 0:92d12d355ba9 205 if (recv == -1) {
dkato 0:92d12d355ba9 206 return NSAPI_ERROR_WOULD_BLOCK;
dkato 0:92d12d355ba9 207 } else if (recv < 0) {
dkato 0:92d12d355ba9 208 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 209 } else {
dkato 0:92d12d355ba9 210 // do nothing
dkato 0:92d12d355ba9 211 }
dkato 0:92d12d355ba9 212
dkato 0:92d12d355ba9 213 return recv;
dkato 0:92d12d355ba9 214 }
dkato 0:92d12d355ba9 215
dkato 0:92d12d355ba9 216 int ESP32Stack::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
dkato 0:92d12d355ba9 217 {
dkato 0:92d12d355ba9 218 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 219
dkato 0:92d12d355ba9 220 if (!socket) {
dkato 0:92d12d355ba9 221 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 222 }
dkato 0:92d12d355ba9 223
dkato 0:92d12d355ba9 224 if (socket->connected && socket->addr != addr) {
dkato 0:92d12d355ba9 225 if (!_esp->close(socket->id, socket->accept_id)) {
dkato 0:92d12d355ba9 226 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:92d12d355ba9 227 }
dkato 0:92d12d355ba9 228 socket->connected = false;
dkato 0:92d12d355ba9 229 }
dkato 0:92d12d355ba9 230
dkato 0:92d12d355ba9 231 if (!socket->connected) {
dkato 0:92d12d355ba9 232 int err = socket_connect(socket, addr);
dkato 0:92d12d355ba9 233 if (err < 0) {
dkato 0:92d12d355ba9 234 return err;
dkato 0:92d12d355ba9 235 }
dkato 0:92d12d355ba9 236 socket->addr = addr;
dkato 0:92d12d355ba9 237 }
dkato 0:92d12d355ba9 238
dkato 0:92d12d355ba9 239 return socket_send(socket, data, size);
dkato 0:92d12d355ba9 240 }
dkato 0:92d12d355ba9 241
dkato 0:92d12d355ba9 242 int ESP32Stack::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
dkato 0:92d12d355ba9 243 {
dkato 0:92d12d355ba9 244 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 245
dkato 0:92d12d355ba9 246 if (!socket) {
dkato 0:92d12d355ba9 247 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 248 }
dkato 0:92d12d355ba9 249
dkato 0:92d12d355ba9 250 int ret = socket_recv(socket, data, size);
dkato 0:92d12d355ba9 251 if (ret >= 0 && addr) {
dkato 0:92d12d355ba9 252 *addr = socket->addr;
dkato 0:92d12d355ba9 253 }
dkato 0:92d12d355ba9 254
dkato 0:92d12d355ba9 255 return ret;
dkato 0:92d12d355ba9 256 }
dkato 0:92d12d355ba9 257
dkato 0:92d12d355ba9 258 void ESP32Stack::socket_attach(void *handle, void (*callback)(void *), void *data)
dkato 0:92d12d355ba9 259 {
dkato 0:92d12d355ba9 260 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 261
dkato 0:92d12d355ba9 262 if (!socket) {
dkato 0:92d12d355ba9 263 return;
dkato 0:92d12d355ba9 264 }
dkato 0:92d12d355ba9 265
dkato 0:92d12d355ba9 266 _esp->socket_attach(socket->id, callback, data);
dkato 0:92d12d355ba9 267 }
dkato 0:92d12d355ba9 268
dkato 0:92d12d355ba9 269 nsapi_error_t ESP32Stack::setsockopt(nsapi_socket_t handle, int level,
dkato 0:92d12d355ba9 270 int optname, const void *optval, unsigned optlen)
dkato 0:92d12d355ba9 271 {
dkato 0:92d12d355ba9 272 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 273
dkato 0:92d12d355ba9 274 if (!optlen) {
dkato 0:92d12d355ba9 275 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 276 } else if (!socket) {
dkato 0:92d12d355ba9 277 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 278 }
dkato 0:92d12d355ba9 279
dkato 0:92d12d355ba9 280 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
dkato 0:92d12d355ba9 281 switch (optname) {
dkato 0:92d12d355ba9 282 case NSAPI_KEEPALIVE: {
dkato 0:92d12d355ba9 283 if(socket->connected) {// ESP32 limitation, keepalive needs to be given before connecting
dkato 0:92d12d355ba9 284 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 285 }
dkato 0:92d12d355ba9 286
dkato 0:92d12d355ba9 287 if (optlen == sizeof(int)) {
dkato 0:92d12d355ba9 288 int secs = *(int *)optval;
dkato 0:92d12d355ba9 289 if (secs >= 0 && secs <= 7200) {
dkato 0:92d12d355ba9 290 socket->keepalive = secs;
dkato 0:92d12d355ba9 291 return NSAPI_ERROR_OK;
dkato 0:92d12d355ba9 292 }
dkato 0:92d12d355ba9 293 }
dkato 0:92d12d355ba9 294 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 295 }
dkato 0:92d12d355ba9 296 }
dkato 0:92d12d355ba9 297 }
dkato 0:92d12d355ba9 298
dkato 0:92d12d355ba9 299 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 300 }
dkato 0:92d12d355ba9 301
dkato 0:92d12d355ba9 302 nsapi_error_t ESP32Stack::getsockopt(nsapi_socket_t handle, int level,
dkato 0:92d12d355ba9 303 int optname, void *optval, unsigned *optlen)
dkato 0:92d12d355ba9 304 {
dkato 0:92d12d355ba9 305 struct esp32_socket *socket = (struct esp32_socket *)handle;
dkato 0:92d12d355ba9 306
dkato 0:92d12d355ba9 307 if (!optval || !optlen) {
dkato 0:92d12d355ba9 308 return NSAPI_ERROR_PARAMETER;
dkato 0:92d12d355ba9 309 } else if (!socket) {
dkato 0:92d12d355ba9 310 return NSAPI_ERROR_NO_SOCKET;
dkato 0:92d12d355ba9 311 }
dkato 0:92d12d355ba9 312
dkato 0:92d12d355ba9 313 if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
dkato 0:92d12d355ba9 314 switch (optname) {
dkato 0:92d12d355ba9 315 case NSAPI_KEEPALIVE: {
dkato 0:92d12d355ba9 316 if(*optlen > sizeof(int)) {
dkato 0:92d12d355ba9 317 *optlen = sizeof(int);
dkato 0:92d12d355ba9 318 }
dkato 0:92d12d355ba9 319 memcpy(optval, &(socket->keepalive), *optlen);
dkato 0:92d12d355ba9 320 return NSAPI_ERROR_OK;
dkato 0:92d12d355ba9 321 }
dkato 0:92d12d355ba9 322 }
dkato 0:92d12d355ba9 323 }
dkato 0:92d12d355ba9 324
dkato 0:92d12d355ba9 325 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:92d12d355ba9 326 }
dkato 0:92d12d355ba9 327