8000 Nrf9160 socket support by glennrub · Pull Request #6236 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

Nrf9160 socket support #6236

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

glennrub
Copy link
Contributor
@glennrub glennrub commented Jul 9, 2020

Adding nrf9160 sockets support by using the bsdlib provided by Nordic Semiconductor. This enables micropython nrf9160 port with GNSS, AT-commands, IPv4, IPv6, UDP, TCP, DTLS1v2, TLS1v2, RAW socket (AF_PACKET), PDN/APN, getaddrinfo() and getaddrinfo() on specified PDN/APN, on-chip Modem DFU.

Samples provided for HTTP and GNSS.

Known limitations which should be handled later:

  • Secure credentials interface in order to establish TLS/DTLS connections. Can be performed manually through AT (AT%CMNG) commands at the moment.
  • AGPS.
  • Poll. Want to see if extmod/moduselect can be used. I have a version of moduselect.c that works, but it is pretty much 99% duplicate code of other moduselect's. Setting sockets in non-block mode is still possible.
  • Network mode() switch interface to select LTE, NB-IOT, GPS and combo of these.
  • Network init() and unit() methods. To toggle the library on and off in case of sleep or during on-chip modem DFU upgrade.

@glennrub glennrub force-pushed the nrf9160_sockets_cleaned_july20 branch 2 times, most recently from 8feee9a to 7bb48ad Compare July 16, 2020 10:47
@glennrub
Copy link
Contributor Author

Rebased to replace RTCounter fix and to get travis build of pca10090.

glennrub added 3 commits July 16, 2020 13:27
Add nrfxlib submodule which contains libraries for
nrf9160 BSD Sockets. Pointing to BSD library version 0.7.5.

Source: https://github.com/nrfconnect/sdk-nrfxlib.git
Adding modules for network and socket with needed
integration drivers.

nrf9160 targets can enable sockets and network module with
its accompanied modnwlte by setting the three
configurations in mpconfigboard.h:

- MICROPY_PY_USOCKET
- MICROPY_PY_NETWORK
- MICROPY_PY_LTE_SOCKET

The modnwlte NIC will be available as NRF91 in the
network module.

HTTP sample provided in examples/nrf9160_http.py.
GNSS sample provided in examples/nrf9160_gps.py.
Enable MICROPY_PY_USOCKET, MICROPY_PY_NETWORK and
MICROPY_PY_LTE_SOCKET for all nrf9160 boards.
@glennrub glennrub force-pushed the nrf9160_sockets_cleaned_july20 branch from 7bb48ad to 880760c Compare July 16, 2020 11:33
@dpgeorge
Copy link
Member

I think we had a conversion about this point before, but it would be preferred to reuse all the existing network code/framework (eg extmod/modlwip.c) and hook in directly to the nrf91 at the level of raw ethernet packets, rather than hooking in at the level of sockets (ie we want to run our own TCP/IP stack rather than the one provided by the nrf91 SDK). Did you have any further thoughts about that?

If the socket/network code here is largely copied from stm32 (or elsewhere) then it'd be good to factor that out and share it rather than duplicating it.

Also, we should start enabling uncrustify formatting on new nrf code so it doesn't need to be reformatted later on.

import network
import socket

n = network.NRF91()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should be network.Cellular() so it can be consistent with other ports that may eventually provide such a network class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion! I never came up with a good name for it.


n = network.NRF91()

at = socket.socket(socket.AF_LTE, socket.SOCK_DGRAM, socket.PROTO_AT)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it the right pattern to have a socket for the AT connection/commands? Wouldn't it be simpler to have the method on the n cellular network object, eg n.at_send(...) and n.at_recv(...)? Again I'm thinking about other ports that may have cellular, even as an external component.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is the pattern to create a AT-socket. Directly dispatched to the BSD-library. I did actually add a convenience function similar to what you suggest, modnwlte.c:828.

It's a one shot though, which only returns the response, then closes the at-socket again. But it should not be a problem to keep this open for a longer time in case you also want to do subscriptions. One reason for doing a socket instead of a convenience function like this is that you might want to also add it to a socket poll() mask.


