Skip to content
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

Add reusable modem modules and generic modem driver #56692

Merged

Conversation

bjarki-trackunit
Copy link
Collaborator

@bjarki-trackunit bjarki-trackunit commented Apr 10, 2023

Modem subsystem for Zephyr RTOS

Introduction

The modem subsystem adds Zephyr implementations of the widely used Linux programs: chat and pppd, and a CMUX module.

What issue will the modem subsystem solve?

Modems on Zephyr RTOS currently offer limited capabilities and features compared to the capabilities and features offered by the modems. The main limiting factor lies with the Zephyr Device Driver model, which is not flexible enough to support the extensive and ever expanding feature set of modems. Even if it could, making a generic API for modems would itself be an extensive task, which may never be realized.

How will the modem subsystem solve the issue?

The modem modules are simple and abstract, allowing users to either implement the entire modem driver in the application layer, or create an out-of-tree modem driver easily. This allows users to create their own tailored modem drivers, with potential out-of-tree device driver APIs. This strategy encourages collaborating on the complex, sharable parts of the drivers, the modem modules, while giving users full flexibility regarding business logic of their modem drivers, which is often proprietary.

The modem modules can also be used to create more general drivers for modems like the ublox-r4 and quectel-bg9x.

Isn't this already implemented in Zephyr?

Zephyr currently has a working device driver, gsm_ppp, which uses CMUX, PPP and a command handler. However, it is not built in a modular fashion. The objects used by the driver are tightly coupled together using public headers and Kconfigs, which makes them hard to test and reuse. The objects depend highly on Kconfigs to allocate lists of fixed lengths for objects and buffers to be allocated during runtime, which makes the configuration and use of said modules difficult. The objects referenced are:

  • PPP L2 network device and PPP frame wrapper (drivers/net/ppp.c)
  • gsm mux which sets up CMUX (drivers/console/gsm_mux.c)
  • uart mux which creates a list of virtual devices using UART API (drivers/console/uart_mux.c)

Potentially for these reasons, of these objects, only the ppp.c is currently tested. After reviewing the gsm_ppp driver and dependencies, it became clear creating a novel modular subsystem for the modems using the newest features of Zephyr, which additionally mimics the daemons available on Linux, was a better approach than changing the existing implementation.

This decision allows the gsm_ppp driver and its dependencies and the novel subsystem to persist in parallel.

Modular design?

The modem modules in the modem subsystem are loosely coupled using the modem_pipe structure and API. This is a simple bytes in/bytes out pipe with a callback when data is ready. Decoupling the modules using this interface makes testing the modules independently staight forward, using mocks which implement the modem_pipe API. It also allows for easily switching "backends", like (modem_pipe -> UART API) could be switched for (modem_pipe -> IPC) and using a CMUX DLCI channel could be switched for using the modem UART directly. At this time, backends for UART, using the ISR and Async APIs, and TTY, using POSIX, are currently implemented.

Performance comparison

The comparison uses the newly introduced sample net/cellular_modem which uses a cellular modem to perform a DNS lookup, followed by transmitting and receiving 64 packets, calculating the average time from sending to receiving a packet. Packets of size 256 and 1024 bytes where tested. The echo time is the total transmission time from send_to() to returning from recv().

Test results

|  Property               |  Existing solution  |  Modem modules
|  Flash                  |  98296 bytes        |  101204 bytes
|  RAM                    |  42552 bytes        |  30416 bytes
|  Echo 256 bytes         |  195 ms             |  160 ms
|  Echo 1024 bytes        |  503 ms             |  401 ms
|  Throughput 256 bytes   |  4914 bytes/s       |  7708 bytes/s
|  Throughput 1024 bytes  |  N/A                |  8709 bytes/s

Note that the existing solution is exceptionally unstable, consistently failing to send more than a few packets larger than 256 bytes for some reason...

Summary

The modem modules consume 12000 bytes (28.5%) less RAM, with nearly identical ROM usage, while presenting a 58% higher transmit throughput :)

