Zephyr API Documentation  2.7.0-rc2
A Scalable Open Source RTOS
esp.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 Tobias Svehagen
3 * Copyright (c) 2020 Grinn
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef ZEPHYR_INCLUDE_DRIVERS_WIFI_ESP_AT_ESP_H_
9#define ZEPHYR_INCLUDE_DRIVERS_WIFI_ESP_AT_ESP_H_
10
11#include <kernel.h>
12#include <net/net_context.h>
13#include <net/net_if.h>
14#include <net/net_ip.h>
15#include <net/net_pkt.h>
16#include <net/wifi_mgmt.h>
17
18#include "modem_context.h"
19#include "modem_cmd_handler.h"
20#include "modem_iface_uart.h"
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26/* Define the commands that differ between the AT versions */
27#if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
28#define _CWMODE "CWMODE_CUR"
29#define _CWSAP "CWSAP_CUR"
30#define _CWJAP "CWJAP_CUR"
31#define _CIPSTA "CIPSTA_CUR"
32#define _CIPSTAMAC "CIPSTAMAC_CUR"
33#define _CIPRECVDATA "+CIPRECVDATA,"
34#define _CIPRECVDATA_END ':'
35#else
36#define _CWMODE "CWMODE"
37#define _CWSAP "CWSAP"
38#define _CWJAP "CWJAP"
39#define _CIPSTA "CIPSTA"
40#define _CIPSTAMAC "CIPSTAMAC"
41#define _CIPRECVDATA "+CIPRECVDATA:"
42#define _CIPRECVDATA_END ','
43#endif
44
45/*
46 * Passive mode differs a bit between firmware versions and the macro
47 * ESP_PROTO_PASSIVE is therefore used to determine what protocol operates in
48 * passive mode. For AT version 1.7 passive mode only affects TCP but in AT
49 * version 2.0 it affects both TCP and UDP.
50 */
51#if defined(CONFIG_WIFI_ESP_AT_PASSIVE_MODE)
52#if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
53#define ESP_PROTO_PASSIVE(proto) (proto == IPPROTO_TCP)
54#else
55#define ESP_PROTO_PASSIVE(proto) \
56 (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
57#endif /* CONFIG_WIFI_ESP_AT_VERSION_1_7 */
58#else
59#define ESP_PROTO_PASSIVE(proto) 0
60#endif /* CONFIG_WIFI_ESP_AT_PASSIVE_MODE */
61
62#define ESP_BUS DT_BUS(DT_DRV_INST(0))
63
64#if DT_PROP(ESP_BUS, hw_flow_control) == 1
65#define _FLOW_CONTROL "3"
66#else
67#define _FLOW_CONTROL "0"
68#endif
69
70#if DT_INST_NODE_HAS_PROP(0, target_speed)
71#define _UART_BAUD DT_INST_PROP(0, target_speed)
72#else
73#define _UART_BAUD DT_PROP(ESP_BUS, current_speed)
74#endif
75
76#define _UART_CUR \
77 STRINGIFY(_UART_BAUD)",8,1,0,"_FLOW_CONTROL
78
79#define CONN_CMD_MAX_LEN (sizeof("AT+"_CWJAP"=\"\",\"\"") + \
80 WIFI_SSID_MAX_LEN + WIFI_PSK_MAX_LEN)
81
82#if defined(CONFIG_WIFI_ESP_AT_DNS_USE)
83#define ESP_MAX_DNS MIN(3, CONFIG_DNS_RESOLVER_MAX_SERVERS)
84#else
85#define ESP_MAX_DNS 0
86#endif
87
88#define ESP_MAX_SOCKETS 5
89
90/* Maximum amount that can be sent with CIPSEND and read with CIPRECVDATA */
91#define ESP_MTU 2048
92#define CIPRECVDATA_MAX_LEN ESP_MTU
93
94#define INVALID_LINK_ID 255
95
96#define MDM_RING_BUF_SIZE CONFIG_WIFI_ESP_AT_MDM_RING_BUF_SIZE
97#define MDM_RECV_MAX_BUF CONFIG_WIFI_ESP_AT_MDM_RX_BUF_COUNT
98#define MDM_RECV_BUF_SIZE CONFIG_WIFI_ESP_AT_MDM_RX_BUF_SIZE
99
100#define ESP_CMD_TIMEOUT K_SECONDS(10)
101#define ESP_SCAN_TIMEOUT K_SECONDS(10)
102#define ESP_CONNECT_TIMEOUT K_SECONDS(20)
103#define ESP_INIT_TIMEOUT K_SECONDS(10)
104
105#define ESP_MODE_NONE 0
106#define ESP_MODE_STA 1
107#define ESP_MODE_AP 2
108#define ESP_MODE_STA_AP 3
109
110#define ESP_CMD_CWMODE(mode) \
111 "AT+"_CWMODE"="STRINGIFY(_CONCAT(ESP_MODE_, mode))
112
113#define ESP_CWDHCP_MODE_STATION "1"
114#if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
115#define ESP_CWDHCP_MODE_SOFTAP "0"
116#else
117#define ESP_CWDHCP_MODE_SOFTAP "2"
118#endif
119
120#if defined(CONFIG_WIFI_ESP_AT_VERSION_1_7)
121#define _ESP_CMD_DHCP_ENABLE(mode, enable) \
122 "AT+CWDHCP_CUR=" mode "," STRINGIFY(enable)
123#else
124#define _ESP_CMD_DHCP_ENABLE(mode, enable) \
125 "AT+CWDHCP=" STRINGIFY(enable) "," mode
126#endif
127
128#define ESP_CMD_DHCP_ENABLE(mode, enable) \
129 _ESP_CMD_DHCP_ENABLE(_CONCAT(ESP_CWDHCP_MODE_, mode), enable)
130
131#define ESP_CMD_SET_IP(ip, gateway, mask) "AT+"_CIPSTA"=\"" \
132 ip "\",\"" gateway "\",\"" mask "\""
133
134extern struct esp_data esp_driver_data;
135
142};
143
145 /* internal */
146 struct k_mutex lock;
148
152
153 /* socket info */
154 struct sockaddr dst;
155
156 /* sem */
157 union {
158 /* handles blocking receive */
159 struct k_sem sem_data_ready;
160
161 /* notifies about reaching 0 refcount */
162 struct k_sem sem_free;
163 };
164
165 /* work */
170
171 /* TX packets fifo */
173
174 /* net context */
178
179 /* callback data */
182};
183
189};
190
191/* driver data */
192struct esp_data {
194
197
199
200 /* addresses */
201 struct in_addr ip;
202 struct in_addr gw;
203 struct in_addr nm;
206
207 /* modem context */
208 struct modem_context mctx;
209
210 /* modem interface */
211 struct modem_iface_uart_data iface_data;
213
214 /* modem cmds */
215 struct modem_cmd_handler_data cmd_handler_data;
217
218 /* socket data */
221
222 /* work */
230
232
233 /* semaphores */
234 struct k_sem sem_tx_ready;
235 struct k_sem sem_response;
236 struct k_sem sem_if_ready;
237};
238
239int esp_offload_init(struct net_if *iface);
240
241struct esp_socket *esp_socket_get(struct esp_data *data,
242 struct net_context *context);
243int esp_socket_put(struct esp_socket *sock);
244void esp_socket_init(struct esp_data *data);
245void esp_socket_close(struct esp_socket *sock);
246void esp_socket_rx(struct esp_socket *sock, struct net_buf *buf,
247 size_t offset, size_t len);
249struct esp_socket *esp_socket_ref(struct esp_socket *sock);
250void esp_socket_unref(struct esp_socket *sock);
251
252static inline
255{
256 if (link_id >= ARRAY_SIZE(data->sockets)) {
257 return NULL;
258 }
259
260 return esp_socket_ref(&data->sockets[link_id]);
261}
262
264 atomic_val_t value,
265 atomic_val_t mask)
266{
268
269 do {
270 flags = atomic_get(&sock->flags);
271 } while (!atomic_cas(&sock->flags, flags, (flags & ~mask) | value));
272
273 return flags;
274}
275
276static inline
278 atomic_val_t clear_flags,
279 atomic_val_t set_flags)
280{
281 return esp_socket_flags_update(sock, set_flags,
282 clear_flags | set_flags);
283}
284
287{
288 return atomic_or(&sock->flags, flags);
289}
290
291static inline bool esp_socket_flags_test_and_clear(struct esp_socket *sock,
293{
294 return (atomic_and(&sock->flags, ~flags) & flags);
295}
296
297static inline bool esp_socket_flags_test_and_set(struct esp_socket *sock,
299{
300 return (atomic_or(&sock->flags, flags) & flags);
301}
302
305{
306 return atomic_and(&sock->flags, ~flags);
307}
308
309static inline atomic_val_t esp_socket_flags(struct esp_socket *sock)
310{
311 return atomic_get(&sock->flags);
312}
313
314static inline struct esp_data *esp_socket_to_dev(struct esp_socket *sock)
315{
316 return CONTAINER_OF(sock - sock->idx, struct esp_data, sockets);
317}
318
319static inline void __esp_socket_work_submit(struct esp_socket *sock,
320 struct k_work *work)
321{
322 struct esp_data *data = esp_socket_to_dev(sock);
323
325}
326
327static inline int esp_socket_work_submit(struct esp_socket *sock,
328 struct k_work *work)
329{
330 int ret = -EBUSY;
331
332 k_mutex_lock(&sock->lock, K_FOREVER);
334 __esp_socket_work_submit(sock, work);
335 ret = 0;
336 }
337 k_mutex_unlock(&sock->lock);
338
339 return ret;
340}
341
342static inline int esp_socket_queue_tx(struct esp_socket *sock,
343 struct net_pkt *pkt)
344{
345 int ret = -EBUSY;
346
347 k_mutex_lock(&sock->lock, K_FOREVER);
349 k_fifo_put(&sock->tx_fifo, pkt);
350 __esp_socket_work_submit(sock, &sock->send_work);
351 ret = 0;
352 }
353 k_mutex_unlock(&sock->lock);
354
355 return ret;
356}
357
358static inline bool esp_socket_connected(struct esp_socket *sock)
359{
360 return (esp_socket_flags(sock) & ESP_SOCK_CONNECTED) != 0;
361}
362
363static inline void esp_flags_set(struct esp_data *dev, uint8_t flags)
364{
365 dev->flags |= flags;
366}
367
368static inline void esp_flags_clear(struct esp_data *dev, uint8_t flags)
369{
370 dev->flags &= (~flags);
371}
372
373static inline bool esp_flags_are_set(struct esp_data *dev, uint8_t flags)
374{
375 return (dev->flags & flags) != 0;
376}
377
378static inline enum net_sock_type esp_socket_type(struct esp_socket *sock)
379{
380 return net_context_get_type(sock->context);
381}
382
383static inline enum net_ip_protocol esp_socket_ip_proto(struct esp_socket *sock)
384{
385 return net_context_get_ip_proto(sock->context);
386}
387
388static inline int esp_cmd_send(struct esp_data *data,
389 const struct modem_cmd *handlers,
390 size_t handlers_len, const char *buf,
392{
393 return modem_cmd_send(&data->mctx.iface, &data->mctx.cmd_handler,
394 handlers, handlers_len, buf, &data->sem_response,
395 timeout);
396}
397
398void esp_connect_work(struct k_work *work);
399void esp_recvdata_work(struct k_work *work);
400void esp_close_work(struct k_work *work);
401void esp_send_work(struct k_work *work);
402
403#ifdef __cplusplus
404}
405#endif
406
407#endif /* ZEPHYR_INCLUDE_DRIVERS_WIFI_ESP_AT_ESP_H_ */
atomic_t atomic_val_t
Definition: atomic.h:22
int atomic_t
Definition: atomic.h:21
static ALWAYS_INLINE atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
Definition: atomic_xtensa.h:111
static ALWAYS_INLINE bool atomic_cas(atomic_t *target, atomic_val_t oldval, atomic_val_t newval)
Definition: atomic_xtensa.h:42
static ALWAYS_INLINE atomic_val_t atomic_get(const atomic_t *target)
Definition: atomic_xtensa.h:16
static ALWAYS_INLINE atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
Definition: atomic_xtensa.h:99
ZTEST_BMEM int timeout
Definition: main.c:31
void esp_connect_work(struct k_work *work)
Definition: esp_offload.c:94
struct esp_socket * esp_socket_get(struct esp_data *data, struct net_context *context)
Definition: esp_socket.c:21
int esp_socket_put(struct esp_socket *sock)
Definition: esp_socket.c:45
static int esp_socket_queue_tx(struct esp_socket *sock, struct net_pkt *pkt)
Definition: esp.h:342
static enum net_ip_protocol esp_socket_ip_proto(struct esp_socket *sock)
Definition: esp.h:383
#define ESP_MAX_DNS
Definition: esp.h:85
void esp_recvdata_work(struct k_work *work)
Definition: esp_offload.c:480
#define ESP_MAX_SOCKETS
Definition: esp.h:88
static atomic_val_t esp_socket_flags_clear_and_set(struct esp_socket *sock, atomic_val_t clear_flags, atomic_val_t set_flags)
Definition: esp.h:277
static void esp_flags_set(struct esp_data *dev, uint8_t flags)
Definition: esp.h:363
struct esp_socket * esp_socket_ref(struct esp_socket *sock)
Definition: esp_socket.c:52
static int esp_cmd_send(struct esp_data *data, const struct modem_cmd *handlers, size_t handlers_len, const char *buf, k_timeout_t timeout)
Definition: esp.h:388
void esp_socket_workq_stop_and_flush(struct esp_socket *sock)
Definition: esp_socket.c:211
static bool esp_socket_flags_test_and_set(struct esp_socket *sock, atomic_val_t flags)
Definition: esp.h:297
static bool esp_flags_are_set(struct esp_data *dev, uint8_t flags)
Definition: esp.h:373
esp_data_flag
Definition: esp.h:184
@ EDF_STA_LOCK
Definition: esp.h:187
@ EDF_AP_ENABLED
Definition: esp.h:188
@ EDF_STA_CONNECTING
Definition: esp.h:185
@ EDF_STA_CONNECTED
Definition: esp.h:186
int esp_offload_init(struct net_if *iface)
Definition: esp_offload.c:639
void esp_send_work(struct k_work *work)
Definition: esp_offload.c:335
void esp_socket_unref(struct esp_socket *sock)
Definition: esp_socket.c:66
void esp_socket_rx(struct esp_socket *sock, struct net_buf *buf, size_t offset, size_t len)
Definition: esp_socket.c:146
static struct esp_data * esp_socket_to_dev(struct esp_socket *sock)
Definition: esp.h:314
static atomic_val_t esp_socket_flags_clear(struct esp_socket *sock, atomic_val_t flags)
Definition: esp.h:303
static bool esp_socket_flags_test_and_clear(struct esp_socket *sock, atomic_val_t flags)
Definition: esp.h:291
static enum net_sock_type esp_socket_type(struct esp_socket *sock)
Definition: esp.h:378
static atomic_val_t esp_socket_flags_update(struct esp_socket *sock, atomic_val_t value, atomic_val_t mask)
Definition: esp.h:263
static bool esp_socket_connected(struct esp_socket *sock)
Definition: esp.h:358
#define MDM_RING_BUF_SIZE
Definition: esp.h:96
static atomic_val_t esp_socket_flags_set(struct esp_socket *sock, atomic_val_t flags)
Definition: esp.h:285
#define CONN_CMD_MAX_LEN
Definition: esp.h:79
struct esp_data esp_driver_data
Definition: esp.c:68
void esp_close_work(struct k_work *work)
Definition: esp_offload.c:505
static void esp_flags_clear(struct esp_data *dev, uint8_t flags)
Definition: esp.h:368
static struct esp_socket * esp_socket_ref_from_link_id(struct esp_data *data, uint8_t link_id)
Definition: esp.h:253
#define MDM_RECV_BUF_SIZE
Definition: esp.h:98
esp_socket_flags
Definition: esp.h:136
@ ESP_SOCK_WORKQ_STOPPED
Definition: esp.h:141
@ ESP_SOCK_CLOSE_PENDING
Definition: esp.h:140
@ ESP_SOCK_CONNECTING
Definition: esp.h:138
@ ESP_SOCK_CONNECTED
Definition: esp.h:139
@ ESP_SOCK_IN_USE
Definition: esp.h:137
static int esp_socket_work_submit(struct esp_socket *sock, struct k_work *work)
Definition: esp.h:327
void esp_socket_init(struct esp_data *data)
Definition: esp_socket.c:80
void esp_socket_close(struct esp_socket *sock)
Definition: esp_socket.c:184
#define K_FOREVER
Generate infinite timeout delay.
Definition: kernel.h:1186
#define k_fifo_put(fifo, data)
Add an element to a FIFO queue.
Definition: kernel.h:2225
net_sock_type
Definition: net_ip.h:84
net_ip_protocol
Definition: net_ip.h:62
int k_mutex_unlock(struct k_mutex *mutex)
Unlock a mutex.
int k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout)
Lock a mutex.
void(* net_context_recv_cb_t)(struct net_context *context, struct net_pkt *pkt, union net_ip_header *ip_hdr, union net_proto_header *proto_hdr, int status, void *user_data)
Network data receive callback.
Definition: net_context.h:93
static enum net_sock_type net_context_get_type(struct net_context *context)
Get context type for this network context.
Definition: net_context.h:510
static uint16_t net_context_get_ip_proto(struct net_context *context)
Get context IP protocol for this network context.
Definition: net_context.h:601
void(* net_context_connect_cb_t)(struct net_context *context, int status, void *user_data)
Connection callback.
Definition: net_context.h:161
#define BIT(n)
Unsigned integer with bit position n set (signed in assembly language).
Definition: util_macro.h:44
#define ARRAY_SIZE(array)
Number of elements in the given array.
Definition: util.h:92
#define CONTAINER_OF(ptr, type, field)
Get a pointer to a container structure from an element.
Definition: util.h:131
#define EBUSY
Definition: errno.h:55
int k_work_submit_to_queue(struct k_work_q *queue, struct k_work *work)
Submit a work item to a queue.
flags
Definition: http_parser.h:131
static ZTEST_BMEM volatile int ret
Definition: k_float_disable.c:28
Network context definitions.
Public API for network interface.
IPv6 and IPv4 definitions.
Network packet buffer descriptor API.
static struct k_work work[2]
Definition: main.c:16
__UINT8_TYPE__ uint8_t
Definition: stdint.h:58
Definition: esp.h:192
struct net_if * net_iface
Definition: esp.h:193
struct k_sem sem_response
Definition: esp.h:235
struct esp_socket sockets[5]
Definition: esp.h:219
struct esp_socket * rx_sock
Definition: esp.h:220
scan_result_cb_t scan_cb
Definition: esp.h:231
struct k_work_q workq
Definition: esp.h:223
struct modem_context mctx
Definition: esp.h:208
struct modem_cmd_handler_data cmd_handler_data
Definition: esp.h:215
uint8_t mode
Definition: esp.h:196
struct in_addr nm
Definition: esp.h:203
uint8_t mac_addr[6]
Definition: esp.h:204
uint8_t cmd_match_buf[CONFIG_WIFI_ESP_AT_MDM_RX_BUF_SIZE]
Definition: esp.h:216
struct in_addr gw
Definition: esp.h:202
char conn_cmd[(sizeof("AT+"_CWJAP"=\"\",\"\"")+WIFI_SSID_MAX_LEN+WIFI_PSK_MAX_LEN)]
Definition: esp.h:198
struct k_work mode_switch_work
Definition: esp.h:228
struct k_work_delayable ip_addr_work
Definition: esp.h:225
struct k_work init_work
Definition: esp.h:224
struct k_work connect_work
Definition: esp.h:227
struct modem_iface_uart_data iface_data
Definition: esp.h:211
struct k_sem sem_if_ready
Definition: esp.h:236
struct k_work dns_work
Definition: esp.h:229
struct sockaddr_in dns_addresses[0]
Definition: esp.h:205
uint8_t flags
Definition: esp.h:195
struct k_work scan_work
Definition: esp.h:226
struct in_addr ip
Definition: esp.h:201
struct k_sem sem_tx_ready
Definition: esp.h:234
uint8_t iface_rb_buf[CONFIG_WIFI_ESP_AT_MDM_RING_BUF_SIZE]
Definition: esp.h:212
Definition: esp.h:144
struct k_work recvdata_work
Definition: esp.h:167
atomic_t flags
Definition: esp.h:151
void * conn_user_data
Definition: esp.h:180
struct k_sem sem_data_ready
Definition: esp.h:159
net_context_connect_cb_t connect_cb
Definition: esp.h:176
struct net_context * context
Definition: esp.h:175
uint8_t idx
Definition: esp.h:149
void * recv_user_data
Definition: esp.h:181
struct k_mutex lock
Definition: esp.h:146
atomic_t refcount
Definition: esp.h:147
struct k_sem sem_free
Definition: esp.h:162
uint8_t link_id
Definition: esp.h:150
struct k_fifo tx_fifo
Definition: esp.h:172
struct k_work send_work
Definition: esp.h:168
net_context_recv_cb_t recv_cb
Definition: esp.h:177
struct k_work close_work
Definition: esp.h:169
struct sockaddr dst
Definition: esp.h:154
struct k_work connect_work
Definition: esp.h:166
Definition: net_ip.h:148
Definition: kernel.h:2153
Definition: kernel.h:2680
Kernel timeout type.
Definition: sys_clock.h:65
A structure used to submit work after a delay.
Definition: kernel.h:3651
A structure used to hold work until it can be processed.
Definition: kernel.h:3770
A structure used to submit work.
Definition: kernel.h:3623
Network buffer representation.
Definition: buf.h:919
Definition: net_context.h:201
Network Interface structure.
Definition: net_if.h:468
Network packet.
Definition: net_pkt.h:62
Definition: net_ip.h:184
Definition: net_ip.h:335
static fdata_t data[2]
Definition: test_fifo_contexts.c:15
WiFi L2 stack public header.
void(* scan_result_cb_t)(struct net_if *iface, int status, struct wifi_scan_result *entry)
Definition: wifi_mgmt.h:113