gps = socket.socket(socket.AF_LOCAL, socket.SOCK_DGRAM, socket.PROTO_GNSS)
gps.setsockopt(socket.SOL_GNSS, socket.SO_GNSS_FIX_RETRY, bytearray([0, 0]))
gps.setsockopt(socket.SOL_GNSS, socket.SO_GNSS_FIX_INTERVAL, bytearray([1, 0]))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can GPS be a class rather than a special kind of socket?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, GPS class is a good idea. Do we have anything on this from before?

It is also a binary format which also provides much more information. I used NMEA variant here, to show something well known.

@glennrub
Copy link
Contributor Author

I think we had a conversion about this point before, but it would be preferred to reuse all the existing network code/framework (eg extmod/modlwip.c) and hook in directly to the nrf91 at the level of raw ethernet packets, rather than hooking in at the level of sockets (ie we want to run our own TCP/IP stack rather than the one provided by the nrf91 SDK). Did you have any further thoughts about that?

Yes, indeed. And i guess at the time there were no RAW socket options available. However, there are now (4 sockets with RAW support. Not that i have played with them to much, but they exist). I'll have to dig a bit into this again and do a new feasibility study. I'm far from an expert on LWIP, but i'm thinking on some challenges i might have to look at:

  • Most imporant: Setting up an interface to only frame IP data, as i believe we do not have an ethernet MAC address available.
  • Interfaces that gets the IPv6 address later than the IPv4 address (AT-command subscription might be needed). In current PR, this must be handled by the user.
  • Binding a RAW socket to use a specific APN/PDN as transport.
  • gethostbyname using a specific APN/PDN context.
  • APN/PDN interfaces which can creates additional IPv4/IPv6 addresses.

Also, RAM usage for TLS/DTLS in micropython would be interesting to look at. To see how much RAM might be consumed for encrypted links and handshakes (bsdlib/modem already hosts a full IP stack and crypto engine and has budgeted RAM to support 3 simultaneous TLS/DTLS sessions, these will in case of only using RAW sockets be unused).
Splitting GNSS/IP/Modem DFU/PDN management, and AT commands might still require some kind of central point of coordination as unsolicited AT-command (AT socket) responses will tell about network activities to LWIP.

My thoughts:
I did actually look at it briefly earlier, but thought it was to much work when I already had something working. But that should not be used as an argument for not doing it the more correct way (sharing more code). I have some ideas in mind on how it might be possible, but i would need some time on it, specially on the LWIP part.

If the socket/network code here is largely copied from stm32 (or elsewhere) then it'd be good to factor that out and share it rather than duplicating it.

Probably the modnwlte.c is the only really new module here as it acts as the adoption layer towards the BSD library and adds some convenience functions. The network and socket modules are pretty much the same, except an extension to gethostbyname to also pass in an APN name to tell which "interface" to do the lookup. I did some work earlier trying to factor out socket and network (#4096). This should be something that could be done in any case, i'll take a new look at it.

Also, we should start enabling uncrustify formatting on new nrf code so it doesn't need to be reformatted later on.

Yeah, that would make sense!

All in all, I'll do a feasibility study/proof-of-concept whether i believe it's feasible use the RAW sockets from the BSD-library in practice. The socket/network sharing, I consider being a low hanging fruit that can be done in parallel in any case.

@ehughes
Copy link
ehughes commented Sep 15, 2020

@dpgeorge @glennrub

I really like the idea of uPython the NRF9160. The default zephyr environment is pretty complicated.

One thing that will be tough with most cellular solutions is that you really don't get layer 2 network access. Generally speaking, the AT commands to the modem are at a socket level. It would be nice to have a clean interface like the other wifi/ethernet solutions but it may be really ugly on the cellular side. To pass 4G/LTE 3GPPP certs, the modem firmware has to isolate the potential for bad behavior so they tend to limit access to the network to higher level sockets only.

Let me know if there is any way I could help. I would love to see uPython on this part as it could simplify many applications that just need to blink out data.

@tve
Copy link
Contributor
tve commented Dec 4, 2020

Very interesting PR! I'm looking into building something with the 9160... Shoehorning all the cellular stuff into the existing LwIP sounds like quite an undertaking. Seems to me like a net loss, to be honest.

@dpgeorge
Copy link
Member

I'll close this due to inactivity.

Also, I think it's clear that using Zephyr is the better option for newer nRF parts because that's where Nordic seems to be spending its development efforts now. So if anyone is interested to look at the nRF9160 then I suggest try using the zephyr port for that.

@dpgeorge dpgeorge closed this Nov 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0