Skip to content

Conversation

@SeppoTakalo
Copy link
Contributor

@SeppoTakalo SeppoTakalo commented Oct 29, 2025

Aim for this PR is to fetch all the required changes to get CMUX Power Saving into nRF Connect SDK 3.2.

This work has been submitted as a PR into Zephyr zephyrproject-rtos/zephyr#97362 almost a month ago and since then, then PR has been split into 15 different smaller PRs which has caused delays and we have not been able to merge it in time.

Therefore the last two PRs are still open and Zephyr is in feature freeze stage. Those are [nrf fromlist], but rest of the work and their dependencies are cherry-picked here.

Only few extra cherry-picks to prevent conflicts, otherwise the PR is pretty much modem/CMUX related.

List of already merged PRs

Pull requests that were needed to prevent conflicts

PRs that remain open

JordanYates and others added 23 commits October 31, 2025 15:15
Extract the user pipe setup and claim/release logic so that it can be
re-used by other software modules, if the AT shell is not used. Ideally
the chat instance would live within the `modem_at_user_pipe.c` and be
handed out by `modem_at_user_pipe_claim`, but the current chat API
doesn't make this possible.

Signed-off-by: Jordan Yates <[email protected]>
(cherry picked from commit c0a2928)
…the device

Allow PPP device to wake up the underlying cellular modem.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit b8541c5)
Full CMUX frames are way too much to fill the debug log
so disable those by default.
Sometimes it is enough to see the CMD and response types, without
hexdump.
Added also debug messages for opening and closing events.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit dac7a0f)
Do not read extra byte when we decide to drop a frame.
Instead go directly to MODEM_CMUX_RECEIVE_STATE_SOF, so the next
flag character will start a new frame.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 0025751)
Automatically size the CMUX work buffers based on
`CONFIG_MODEM_CMUX_MTU`. This eliminates a Kconfig variable that would
otherwise need to manually be kept in sync. The option to extend the
size of these buffers is still provided through
`CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE_EXTRA`.

Signed-off-by: Jordan Yates <[email protected]>
(cherry picked from commit f047a41)
…script

Remove periodic chat script as the AT+CEREG=1 notifications are already
enabled.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 5fa605a)
Implement following responses from 3GPP TS 27.010:
5.4.6.3.8 Non Supported Command Response (NSC)
5.3.3 Disconnected Mode (DM) response

Close DLC when receiving DM response.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 9de7d61)
Define CMUX_HEADER_SIZE macro that is 6 or 7 bytes depending on
MTU.

Remove the previous CMUX_FRAME_SIZE_MAX that was a bit misleading
as it meant only the header size without data and was fixed to 7 bytes.

Redefine new macros CMUX_FRAME_SIZE_MAX and CMUX_FRAME_SIZE_MIN which
are actually frame sizes with data included.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 9d93594)
The C/R bit in the address field should be handled as explained
in 5.2.1.2 in the spec (3GPP TS 127.010).

To detect if the frame is a command or a response,
we need to know who was the initiator of the CMUX channel.

>    Initiator is the station that take the initiative to initialize
>    the multiplexer (i.e. sends the SABM command at DLCI 0 )

See the table from given section of the specification.

Also, on UIH frames 5.4.3.1 says
>    The frames sent by the initiating station have the C/R bit set to 1
>    and those sent by the responding station have the C/R bit set to 0.

NOTE: This is different than a C/R bit in the Type field.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit b1942ce)
Optimise the PPP frame wrapping process by performing all work inside a
single function into a contiguous buffer, instead of operating on the
ring buffer one byte at a time.

On a nRF54L15 (M33 @ 128 MHz) before the change:
```
Wrapping 1062 byte packet: ~4.1 ms
Wrapping 1355 byte packet: ~5.0 ms
```
After the change:
```
Wrapping 1026 byte packet: ~2.4 ms
Wrapping 1341 byte packet: ~3.1 ms
```

Signed-off-by: Jordan Yates <[email protected]>
(cherry picked from commit 9f1e166)
Refactor internal event bits to use state enum values
and define set_state() and wait_state() so we don't need
two set of variables to maintain.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 2cfd924)
Instead of dropping all responses, handle the CLD.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 822a501)
…ng to CLD

If we immediately send disconnected event when CLD is received,
we might close the UART pipe before the response is actually send.

Also, shutdown_handler should not retry indefinitely.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit a9bc72a)
…down

Properly close down the CMUX channel before shutting down
the modem.

