zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.04k stars 6.18k forks source link

Decoupling the modem_cellular.c device driver #73722

Open bjarki-andreasen opened 1 month ago

bjarki-andreasen commented 1 month ago

Introduction

We need to make the modem subsystem more flexible to cover the following requirements:

Problem description

The current primary cellular modem driver modem_cellular.c contains quite a bit of very similar if not duplicate code, and is not easily extendable without copying the entire driver out-of-tree. It is also limited to only supporting modems which support CMUX, which is not always the case, and in some cases may not be desired even if supported.

Specific usecases

Proposed solution

For reference, the current design of modem_cellular.c is presented here:

modem-sys-Page-3

For modems with CMUX, like the ones supported by the modem_cellular.c driver, the following diagram shows an applicable solution:

modem-sys

The new modem module modem_pipelink, makes pipes created by and managed by the device driver, available to the subsystem/application layer. The modem device driver signals when the pipes exposed through pipelinks become available (after power up and initial configuration), which triggers the common modules to open their pipe and start operating. A PR for the pipe module with an example user (AT shell) is found here #73240

Notice the scalability of the solution, as we can abstract away the type of pipe (UART/DLCI) and we can extend the number of modules interacting with the modem by simply creating more DLCI channels and pipelinks :)

For modems with CMUX, this will work great, since each pipe is completely separate, either physically or through CMUX, allowing PPP on one channel, without blocking another. However, for modems without CMUX or similar, the following diagram proposes a slightly different solution:

modem-sys-Page-2

This design replaces modem cmux with a new module modem pipemux. While modem cmux creates parallel channels, where each can transmit and receive independently, only one modem pipemux channel can transmit at a time, while all modem pipemux channels can receive simultaneously. To synchronize transmitting data between the common modules using the pipemux, a "borrow" feature must be added to the modem_pipe module. The borrow feature will be completely backwards compatible, and will use the following API:

int modem_pipe_lock(struct modem_pipe *pipe, k_timeout_t timeout);
int modem_pipe_unlock(struct modem_pipe *pipe);

Common modules will call modem_pipe_lock() on their pipe instance when they need to transmit something. With the lock held, they will perform any synchronous work they need to, like running a chat script, then they will call modem_pipe_unlock() to allow other common modules to transmit something.

Using modem_cmux, taking the lock on a pipe connected to a DLCI channel will always succeed immediately. Using modem_pipemux, taking the lock may block until it becomes available.

Summary

We can make the modem drivers flexible, allowing custom user defined logic, and creating common modules for shared features, by introducing two new modem modules, and adding a lock to the modem_pipe module. Once these modules are in, we can start creating new optimized vendor specific drivers for power management, and creating common modules for shared features like SMS, PPP, AT shell etc.

rerickson1 commented 1 month ago

Like this a lot. Do you have a use case in mind to test pipemux on a real modem? I am curious to see it in action with a real example switching between PPP and AT commands :-)

bjarki-andreasen commented 1 month ago

@rerickson1 I'm working on the modem_pipemux module and lock mechanism for the modem_pipe currently, Once ready I will put together a demo, probably gonna copy the modem_cellular driver, and rewrite it to use modem_pipemux in place of modem_cmux :) It may be a better demo to use pipelinks and move the PPP and AT commands out of the driver as well, similar to the "complete" design