@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 2 times, most recently from d48e159 to a8cc907 Compare April 20, 2023 18:14
@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 5 times, most recently from e5b699a to 9ab1a07 Compare May 19, 2023 10:36
@bjarki-trackunit bjarki-trackunit self-assigned this May 19, 2023
@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 3 times, most recently from 633d40c to 342731a Compare May 19, 2023 18:49
@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 6 times, most recently from 1f64f77 to 8d1b309 Compare May 29, 2023 21:01
@carlescufi
Copy link
Member

Architecture WG:

@bjarki-trackunit bjarki-trackunit marked this pull request as ready for review May 30, 2023 15:12
Copy link
Member

@rerickson1 rerickson1 left a comment

Choose a reason for hiding this comment

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

Adding a section to the docs and a sample using the basic driver would be good.

subsys/modem/backends/modem_backend_tty.c Outdated Show resolved Hide resolved
subsys/modem/modem_pipe.c Show resolved Hide resolved
@rerickson1 rerickson1 requested a review from ycsin May 30, 2023 16:54
@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 2 times, most recently from 76b60cc to 4c29f55 Compare August 19, 2023 16:10
@bjarki-trackunit bjarki-trackunit removed the DNM This PR should not be merged (Do Not Merge) label Aug 19, 2023
@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 3 times, most recently from fe9e4bd to 6045148 Compare August 20, 2023 18:25
Bjarki Arge Andreasen added 4 commits August 24, 2023 11:43
This PR adds the following modem modules to the subsys/modem
folder:

- chat: Light implementation of the Linux chat program, used to
        send and receive text based commands statically created
        scripts.

- cmux: Implementation of the CMUX protocol
- pipe: Thread-safe async data-in/data-out binding layer between
        modem  modules.

- ppp: Implementation of the PPP protocol, binding the Zephyr PPP
       L2 stack with the data-in/data-out pipe.

These modules use the abstract pipes to communicate between each
other. To bind them with the hardware, the following backends
are provided:

- TTY: modem pipe <-> POSIX TTY file
- UART: modem pipe <-> UART, async and ISR APIs supported

The backends are used to abstract away the physical layer, UART,
TTY, IPC, I2C, SPI etc, to a modem modules friendly pipe.

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
The tests test each module independently using the mock pipe,
which implements the modem_pipe API, making it compatible
with the modem modules.

The modem_ppp module is slightly different from the others
since it also interacts with the network stack. To acheive
this, a mock implementation of the PPP L2 net iface has
been implemented in the test suite for the modem_ppp.

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
The added cellular modem driver is a naive driver, which
shall serve as a template for implementing tailored
drivers for modems like the UBLOX-R4. It uses only
generic at commands, described in 3gpp, and protocols,
like CMUX and PPP.

A binding for the BG95 has been added, which replaces
the quectel,bg9x. This is neccesary since the BG95 does
not have a usable reset pin, the reset and powerkey are
internally connected to each other.

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
Add modem_cellular driver to build_all. Since the driver
is generic, supporting 4 different modems, it builds an
instance for all 4 as they exist in the devicetree.

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
@bjarki-trackunit bjarki-trackunit force-pushed the feature_add_modem_subsys branch 3 times, most recently from 494753d to b5d6138 Compare August 24, 2023 10:12
Bjarki Arge Andreasen added 2 commits August 24, 2023 12:31
This commit adds a sample application which demonstrates how
to use the new driver and modules. The sample uses power
management to turn on the modem, uses network management
to wait for L4 connected, then uses DNS to get the IP
of the server running the python script found in the
server folder, which echoes back data recevied to it.
A packet containing psudo random data is then sent to
the server, which the echoes it back. To validate the
capability of the driver to restart the modem, the
modem is restarted, and the packet is sent again.

The server is hosted by linode, and uses the domain
name test-endpoint.com

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
This commit adds the new modem modules subsystem to the
MAINTAINERS.yml file.

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
@bjarki-trackunit
Copy link
Collaborator Author

bjarki-trackunit commented Aug 24, 2023

Patch note:

Addressed all comments

All review comments have now been addressed :)

Added throughput test to cellular sample