The CMUX Close-Down command should indicate the remote end
to clean up, even if we don't have shutdown script or power-key GPIO.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 7270168)
Implement Modem Status Command(MSC) and a per DLC flow
control by using it.

Send flow control signals when our input buffer don't fit
full frame anymore.
Stop TX if we have received from controls on MSC.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 1f996d0)
Extract common DTS bindings to zephyr,cellular-modem-device.yaml
as these are referred in the modem_cellular.c in the
MODEM_CELLULAR_DEFINE_INSTANCE() macro.

Signed-off-by: Seppo Takalo <[email protected]>
(cherry picked from commit 4040a1e)
…r listen()

Add a note that the backlog parameter of the listen() function is now
respected and the backlog support has been implemented for the TCP
server.

Signed-off-by: Robert Lubos <[email protected]>
(cherry picked from commit 77c348a)
Add the option to use a dedicated workqueue for the modem backend
instead of the system workqueue.

Signed-off-by: Jordan Yates <[email protected]>
(cherry picked from commit 761961f)
…r commands

Instead of relying non-standard compiler behavior, define
encode and decode functions for all CMUX command structures.

Final command is encoded into a shared buffer, because it is
always copied directly to TX ringbuffer.

Added also functions to validate commands.

Upstream PR #: 98009

Signed-off-by: Seppo Takalo <[email protected]>
DTR signal on UART extends the power saving by allowing host
to indicate the remote end that the UART is not in active state.

Upstream PR #: 98145

Signed-off-by: Seppo Takalo <[email protected]>
Signal powersaving mode for the remote end using PSC command.
Wakes up the remote end from powersaving mode by sending flag characters.

This method is defined in 3GPP TS 27.010.
Sections 5.4.6.3.2 Power Saving Control (PSC) and
5.4.7 Power Control and Wake-up Mechanisms.

Essentially it is one PSC command to indicate a sleep state, and
then repeated flag characters to wake up the remote end or indicate
that we have been woken up.

Upstream PR #: 97362

Signed-off-by: Seppo Takalo <[email protected]>
… CMUX

CMUX driver can enable the support for idle-timer in
devicetree and can be requested to shut down the pipe
during sleep.

Then UART backend put the actual device into sleep when
pipe is closed.

Waking up is requested by sending data to DLC pipe
or by manually opening the uart_pipe.
Modem may request similar wake-up by a RING interrupt which
would open the same pipe.

When UART is powered and pipe is not closed, CMUX wake-up
procedure is automatic. Either end may initiate the wake-up.

Upstream PR #: 97362

Signed-off-by: Seppo Takalo <[email protected]>
…ffer

Ringbuffer is not safe in ISR but k_pipe without waiting is.
So use pipe for events, so that possible GPIO callbacks from
ISR content can post events.

Upstream PR #: 97362

Signed-off-by: Seppo Takalo <[email protected]>
Use ring indicator to wake up the CMUX device
from sleep.
Only used for runtime power management, but same event
could be used for initiating idle -> connected as well.

Upstream PR #: 97362

Signed-off-by: Seppo Takalo <[email protected]>
Instead of copying all fields from cmux_config into run-time
struct cmux, just have the configuration structure as a member.

Upstream PR #: 97362

Signed-off-by: Seppo Takalo <[email protected]>
When working on CMUX power saving, it is typical
that we end up closing the pipe before the last
RX_READY event is handled from workqueue, so we end up
receiving -EPERM which is not really a fatal error.

Pipes recover when they are re-opened. So drop this error
and return zero instead, like modem_pipe_open() and close() does.

Upstream PR #: 97362

Signed-off-by: Seppo Takalo <[email protected]>
@SeppoTakalo
Copy link
Contributor Author

@rlubos do you know, is there a way to get this in when the "Commit tags" check fails on:

commit-tags: fromlist: 98145

ERROR: PR #98145 has requested changes, please resolve those

But the requested change have been addressed, it is just that the reviewers are not responding
image

See zephyrproject-rtos/zephyr#98145

These delays accumulate and we soon run out of time before next NCS release. If every change request takes 3-5 days, we only have time for one or two changes anymore.

@rlubos
Copy link
Contributor

rlubos commented Oct 31, 2025

@carlescufi Please check above, ok to override the Commit tags check for this particular case?

@SeppoTakalo BTW the manifest PR fails on Compliance check, it should be fixed before the PR is considered mergable.

@carlescufi
Copy link
Contributor

@carlescufi Please check above, ok to override the Commit tags check for this particular case?

OK to override.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants