So far received packets were parsed (at AT command level) and allocated
in [esp_rx] thread. Then they were submitted to [esp_workq] thread for
processing (calling application callback).
This flow results in following deadlock when esp_workq thread waits on
response to some AT command:
- [esp_rx] waits on allocation of new RX packet
- [esp_workq] waits for [esp_rx] to process response to AT command
that was just sent
- blocked [esp_workq] prevents processing and deallocating RX packets
- [esp_rx] times out on allocation and closes socket
Process RX packets directly from [esp_rx] thread to prevent above
deadlock.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
ESP fetches DNS servers from local network by using DHCP. There is an AT
command to get those DNS addresses. Use that to provide DNS addresses
for Zephyr's DNS resolver.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Socket can be closed either by Zephyr or by peer. In the former case ESP
WiFi chip still notfies about closed socket, which currently results in
printing warning log:
<wrn> wifi_esp: Link X already closed
Change level of this log from warning to debug, so that driver users are
not concerned about situation that is a normal behaviour.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
There was a regression when implementing automatic AT+CWMODE{,_CUR}
handling based on driver needs. ESP AT 1.7 firmware does not support
AT+CWMODE_CUR=0, which means that radio needs to be either in STA, AP or
STA+AP mode (no NONE state available).
Fix ESP AT 1.7 compatibility by keeping radio in STA mode whenever it is
not used.
Move also first AT+CWMODE_CUR invocation before AT+CWDHCP_CUR, so that
the latter executes successfully with ESP AT 1.7.
Fixes: 03ce61004b ("drivers: wifi: esp: control CWMODE depending on
current needs")
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Added ap_enable and ap_disable api. The driver will open create an
access point with DHCP Server ip 192.168.1.1 and no security.
Added a small fix for the AF_INET issue.
Added parent and remote to accept routine context.
Added put implementation.
Signed-off-by: Nicolai Glud <nicolai.glud@prevas.dk>
net_context contains both net_sock_type and net_ip_protocol, which are
static during the lifetime of net_context. net_context has basically the
ownership of esp_socket, so we can be sure 'type' and 'ip_proto' are
always accessible through net_context API.
Remove 'type' and 'ip_proto' members from 'esp_socket' structure, as
those are already accessible by net_context API.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Change type of esp_socket->flags from uint8_t to atomic_t, so that read
and write access to those flags is done in atomic (thread-safe) manner.
Introduce esp_socket_ref() and esp_socket_unref() functions, which
operate on atomic refcount variable. esp_socket_ref() role is to
increase refcount if it was already non-zero. If it was zero then NULL
is returned, which means that socket is not used by net_context at the
moment.
Role of refcount:
* socket instance is assured to be between net_offload->get() and
net_offload->put() when refcount > 0,
* makes sure that socket instance can be used (its members can be
dereferenced) when refcount > 0,
* 'context' member is always valid and its members can be dereferenced
when refcount > 0.
esp_socket_get() gets unused socket, as previously. Additionally it sets
refcount to 1 at the end of call, which basically means that from that
point such socket can be referenced by other parts of the driver. Each
esp_socket_get() call should be followed by esp_socket_unref() and
esp_socket_put() to properly invalidate socket and prevent other parts
of driver from using it.
Add ESP_SOCK_WORKQ_STOPPED flag, which is now used to prevent scheduling
more work into driver workqueue. This flag is set in net_offload->put()
callback, so that no more socket work (such as processing RX/TX packets
or closing socket because of errors) is submitted after that.
Introduce mutex lock, which has following role:
* protects dst, connect_cb + conn_user_data, recv_cb + recv_user_data,
* assures that checking ESP_SOCK_WORKQ_STOPPED flag and actually
submitting (or not if net_offload->put was already called) new socket
work to workqueue is done in atomic way.
As there is a mechanism to prevent submitting new work items to
workqueue when net_offload->put() has been executed, then there is no
need to explicitly call esp_socket_ref() in esp_workq thread. This is
because one reference is being held by net_context (after calling
net_context->get()). This is why all the esp_socket_in_use() were simply
dropped. Code running from esp_rx thread on the other hand always uses
esp_socket_ref_from_link_id() helper function (which is backed by
esp_socket_ref()), so that it replaces previous esp_socket_in_use()
calls and additionally makes sure that socket stays valid ("in use")
until esp_socket_unref() is called.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
So far a dedicated FIFO was used for all RX packets, which was consumed
in single submitted work. This work was also responsible for closing
socket and notifying uppper network layers if some errors occurred
previously or socket was simply closed by peer. There is however a
potential race condition in scenario described below:
esp_rx thread | esp_workq thread
--------------------------|-----------------------------
| ---- esp_recv_work ----
| handle RX packets from FIFO
|
---- on_cmd_ipd ---- |
put new RX packet to FIFO |
---- on_cmd_ipd ---- |
|
---- on_cmd_closed ---- |
mark socket as closed |
---- on_cmd_closed ---- |
|
| handle close
| ---- esp_recv_work ----
In this case we assume that esp_workq was preempted just after
processing all RX packets from FIFO and before checking if socket was
closed. In such scenario RX packet put to FIFO just before doing close
is going to be unhandled, so application layer will miss part of the
data.
Change the way RX packets are scheduled to workqueue, by using the
already available net_pkt->work objects (used for example in native TCP
stack). Create a separate work for closing connection. As a result all
RX packets and close handlers are on the same queue and there is no risk
of handling close events before handling all previously received data.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
There might be some scheduled work related to socket currently requested
to be destroyed/closed. Schedule a dummy work to make sure all
previously running work items in workqueue are finished.
When talking about TX packets, this makes sure that all previously
scheduled data is actually sent (flushed) before closing socket.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
It is enough to initialize work structures once during driver init,
because work handlers do not change during driver lifetime.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Currently there are two code paths when sending packets:
asynchronous (using workqueue) when zero timeout was specified and
synchronous in other cases. This doesn't seem to be justified, so
convert code to always schedule packet sending using workqueue.
Each net_pkt has an embedded work item, so use it instead of esp socket
specific work that was shared across all sent packets. This gives a
possibility to schedule multiple packets for sending.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Callback and user data are saved in net_context structure. Those members
are used by native networking stack (net_if), so simply follow the same
pattern.
First of all this allows to reduce runtime information for driver socket
instance. Second and most important benefit is that it allows to move
send handling entirely to workqueue thread.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
ESP chip send number of available RX data using
+IPD=<sock>,<avail_bytes> command. This exact number (truncated to MRU)
was used to read data with AT+CIPRECVDATA=<sock>,<num_of_bytes>.
Use always MRU when sending AT+CIPRECVDATA=<sock>,<mru> request. When
there are less bytes available, then +CIPRECVDATA will just return less
bytes, which is fine for the driver.
There are two advantages to this new behavior:
* there is no need to follow how many bytes were notified by +IPD
message, thus reducing implementation size,
* when data is constantly received by ESP chip, then the last number of
bytes notified by +IPD is no longer up-to-date when sending a
AT+CIPRECVDATA; always requesting MRU number of bytes allows to
always receive maximum currently available number of bytes buffered
by ESP chip.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Dump of communication between ESP chip and Zephyr shows that
+IPD:<sock>,<bytes_avail> is always received after +CIPRECVDATA. This
means that we don't need to update sock->bytes_avail in esp_workq
thread. Additionally there is no need to schedule next AT+CIPRECVDATA
request, as that will be done by +IPD handler anyway.
Relying on +IPD to be received after each +CIPRECVDATA (as long as there
is some more data to be received) allows to simplify operations on
sock->bytes_avail. From now on only esp_rx thread will update its value
and schedule AT+CIPRECVDATA in esp_workq thread. Then in
sock->bytes_avail will be treated as "readonly" in esp_workq
thread. This allows to prevent race condition when both esp_rx and
esp_workq threads could potentially update value of sock->bytes_avail
value at the same time.
<sock>,CLOSED message is received always after retrieving all data from
ESP chip (using AT+CIPRECVDATA), so there is no need to check whether
there are more bytes to be received before marking socket as closed in
Zephyr driver.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Deduplicate final part of RX data processing for two supported cases:
passive (+CIPRECVDATA) and non-passive (+IPD). Move implementation to
esp_socket module, as this is strictly related to socket.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Split +IPD message handling into smaller logical functions, so it is
much easier to follow code and further improve it. Make sure to do as
much parsing work as possible, before accessing esp_socket object. This
will allow to introduce thread-safety locking just in the critical parts
in subsequent commits.
Prefer early return from function over goto to return instruction,
whenever cleanup code is not needed.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Current on_cmd_ciprecvdata handler is a bit overwhelming to follow.
Add a cmd_ciprecvdata_parse() helper, which is responsible only for
parsing received metadata (message offset and length), leaving socket
instance untouched.
Consume received payload later on, just after verifying that socket is
in valid state.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
After a synchronous (timeout > 0) connection attempt was made, it was
being checked if there is some packet to be sent. If positive, then a
send work was queued.
This behavior makes little sense, as TCP connection is not even
considered established at this point (from net_context perspective) if
function has not returned yet. Additionally it differs from
asynchronous (timeout == 0) connection attempt. In case of UDP (and
calling esp_connect() from esp_sendto()) sock->tx_pkt is assured to be
NULL. Drop this piece of code as it doesn't seem to be justified.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2 (out of 3) components used CONFIG_WIFI_LOG_LEVEL, while the last one
didn't specify explicit log level. Always use CONFIG_WIFI_LOG_LEVEL in
all components.
While at it switch to LOG_MODULE_REGISTER(<module>, <log_level>), which
is a more compact way to define log level.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Calculate size based on the real message, instead of assuming some
arbitrary size. This consumes slightly less stack space, but more
importantly gives an idea what has been taken into account when
calculating the size.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
+IPD,<sock>,<bytes_avail> command in passive mode notifies about ESP
internal buffer usage level. Hence value of <bytes_avail> can exceed
4 digit value, which currently results in failure.
+IPD message is used in driver only for scheduling AT+CIPRECVDATA
command and actual value of <bytes_avail> doesn't really
matter. Increase maximum supported value that can be received from
9999 (maximum 4 digits) to 4294967295, which is maximum value of 32-bit
unsigned integer.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Set NET_CONTEXT_CONNECTED when stream socket got connected. This fixes
TCP connection when using eswifi WiFi driver, which got broken after
sockets layer started to validate net_context connection state before
allowing to receive any data.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Set NET_CONTEXT_CONNECTED when stream socket got connected. This fixes
TCP connection when using winc1500 WiFi driver, which got broken after
sockets layer started to validate net_context connection state before
allowing to receive any data.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Set NET_CONTEXT_CONNECTED when stream socket got connected. This fixes
TCP connection when using ESP WiFi driver, which got broken after
sockets layer started to validate net_context connection state before
allowing to receive any data.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
So far ESP chip was configured directly into STA mode. This works fine,
but consumes lots of power because of enabled WiFi radio, even when it
is not actively used.
Enter NONE mode during initialization, so WiFi radio will be
disabled. Switch between NONE, STA, AP and STA+AP modes depending on
what driver is currently doing (e.g. enable STA only when scanning,
connecting and being connected to AP).
AT+CWAUTOCONN=0 command fails when in NONE mode, so workaround that by
entering temporarily into STA and then switching back to NONE.
Add also a warning log when switching mode was not successful, to ease
debugging possible issues.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
AT+CWMODE command controls in which mode (NONE, STA, AP, STA+AP) ESP
chip is operating. Add helper macros to replace usage of magic
numbers (0-3), hence improve readability. Add also a esp_mode_switch()
helper function, which allows to conveniently switch to chosen mode.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Change internal API operating on ESP driver flags to support multiple
bitwise ORed flags at once. This allows to improve resulting code when
multiple flags are read or modified at once.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
All except one invocations of modem_cmd_send() pass the same interface,
command handler and semaphore. Create a helper function in order to make
invocations slightly more readable.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Both 'cb' and 'user_data' parameters for send/sendto were saved as
'send_cb' and 'send_user_data' members in socket information. None of
them are actually used, so drop them.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Constifying global data allows to save lots of RAM. Defining data inside
function as 'static const' allows on the other hand to save stack usage
and reduced code size (because data doesn't have to be copied on stack
in runtime).
This improvement allows to save 640 bytes of RAM and 64 bytes of ROM
when compiled on ARM.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Configure hostname by issuing AT+CWHOSTNAME="<hostname>" command. Do it
just after setting link address, which is used to generate hostname
postfix when CONFIG_NET_HOSTNAME_UNIQUE=y.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
- Add ESP DHCP Support
- Add ESP Static IP Support including
KConfig entries for configuring IP,Gateway and netMask
Signed-off-by: Mohamed ElShahawi <ExtremeGTX@hotmail.com>
So far there was 100ms timeout on allocation of RX net_pkt. This is too
little for cases when lots of data are incoming on pretty
fast (e.g. 1Mbps) UART interface and application layer does not consume
received network packets fast enough. Up to now in such cases all
incoming data was processed from UART and there was no data loss when
utilizing hardware flow control. However there was high chance that data
processed from UART could not be passed further to network stack,
because of the 100ms net_pkt allocation timeout. This happens for
example when low priority application does not have enough time to run.
Increase default RX net_pkt allocation timeout from 100ms to 5s, so
there is much more time to process network packets. Such timeout should
not harm, because only a dedicated RX thread will be suspended for that
time, resulting in suspending UART traffic if hardware flow control is
supported.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
There is now a hardcoded 100ms timeout on allocating new net_pkt for
received data. Move that configuration to Kconfig, so that value can be
tuned according to application needs.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
There is no reason to keep active stream socket when there was some data
loss. Mark such socket for closing and close it when all (so far)
received packets have been processed.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Add uart bus interface to extended esWIFI driver. This enables all
Inventek modules with IWIN AT Commands firmware.
Signed-off-by: Gerson Fernando Budke <gerson.budke@atl-electronics.com>
The WIFI_ESWIFI_NAME config would be uselful when there is no device
tree alternative. The esWIFI driver already is on device tree and the
label property exists. This remove WIFI_ESWIFI_NAME Kconfig variable
and switch to device tree equivalent.
Signed-off-by: Gerson Fernando Budke <gerson.budke@atl-electronics.com>
Remove global access to structure eswifi_spi_data variable. Instead,
add a method to pass access to that structure. This allows better
control to the data bus variable.
Signed-off-by: Gerson Fernando Budke <gerson.budke@atl-electronics.com>
All net_bufs allocated to modem_cmd_handler's data->rx_buf are consumed
synchronously in esp.c in the same thread. This means that allocating
them with timeout makes no sense, because timeout will *always* be hit
when there are no more buffers in net_buf_pool.
Get rid of the unnecessary timeout, as it doesn't help and just slows
down processing of incoming data, increasing possibility of data
overrun.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
So far a dedicated buffer was used for data read from modem
interface. New net_bufs were allocated and filled later, which means
that data was lost when no more net_bufs were available in the pool.
Prevent data loss by allocating net_buf before attempting any read on
modem interface. Process incoming data in a loop as long as reading from
interface results in new data. Also remove dedicated buffer
(data->read_buf) and directly fill net_buf content instead. As a side
effect there are less memory copy operations and RAM usage is reduced.
Pre-allocated net_buf is now always appended to data->rx_buf. When there
was no (more) data read from interface to such net_buf, then this empty
net_buf will be on the end of data->rx_buf fragment list. Update
skipcrlf() and findcrlf() implementations to explicitly check for each
net_buf length, instead of blindly assuming them to have at least single
byte.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Listen func goes through a chain of calls to call winc1500_accept.
This is done to install the accept callback and should not block.
This fixes#28953 where winc1500 driver blocks on listen.
Signed-off-by: Nicolai Glud <nicolai.glud@prevas.dk>
Add power-gpios device-tree binding property to power on module before
communicating with it. This pin is called CHIP_PU in case of ESP32{,-S2}
and CHIP_EN in case of ESP8266. Dedicated reset pin is available only on
the latter, however Espressif recommends (in ESP8266 Hardware Design
Guidelines) to use CHIP_EN instead. Follow those recommendations and use
power-gpios to reset chip if that is provided over device-tree.
Configure power-gpios and reset-gpios as inactive by default, so that
chip becomes ready after executing esp_reset() function, either if one
or both are provided over device-tree.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Most DT bindings use reset-gpios name when there is a pin to reset whole
chip. Rename wifi-reset-gpios to reset-gpios to be more consistent
between various drivers. Additionally this prevents confusion, as
somebody might think that this pin resets only WiFi, which is not true.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
If HW flow control is enabled, then modem_context framework won't drain
UART FIFO blindly, but will stop when there is no more space in RX
ring_buf. This prevents data loss by "pausing" incoming data on hardware
level.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
This API allows to drop use of preallocated isr_buf. Most importantly as
a result RAM usage is reduced for each driver utilizing modem_context
framework. Additionally there is less copying done in ISR context, as
data is direcly read from UART FIFO to ring_buf.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Allow to reconfigure UART baudrate on ESP and on host MCU, so a
non-default baudrate can be used for communication. This option helps
for example to increase network bandwidth without touching ESP chip
firmware.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>