The cellular_modem sample now includes the following features:

  • Power cycle modem
  • Use DNS lookup to find address of test-endpoint.com
  • Send UDP packet and await echo back from test-endpoint.com
  • NEW: Send multiple UDP packets as fast as possible to test-endpoint.com, and await response from test-endpoint.com indicating how many packets where received, and if their payload was correct (payload is pseudo random). Throughput is calculated and shown in bytes/s

End to end tests performed

With the cellular_modem sample able to validate stability and measure transmit throughput, performance tests could be performed. Performance tests where performed for the modem_cellular.c driver and gsm_ppp.c driver for comparison. The RAM and Flash usage was noted as well.

Test setup

A b_u585i_iot02a board was used with a Quectel BG95 modem to perform the tests. The cellular_modem sample was altered slightly when testing the gsm_ppp.c driver as it doesn't support PM, and must be controlled using gsm_ppp_start().

Test results

|  Property               |  gsm_ppp.c          |  modem_cellular.c
|  Flash                  |  98296 bytes        |  101204 bytes
|  RAM                    |  42552 bytes        |  30416 bytes
|  Echo 256 bytes         |  195 ms             |  160 ms
|  Echo 1024 bytes        |  503 ms             |  401 ms
|  Throughput 256 bytes   |  4914 bytes/s       |  7708 bytes/s
|  Throughput 1024 bytes  |  N/A                |  8709 bytes/s

The gsm_ppp.c driver consistently deadlocked after sending a few packets during the throughout test and echo test when the packet size was more than 256 bytes. For the echo test, we get the transmit time for each echo, so I used the average of the few packets that where successfully sent before deadlocking, this was not an option for the throughput test, hence why its N/A on the test results.

Conclusion

The modem subsystem, the new modem driver, and the associated sample, I believe are now in a merge-able state. The modem subsystem has wide unit test coverage, and has proven stable through performance testing. The new modem driver is in a usable state after quite a bit of help from @rerickson1. Performance testing shows that the new subsystem uses 28% less RAM, while providing a transmit throughout 58% higher than the existing solution using gsm_ppp.c provides, while also providing better stability.

Special thanks to @rerickson1 for helping with developing the modem_cellular.c driver, and @rlubos, @jukkar and @rerickson1 for your thorough reviews :)

Please re-review this PR at your convenience :)

Copy link
Member

@rerickson1 rerickson1 left a comment

Choose a reason for hiding this comment

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

Great work on this!

Copy link
Member

@jukkar jukkar left a comment

Choose a reason for hiding this comment

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

LGTM. One thing to think about after this is merged, is how to prepare the deprecation of the older modem files / drivers. We do not want to have multiple implementations of the same thing for too long.

@carlescufi carlescufi merged commit d4d31a3 into zephyrproject-rtos:main Aug 30, 2023
22 checks passed
@WilliamGFish
Copy link
Collaborator

WilliamGFish commented Sep 14, 2023

LGTM. One thing to think about after this is merged, is how to prepare the deprecation of the older modem files / drivers. We do not want to have multiple implementations of the same thing for too long.

There may still be some work as the ESP_AT Wi-Fi driver is built around the Modem implementation...This looks great and it will be a shame to see the old SARA drivers being retired, it was hard work all that time ago.
@bjarki-trackunit Could use some help looking at this.

@bjarki-trackunit
Copy link
Collaborator Author

@WilliamGFish The gsm_ppp.c driver is replaced by the modem_cellular.c driver, which both use PPP and CMUX function, and it should therefore be deprecated. The SARA-R4 driver uses network offloading, and a bit of gpio handling, so there is an argument for keeping the driver. I do believe we should deprecate the old modem libraries like modem_cmd_handler which are replaceable by the new modem modules though, which then would require updating the existing modem drivers that depend on them. Is there interest in doing this update of drivers like the SARA-R4?

@WilliamGFish
Copy link
Collaborator

Is there interest in doing this update of drivers like the SARA-R4?

I think the SARA range is still going strong and the driver currently cover the U2 & R4 but may be able to be adapted to include the R5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants