Skip to content

dectnrp_nrf91x1: first driver implementation - #3

Merged
bullekeup merged 1 commit into
mainfrom
dectnrp_nrf91-first-shot
Sep 18, 2026
Merged

bullekeup merged 1 commit into
mainfrom
dectnrp_nrf91-first-shot

Conversation

@RainerSchubert

@RainerSchubert RainerSchubert commented Jul 14, 2026 •

Copy link
Copy Markdown
Member

A first shot dectnrp_nrf91 driver implementation is added.

This PR can be setup/build/debugging and tested in combination with Opener-Initiative/opener-samples#1.

You can "easily" follow the steps in README.md. This branch of this PR gets automatically checked out by west.

Comment thread drivers/dectnrp/CMakeLists.txt Resolved
Comment thread include/zephyr/net/dectnrp/dectnrp.h Outdated

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Also here:
All the l2 protocol header files should live in include/zephyr/net
https://github.com/zephyrproject-rtos/zephyr/tree/zephyr-v3.5.0/include/zephyr/net
Naming should be similar to ieee802154_...

@RainerSchubert
RainerSchubert force-pushed the dectnrp_nrf91-first-shot branch 2 times, most recently from 251953f to 16aa273 Compare July 14, 2026 17:19
*/
uint8_t phy_header_type :1;
/** Transport parameters related to this operation */
struct dectnrp_transport_parameters transport_parameters;

@RainerSchubert RainerSchubert Jul 14, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Packet related parameters as transport parameters phy_header_type etc are currently implemented that way as we can not inject a control-block directly into net_pkt as for example ieee802154 does
https://github.com/zephyrproject-rtos/zephyr/blob/1ce2060f563897d4430d66c111a77cbc611634a7/include/zephyr/net/net_pkt.h#L354.

But we could use the generic one and append packet related parameters directly to the packet.

/* Control block which could be used by any layer */
	union {
		uint8_t cb[CONFIG_NET_PKT_CONTROL_BLOCK_SIZE];

https://github.com/zephyrproject-rtos/zephyr/blob/1ce2060f563897d4430d66c111a77cbc611634a7/include/zephyr/net/net_pkt.h#L349

Comment thread include/zephyr/net/dectnrp_driver.h Outdated
/** RSSI2 value of this message.
* Encoded according to @ref ETSI TS 103 636-2 chapter 8.3.
*
* @todo It needs to be decided whether we want to transmit the RSSI2 according to spec.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I have chosen the format according to ETSI TS 103 636-2 chapter 8.3 because it is saving space.
But we pay for that by more overhead when decoding encoding.

Maybe for single RSSI2 values it would be more useful to have int16_t with simple integer values.
It takes one byte more but saves the hassle of encoding/decoding.

For RSSI1 I choose the format according to ETSI TS 103 636-2 chapter 8.2 (same as RSSI2) because there are a lot more values to handle. There I think it makes sense to save memory.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it depends on what you are using it for; RSSI2 is better for computing/calculations and RSSI is ok for human readable.

Comment thread include/zephyr/net/dectnrp_driver.h Resolved
@RainerSchubert
RainerSchubert force-pushed the dectnrp_nrf91-first-shot branch 3 times, most recently from 39ff747 to 850c0ed Compare July 14, 2026 19:38
/** Related start time. */
net_time_t start_time;
/** Points to PCC. */
const uint8_t *pcc;

@RainerSchubert RainerSchubert Jul 14, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

With this implementation I decided to use the event interface in interrupt context. With this implementation the events are notified directly in interrupt context of the IPC. That means the upper layer (presumable the scheduler) finish this interrupt as fast as it can.
Decision needed: Do we want the event interface be an interrupt.

With this implementation I decided also to hand the PCC and PDC to the upper layer as raw pointers into IPC buffers. The upper layer (presumable the scheduler) has the flexibility how to handle it. But as we are in interrupt context anyway the scheduler has to make a copy and finish the interrupt as fast as it can.

Naturally I would prefer a net_pkt instead of raw pcc + pdc. But that may involve duplicate copying of data. If we do decide to use a net_pkt the driver is responsible of copying data into it.
In that case

  • we can also manage meta data related to the message in the context block of the net_pkt.
  • the driver needs to get the net_pkt for example via struct net_pkt *pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, packet_size, AF_UNSPEC, 0, K_MSEC(100));

Decision needed: Do we want to use net_pkt to transfer messages (pcc alone, pcc+pdc) via event interface.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think that copying data here now is fine. If we do want to optimize that later, we might sidestep some of libmodem's memory management and then let the radio core write the data right into the right place in a net_pkt.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For me using net_pkt for events passing is too much work at this stage, would involve copying in the driver, notify the scheduler, handling net_buf allocation and associated errors, etc...

As for latency concerns, having the scheduler handling events in interrupt context and decide if it takes action immediately or defer processing is beneficial, so I think passing raw pointers in interrupt mode and make the scheduler copy data and return is the right choice for now (at least until we can have net_pkt directly wired at libmodem's memory management layer like @chrysn suggested)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So for now I am going to leave it the "raw pointer" way.

struct dectnrp_rssi_mode {
uint8_t _dummy;
/** The result holds the rssi1 dbm values for each sub-slot for one frame. */
uint8_t subslot[DECTNRP_SUBSLOTS_PER_FRAME];

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I decided to have a resolution of subslots for reported RSSI1 results.
We also could choose the per symbol resolution as Nordic reports it but that consumes a lot more memory (5*48 = 240).
I may see a use-case for the per symbol resolution to make the scheduling (frame start placement) more fine granular.
Also we have to support sub-frame/per-slot/per-subslot measurement.
We anyway have to deal with a more flexible solution here when we start supporting µ>1..

* @param data
* @param len
*/
static void rssi1_accumulate(struct dectnrp_driver_op *op, int8_t *data, uint16_t len)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As decided with the dectnrp_driver_api

850c0ed#r3759909992

we currently accumulate RSSI1 symbol values into RSSI1 sub-slot values.
Accumulate means we pick the maximum value out of 5 rssi1 (per-symbol) values.

@RainerSchubert
RainerSchubert force-pushed the dectnrp_nrf91-first-shot branch from 85ddbdf to 7e60f37 Compare September 3, 2026 10:05
};

union dectnrp_event_data {
enum dectnrp_driver_error {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I started to add some enumerated error codes. This should be discussed.

In my opinion generic posix errno are not fine granular enough to differentiate errors of dectnrp_driver.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree, these can be added as the work progresses and they are justified

@RainerSchubert
RainerSchubert marked this pull request as ready for review September 4, 2026 15:24
@RainerSchubert
RainerSchubert requested a review from a team as a code owner September 4, 2026 15:24
@RainerSchubert
RainerSchubert force-pushed the dectnrp_nrf91-first-shot branch 4 times, most recently from 2ab2e09 to c834bb3 Compare September 9, 2026 08:54
Comment thread drivers/dectnrp/dectnrp_nrf91.c Outdated

#if CONFIG_DECTNRP_DRIVER_BLOCKING_API

static int nrf91_set_channel(const struct device *dev, uint16_t channel)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we be considering the use of zephyr inbuilt network management functionality (NET_MGMT). If the application changes the channel, tx power, etc it could be dangerous as it does not have access to the resource and scheduling functions.
For early samples it is of minimal importance but long term could be a n issue.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree, I think we should indeed use Zephyr network management, but we should be careful where to wire it within the stack since we will have non Zephyr users like @chrysn with Ariel OS, who will probably not be able to reimplement the whole Zephyr network management subsystem. This is surely something we should discuss and plan.

@RainerSchubert RainerSchubert Sep 10, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes net_mgmt is the way to go. But here we have the driver interface, I think the net_mgmt should go to l2 layer which may use driver api to change something in the driver. That is also the way ieee802154 does use it.

Also that nrf91_set_channel function will not be needed as channel should be set per operation.

{
char fw_uuid_buf[64];

int ret = nrf_modem_at_cmd(fw_uuid_buf, sizeof(fw_uuid_buf), "AT%%XMODEMUUID");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am a little confused with the use of AT commands rather than function calls:
hwinfo_get_device_id(*uint_16 device_id, sizeof(device_id));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The modem build UUID describes the modem firmware build, it is not the same as the device id returned by hwinfo_get_device_id (u64 stored in the FICR)

I have not found a function to retrieve the modem build UUID in the modem / nrfxlib library (but I may have missed it)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i can not see it either but we should talk to Lauri about this being part of the modem firmware as in future releases certain functionality will be reliant on the firmware version installed.

*mfw_version = RADIO_MFW_UNKNOWN;
char fw_version_buf[32];

int ret = nrf_modem_at_cmd(fw_version_buf, sizeof(fw_version_buf), "AT+CGMR");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

again an AT command rather than direct function call.
They should have an easy method for modem firmware version query

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have not found a function to easily retrieve the firmware version, and as this AT commands is an officially documented way to get it and we only check it at init, I think it is fine

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

But it works and as it is the "official" way of retrieving uuid and mfw I think for now it should be OK.
It anyway is a wrapper around the IPC and AT commands is just a "string API" to access the modem firmware.

@bullekeup

Copy link
Copy Markdown
Member

I have reviewed and tested on my two nRF9151 DKs, everything works as intended first try !

Before merging, I think we should apply the rename refactor from nrf91 to nrf91x1 to be more descriptive of the intended target (but I will not block merging on that if everyone else is OK with current naming)

@po3ts @chrysn what's your view on this ?

@WilliamGFish WilliamGFish left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM but I have questions about the use of AT commands with the driver

@po3ts

po3ts commented Sep 10, 2026

Copy link
Copy Markdown
Member

I have reviewed and tested on my two nRF9151 DKs, everything works as intended first try !

Before merging, I think we should apply the rename refactor from nrf91 to nrf91x1 to be more descriptive of the intended target (but I will not block merging on that if everyone else is OK with current naming)

@po3ts @chrysn what's your view on this ?

I support renaming to nrf91x1. I still have to run it on my boards, though. I'll do that either this evening or tomorrow morning...

@RainerSchubert

RainerSchubert commented Sep 10, 2026 •

Copy link
Copy Markdown
Member Author

So I am going to rename nrf91 -> nrf91x1.
It seems a democratical consensus ;)

@RainerSchubert

Copy link
Copy Markdown
Member Author

LGTM but I have questions about the use of AT commands with the driver

We have no other solution for that merge (or do we have one!?) .. I think Nordic will not change it in the near future.

@po3ts

po3ts commented Sep 12, 2026

Copy link
Copy Markdown
Member

Just ran it on my nRF9151 DKs, worked out of the box! This is ready to merge from my side once the nrf91x1 rename is in.

  * improved the dectnrp_driver_api
  * first implementation of nrf91x1 driver
    * implements scheduled api with rx, tx, rssi1 operations
    * DECTNRP_DRIVER_NRF91X1 depends on SOC_SERIES_NRF91X
  * added static driver capabilities hard-wired via kconfig
  * add first simple DECTNRP_L2 draft

Signed-off-by: Rainer Schubert <rainer.schubert@deveritec.com>
@RainerSchubert
RainerSchubert force-pushed the dectnrp_nrf91-first-shot branch from b5c514e to bb33f5c Compare September 14, 2026 18:47
@RainerSchubert

Copy link
Copy Markdown
Member Author

I changed (hopefully) every occurrence of nrf91 to nrf91x1 (both lower and upper case and also filenames).

@WilliamGFish WilliamGFish left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM...if you guys test on hardware then ok with me

@RainerSchubert RainerSchubert changed the title dectnrp_nrf91: first driver implementation dectnrp_nrf91x1: first driver implementation Sep 17, 2026

@po3ts po3ts left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's very good work, @RainerSchubert! Ready to merge from my side.

@po3ts

po3ts commented Sep 18, 2026

Copy link
Copy Markdown
Member

@bullekeup and @chrysn, we need one additional approval before this can be merged into main. Can one of you please approve the changes?

@bullekeup
bullekeup merged commit 25e6712 into main Sep 18, 2026
2 checks passed
@po3ts
po3ts deleted the dectnrp_nrf91-first-shot branch September 26, 2026 17:07
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