Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Ninaw10 driver fixes #8138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

iabdalkader
Copy link
Contributor

@iabdalkader iabdalkader commented Jan 4, 2022

Following a discussion in #7668 a few small fixes and improvements:

  • Allow recv() and recvfrom() to be used interchangeably on TCP/UDP sockets.
  • Return -1 on timeout error from recv(), recvfrom(), send() and sendto().
  • Make NIC state persistent.
  • Disable active connections before connecting/reconnecting.
  • Fix manual DNS bug.
  • Set secondary DNS server.

@iabdalkader iabdalkader force-pushed the ninaw10_driver_fixes branch from c179ff3 to 27951a0 Compare January 4, 2022 19:39
@robert-hh
Copy link
Contributor

Hi @iabdalkader Thank you for making the changes. I can confirm, that

  • recv() and recvfrom() can be used interchangeably on TCP/UDP sockets.
  • the NIC state is reported as active and connected when re-instantiating wlan if the device has been connected once.

What still is strange from our discussion:

  • settimeout() on UDP sockets still fails.
  • getaddrinfo() with a domain name still fails, if the connection has not been made in the same script.

@iabdalkader
Copy link
Contributor Author

iabdalkader commented Jan 4, 2022

settimeout() on UDP sockets still fails.

For some reason TCP/UDP sockets must be connected/bound first before setting a timeout on the socket. That's an issue in modusocket.c here: https://github.com/micropython/micropython/blob/master/extmod/modusocket.c#L320 I'm not sure why it's like that. Can you comment on this @dpgeorge ?

getaddrinfo() with a domain name still fails

How to reproduce this ?

@robert-hh
Copy link
Contributor

How to reproduce this ?

a) run a script from REPL which connects the device to a AP.
b) run the statements from REPL:

import socket
socket.getaddrinfo("pool.ntp.org", 123)

At my build of the nano-connect, that raises:

Traceback (most recent call last):
File "", line 1, in
OSError: -1

@iabdalkader
Copy link
Contributor Author

It doesn't fail.

MPY: soft reboot
MicroPython v1.17-286-g4048fdf15-dirty on 2022-01-04; Arduino Nano RP2040 Connect with RP2040
Type "help()" for more information.
>>> 
paste mode; Ctrl-C to cancel, Ctrl-D to finish
=== import network
=== SSID='xxx' # Network SSID
=== KEY='xxxx'  # Network key
=== wlan = network.WLAN(network.STA_IF)
=== wlan.active(True)
=== wlan.connect(SSID, KEY)
=== 
=== 
>>> import socket
>>> socket.getaddrinfo("pool.ntp.org", 123)
[(2, 1, 0, '', ('193.203.3.170', 123))]

@robert-hh
Copy link
Contributor

Try putting the AP connection in a separate file (not pasting from REPL) and import that file. Then try getaddrinfo() from REPL.

@iabdalkader
Copy link
Contributor Author

I did, I put the connect code in _boot.py and did a soft-reboot still working.

MPY: soft reboot
MicroPython v1.17-287-g27951a02a-dirty on 2022-01-04; Arduino Nano RP2040 Connect with RP2040
Type "help()" for more information.
>>> wlan.active()
True
>>> import socket
>>> socket.getaddrinfo("pool.ntp.org", 123)
[(2, 1, 0, '', ('162.159.200.1', 123))]
>>> 

@robert-hh
Copy link
Contributor

What id you to that into a separate script, which you manuallly importd from REPL or import from main.py? I typically use such a script, which is called from main.py. e.g.

WIFI_DNS = "10.0.0.240"
GOOGLE_DNS = "8.8.8.8"
try:
    from my_config import *
except:
    WIFI_SSID = "<SSID>"
    WIFI_PASSWD = "<PWD>"
    WIFI_IP = "10.0.0.175"

import network
import time

wlan = network.WLAN(network.STA_IF) # create station interface
wlan.active(True)       # activate the interface
if not wlan.isconnected():      # check if the station is connected to an AP
    wlan.ifconfig((WIFI_IP, "255.255.255.0", WIFI_DNS, GOOGLE_DNS))
    wlan.connect(WIFI_SSID, WIFI_PASSWD) # connect to an AP

    for _ in range(10):
        if wlan.isconnected():      # check if the station is connected to an AP
            break
        print('.', end='')
        time.sleep(1)
    else:
        print(" Connect attempt timed out\n")

print('\nnetwork config:', wlan.ifconfig())

@robert-hh
Copy link
Contributor

robert-hh commented Jan 4, 2022

The difference:
If I omit the wlan.ifconfig() before wlan.connect(), then it works.

edit: using wlan.ifconfig() after the wlan.connect() also causes the fail.

@iabdalkader
Copy link
Contributor Author

edit: using wlan.ifconfig() after the wlan.connect() also causes the fail.

Okay so the actual issue is in ifconfig not where WLAN is called, I'll look into it, it could be a firmware bug.

@iabdalkader
Copy link
Contributor Author

iabdalkader commented Jan 4, 2022

Confirmed it's a bug in the firmware, setting DNS breaks name resolution, I have an Arduino sketch that reproduces the issue if you want it. I can't fix this bug but I'll report it upstream.

* The wrong ACK is returned and checked.
* Send secondary DNS to google.
@iabdalkader
Copy link
Contributor Author

@robert-hh Found a bug in my code, which breaks DNS, it's fixed and a secondary DNS is set too.. See latest commit. There's still an issue with the firmware, but it does Not affect my driver.

@robert-hh
Copy link
Contributor

So you say that the issue with ifconfig() is still present. The code builds fine. Which changed behavior should I see?

@iabdalkader
Copy link
Contributor Author

So you say that the issue with ifconfig() is still present.

No I'm saying it's fixed.

@robert-hh
Copy link
Contributor

Confirmed. Somehow building did not work the first time. So I started over from scratch by pulling the PR again.

@dpgeorge
Copy link
Member

dpgeorge commented Jan 6, 2022

For some reason TCP/UDP sockets must be connected/bound first before setting a timeout on the socket.

That's because it doesn't have a NIC bound yet to the socket. If self->nic == MP_OBJ_NULL then self->nic_type is also NULL and there's no way to call self->nic_type->settimeout.

If there are multiple NICs (eg WiFi and ETH) then how can it set the timeout before knowing which NIC to bind to? The NIC to bind to is determined when the IP address of the destination is known.

This is the main drawback of using this extmod/modusocket.c approach, compared to the lwIP-on-host approach (used eg by PYBD, esp32, esp8266).

Possible solutions:

  1. in most cases there is only one NIC anyway, so if a NIC is needed and not yet bound (eg on first call to settimeout) then just select and bind the socket to the first available NIC
  2. require that the timeout be stored in mod_network_socket_obj_t for all drivers that use this scheme, and then update that value when settimeout is called

Option 1 is easier. If you work on this, please do it separate to this PR.

@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Jan 6, 2022
@iabdalkader
Copy link
Contributor Author

How about if NIC is NULL store the timeout in socket object ?

If you work on this, please do it separate to this PR.

Understood, this PR is done anyway.

@dpgeorge
Copy link
Member

dpgeorge commented Jan 6, 2022

How about if NIC is NULL store the timeout in socket object ?

That would mean that when the NIC is created/bound it would need to configure the socket with the timeout value stored in the socket object, right? As well as implementing its own settimeout slot. That sounds ok.

@iabdalkader
Copy link
Contributor Author

iabdalkader commented Jan 6, 2022

That would mean that when the NIC is created/bound it would need to configure the socket with the timeout value stored in the socket object, right?

It's possible, in socket_select_nic() if the NIC is not bound check if timeout != 0 (timeout has been changed) call self->nic_type->settimeout(self, self->timeout), but this also implies that socket_settimeout() will Not fail if NIC==NULL.

@dpgeorge
Copy link
Member

dpgeorge commented Jan 6, 2022

It's possible, in socket_select_nic() if the NIC is not bound check if timeout != 0 (timeout has been changed) call self->nic_type->settimeout(self, self->timeout)

Yes that sounds like a good approach.

@dpgeorge
Copy link
Member

dpgeorge commented Jan 6, 2022

I didn't test these changes but they look good. Merged in 0f25e03 through 12f9f93

@dpgeorge dpgeorge closed this Jan 6, 2022
@iabdalkader iabdalkader deleted the ninaw10_driver_fixes branch January 6, 2022 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants