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

drivers/nrf24l01p: Netdev driver for nrf24l01p #13743

Merged
merged 4 commits into from
Jan 24, 2021

Conversation

fabian18
Copy link
Contributor

@fabian18 fabian18 commented Mar 28, 2020

Contribution description

This PR is a shorter version of #12681, which aimed to contribute a netdev driver for the nrf24l01+ but was too large to be reviewed.

The old driver for the nrf24l01+ is simply renamed to nrf24l01p_lowlevel.
With this driver you can only use Enhanced ShockBurst as a protocol.
There is no custom header that includes the transceiver´s source address.

Testing procedure

Try txtsnd:

ifconfig
2020-03-28 09:31:33,935 #  ifconfig
2020-03-28 09:31:33,939 # Iface  3  HWaddr: 71:24:28:11:01  Channel: 4 
2020-03-28 09:31:33,944 #            TX-Power: 0dBm  State: RX  max. Retrans.: 5 
2020-03-28 09:31:33,948 #           AUTOACK  Source address length: 5
2020-03-28 09:31:33,949 #           
2020-03-28 09:31:33,952 #           Statistics for Layer 2
2020-03-28 09:31:33,955 #             RX packets 0  bytes 0
2020-03-28 09:31:33,959 #             TX packets 0 (Multicast: 0)  bytes 0
2020-03-28 09:31:33,962 #             TX succeeded 0 errors 0
2020-03-28 09:31:33,963 # 
txtsnd 3 77:24:26:11:01 RIOT
2020-03-28 09:31:46,899 #  txtsnd 3 77:24:26:11:01 RIOT
ifconfig
2020-03-28 09:32:12,521 #  ifconfig
2020-03-28 09:32:12,525 # Iface  3  HWaddr: 71:24:28:11:01  Channel: 4 
2020-03-28 09:32:12,531 #            TX-Power: 0dBm  State: RX  max. Retrans.: 5 
2020-03-28 09:32:12,534 #           AUTOACK  Source address length: 5
2020-03-28 09:32:12,535 #           
2020-03-28 09:32:12,538 #           Statistics for Layer 2
2020-03-28 09:32:12,542 #             RX packets 1  bytes 4
2020-03-28 09:32:12,546 #             TX packets 0 (Multicast: 0)  bytes 4
2020-03-28 09:32:12,549 #             TX succeeded 1 errors 0
2020-03-28 09:32:12,550 #

> ifconfig
2020-03-28 09:31:22,099 #  ifconfig
2020-03-28 09:31:22,103 # Iface  3  HWaddr: 77:24:26:11:01  Channel: 4 
2020-03-28 09:31:22,108 #            TX-Power: 0dBm  State: RX  max. Retrans.: 5 
2020-03-28 09:31:22,112 #           AUTOACK  Source address length: 5
2020-03-28 09:31:22,113 #           
2020-03-28 09:31:22,116 #           Statistics for Layer 2
2020-03-28 09:31:22,119 #             RX packets 0  bytes 0
2020-03-28 09:31:22,123 #             TX packets 0 (Multicast: 0)  bytes 0
2020-03-28 09:31:22,126 #             TX succeeded 0 errors 0
2020-03-28 09:31:22,126 # 
> ifconfig
2020-03-28 09:31:52,236 #  ifconfig
2020-03-28 09:31:52,240 # Iface  3  HWaddr: 77:24:26:11:01  Channel: 4 
2020-03-28 09:31:52,245 #            TX-Power: 0dBm  State: RX  max. Retrans.: 5 
2020-03-28 09:31:52,249 #           AUTOACK  Source address length: 5
2020-03-28 09:31:52,250 #           
2020-03-28 09:31:52,253 #           Statistics for Layer 2
2020-03-28 09:31:52,256 #             RX packets 1  bytes 4
2020-03-28 09:31:52,260 #             TX packets 0 (Multicast: 0)  bytes 0
2020-03-28 09:31:52,263 #             TX succeeded 0 errors 0
2020-03-28 09:31:52,264 # 
> txtsnd 3 71:24:28:11:01 RIOT
2020-03-28 09:32:08,878 #  txtsnd 3 71:24:28:11:01 RIOT

Issues/PRs references

#1808
#2021
#12681

@benpicco benpicco added Area: drivers Area: Device drivers Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Mar 28, 2020
@benpicco
Copy link
Contributor

What is the difference between this and #12681?

@fabian18
Copy link
Contributor Author

#12681 :

  • deleted the nrf24l01p lowlevel driver
  • you could choose whether you want to use ShockBurst or Enhanced SchockBurst
  • There was a custom header that was put into the payload if MODULE_GNRC_SIXLOWPAN
    was used. This made the transceiver include it´s source address into a frame. This was necessary to construct the source ipv6 address (from IPHC).
  • And you could do that with Shockburst and Enhanced Shockburst. For ShockBurst, which only supports static payload lengths, you had to remove padding bytes.

This resulted in a lot of ugly #ifdefs in the code.
Now there is only Enhanced ShockBurst to send 32 byte of whatever you want and the old driver is just renamed to nrf24l01p_lowlevel, even though git counts it as added lines, if I see correctly.

@maribu
Copy link
Member

maribu commented Mar 30, 2020

Maybe it is better not rename the old driver, but to give the new driver a new distinct name? Github seems to be greatly confused by the rename. (When looking at the individual commits, the rename is correctly detected. But when looking the overall changes of this PR, it looks like drivers/include/nrf24l01p.h is modified; even though it is a completely new file.)

Or maybe we could have the rename split out as individual PR? That should be something that requires zero code review, so that a decision on that could be reached swiftly. And then this PR could be rebased on master once the rename is merged.

@fabian18
Copy link
Contributor Author

If this driver should not be named nrf24l01p, how would you name it?
I would rather split out the renaming of the old driver.
But what is the opinion of the original author(s)? (I think @PeterKietzmann )

@benpicco
Copy link
Contributor

nrf24l01p_ng 😉

@fabian18
Copy link
Contributor Author

nrf24l01p_ng wink

Ok, I could use this.

@maribu
Copy link
Member

maribu commented Mar 30, 2020

Note that for the GNRC stuff you could still go with nrf24l01p without _ng, e.g. for NETDEV_TYPE_NRF24L01P. The old driver was missing that integration and therefore no name conflicts will appear there. But: Maybe it is better to keep this consistent.

@fabian18 fabian18 force-pushed the driver-nrf24l01p-netdev-minimal branch from 0b5768b to e318375 Compare March 31, 2020 22:25
Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

I finally received my modules and can do some testing now!

After flashing examples/gnrc_networking I noticed some failed asserts - you'll need to add NETDEV_TYPE_NRF24L01P_NG to sys/net/link_layer/l2util/l2util.c.

You probably want to add it in some other places too - I'd say searching for NETDEV_TYPE_CC110X is a good guide as that's a similar transceiver.

benpicco added a commit to benpicco/RIOT that referenced this pull request May 4, 2020
This does two things:

The documentation of `luid_get()` is wrong, or at least confusing.

It talks about

> an 8-bit incrementing counter value into the most significant byte

while the implementation does

    ((uint8_t *)buf)[len - 1] ^= lastused++;

Now it could be argued that the intention was that the ID is supposed
to be used in Big Endian contexts and that was an omission, however
to keep everyone's sanity, let's keep it simple and ust state that this
actually changes the LSB.

Also add a `luid_get_be()` function that does the same, but modifies the
most significant bit - or the least significant one if interpreted as
Big Endian.

This can then be used directly by e.g. RIOT-OS#13743
benpicco added a commit to benpicco/RIOT that referenced this pull request May 4, 2020
This does two things:

The documentation of `luid_get()` is wrong, or at least confusing.

It talks about

> an 8-bit incrementing counter value into the most significant byte

while the implementation does

    ((uint8_t *)buf)[0] ^= lastused++;	// 0 is LSB!

Now it could be argued that the intention was that the ID is supposed
to be used in Big Endian contexts and that was an omission, however
to keep everyone's sanity, let's keep it simple and ust state that this
actually changes the LSB.

Also add a `luid_get_be()` function that does the same, but modifies the
most significant bit - or the least significant one if interpreted as
Big Endian.

This can then be used directly by e.g. RIOT-OS#13743
benpicco added a commit to benpicco/RIOT that referenced this pull request May 4, 2020
This does two things:

The documentation of `luid_get()` is wrong, or at least confusing.

It talks about

> an 8-bit incrementing counter value into the most significant byte

while the implementation does

    ((uint8_t *)buf)[0] ^= lastused++;	// 0 is LSB!

Now it could be argued that the intention was that the ID is supposed
to be used in Big Endian contexts and that was an omission, however
to keep everyone's sanity, let's keep it simple and just state that this
actually changes the LSB.

Also add a `luid_get_be()` function that does the same, but modifies the
most significant byte - or the least significant one if interpreted as
Big Endian.

This can then be used directly by e.g. RIOT-OS#13743
@benpicco
Copy link
Contributor

benpicco commented May 4, 2020

I flashed the driver on two nodes and they do get different addresses now, however they can not communicate:

same54-xpro

2020-05-04 18:29:03,621 # Iface  6  HWaddr: A4:DF:DD:73:F5  Channel: 4 
2020-05-04 18:29:03,626 #            TX-Power: 0dBm  State: RX  max. Retrans.: 5 
2020-05-04 18:29:03,630 #           AUTOACK  L2-PDU:32 MTU:32  HL:64  RTR  
2020-05-04 18:29:03,632 #           RTR_ADV  
2020-05-04 18:29:03,635 #           Source address length: 5
2020-05-04 18:29:03,638 #           Link type: wireless
2020-05-04 18:29:03,644 #           inet6 addr: fe80::a0a4:dfff:fedd:73f5  scope: link  VAL
2020-05-04 18:29:03,646 #           inet6 group: ff02::2
2020-05-04 18:29:03,649 #           inet6 group: ff02::1
2020-05-04 18:29:03,653 #           inet6 group: ff02::1:ffdd:73f5
2020-05-04 18:29:03,654 #           
2020-05-04 18:29:03,657 #           Statistics for Layer 2
2020-05-04 18:29:03,659 #             RX packets 0  bytes 0
2020-05-04 18:29:03,664 #             TX packets 0 (Multicast: 0)  bytes 0
2020-05-04 18:29:03,667 #             TX succeeded 0 errors 0
2020-05-04 18:29:03,670 #           Statistics for IPv6
2020-05-04 18:29:03,672 #             RX packets 0  bytes 0
2020-05-04 18:29:03,677 #             TX packets 24 (Multicast: 24)  bytes 0
2020-05-04 18:29:03,680 #             TX succeeded 0 errors 0
2020-05-04 18:29:03,680 # 
ping6 fe80::a07c:26ff:fe67:1537
2020-05-04 18:29:13,787 #  ping6 fe80::a07c:26ff:fe67:1537
2020-05-04 18:29:16,787 # 
2020-05-04 18:29:16,791 # --- fe80::a07c:26ff:fe67:1537 PING statistics ---
2020-05-04 18:29:16,797 # 3 packets transmitted, 0 packets received, 100% packet loss
> ping6 ff02::1
2020-05-04 18:29:20,825 #  ping6 ff02::1
2020-05-04 18:29:23,825 # 
2020-05-04 18:29:23,828 # --- ff02::1 PING statistics ---
2020-05-04 18:29:23,833 # 3 packets transmitted, 0 packets received, 100% packet loss
WeAct-f411ce
2020-05-04 18:30:02,416 # Iface  7  HWaddr: 7C:26:67:15:37  Channel: 4 
2020-05-04 18:30:02,418 #  TX-Power: 0dBm  State: RX  max. Retrans.: 5 
2020-05-04 18:30:02,419 # AUTOACK  L2-PDU:32 MTU:32  HL:64  RTR  
2020-05-04 18:30:02,419 # RTR_ADV  
2020-05-04 18:30:02,420 # Source address length: 5
2020-05-04 18:30:02,420 # Link type: wireless
2020-05-04 18:30:02,421 # inet6 addr: fe80::a07c:26ff:fe67:1537  scope: link  VAL
2020-05-04 18:30:02,422 # inet6 group: ff02::2
2020-05-04 18:30:02,422 # inet6 group: ff02::1
2020-05-04 18:30:02,422 # inet6 group: ff02::1:ff67:1537
2020-05-04 18:30:02,422 # 
2020-05-04 18:30:02,423 #           Statistics for Layer 2
2020-05-04 18:30:02,423 #           Statistics for IPv6
2020-05-04 18:30:02,423 # 
> ping6 fe80::a0a4:dfff:fedd:73f5
2020-05-04 18:30:07,784 #  ping6 fe80::a0a4:dfff:fedd:73f5
2020-05-04 18:30:10,784 # 
2020-05-04 18:30:10,785 # 100% packet loss
> ping6 ff02::1
2020-05-04 18:30:13,407 #  ping6 ff02::1
2020-05-04 18:30:16,407 # 
2020-05-04 18:30:16,407 # 100% packet loss

(Not sure why stdio looks different here, this is over CDC ACM)

Can't receive anything with txtsnd either.

@fabian18
Copy link
Contributor Author

fabian18 commented May 4, 2020

however they can not communicate:

They cannot communicate over ipv6. This is the major difference between this PR and the previous one.
They can only transmit 32 bytes,
hence ipv6 does not fit,
hence 6LowPAN is required
hence senders must include source L2 address for IPHC,
hence the ShockBurst protocol requires a proprietary change
(which was done by the previous PR)

Can't receive anything with txtsnd either.

Thats weird ...
Don´t you see an increasing RX counter in ifconfig if you send via txtsnd?
Have you tried to enable debug, if you want more output?
That are my params.

CFLAGS += "-DNRF24L01P_NG_PARAMS = {                                   \
    .spi = $(NRF24L01P_SPI_PORT),                                      \
    .spi_clk = SPI_CLK_5MHZ,                                           \
    .pin_cs = $(NRF24L01P_CS_PIN),                                     \
    .pin_ce = $(NRF24L01P_CE_PIN),                                     \
    .pin_irq = $(NRF24L01P_IRQ_PIN),                                   \
    .config =       {                                                  \
        .cfg_crc = NRF24L01P_NG_PARAM_CRC_LEN,                         \
        .cfg_tx_power = NRF24L01P_NG_PARAM_TX_POWER,                   \
        .cfg_data_rate = NRF24L01P_NG_PARAM_DATA_RATE,                 \
        .cfg_channel = NRF24L01P_NG_PARAM_CHANNEL,                     \
        .cfg_max_retr = NRF24L01P_NG_PARAM_MAX_RETRANSM,               \
        .cfg_retr_delay = NRF24L01P_NG_PARAM_RETRANSM_DELAY,           \
    }                                                                  \
}"

@fabian18
Copy link
Contributor Author

Do I understand correctly that retransmission (and ACKs) are handled by hardware?

Yes.

Thank you @benpicco that you looked at the driver again.
I will add comments. But I also have not looked at the driver for a long time and I´ll have to look up the details for myself again.

@fabian18
Copy link
Contributor Author

Right now it is like this:
pipe 0:

  • holds the default listen address of the transceiver
  • address must be overridden to the destination address if a transmission is initiated, according to the datasheet

pipe 1:

  • holds the address that is used for broadcasting 0xff ... 0xff

pipe 2 - 5:

  • are enabled optionally
  • must share the address of pipe 1 but must have a different LSByte, according to the datasheet
    (So they are 0xff ... X. This is stupid. I don´t know why I did this.)

I am going to change pipe 0 and pipe 1 like this:
pipe 0:

  • holds the broadcasting address 0xff ... 0xff

pipe 1:

  • holds the default listen address of the transceiver

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

Looks pretty good!

I noticed a problem with large fragmented packets though

2020-12-20 01:41:38,595 #  ping fe80::a07f:b6ff:fe84:b47f -s 250
2020-12-20 01:41:38,652 # 258 bytes from fe80::a07f:b6ff:fe84:b47f%7: icmp_seq=0 ttl=64 time=54.932 ms
2020-12-20 01:41:39,709 # 258 bytes from fe80::a07f:b6ff:fe84:b47f%7: icmp_seq=1 ttl=64 time=112.845 ms
2020-12-20 01:41:40,661 # 258 bytes from fe80::a07f:b6ff:fe84:b47f%7: icmp_seq=2 ttl=64 time=64.198 ms
2020-12-20 01:41:40,661 # 
2020-12-20 01:41:40,661 # --- fe80::a07f:b6ff:fe84:b47f PING statistics ---
2020-12-20 01:41:40,662 # 3 packets transmitted, 3 packets received, 0% packet loss
2020-12-20 01:41:40,663 # round-trip min/avg/max = 54.932/77.325/112.845 ms
2020-12-20 01:41:42,604 #  ping fe80::a07f:b6ff:fe84:b47f -s 300
2020-12-20 01:41:42,606 # gnrc_netif: possibly lost interrupt.
2020-12-20 01:41:44,606 # gnrc_netif: possibly lost interrupt.
2020-12-20 01:41:45,604 # 
2020-12-20 01:41:45,605 # --- fe80::a07f:b6ff:fe84:b47f PING statistics ---
2020-12-20 01:41:45,607 # 3 packets transmitted, 0 packets received, 100% packet loss

my suspicion is that this has to do with that busy send loop.

I tried returning -EBUSY instead of -EGAIN and not releasing the pkt on failure so gnrc_netif_pktq can re-send it.

However, after that fragmented packets wouldn't work at all anymore.
My suspicion is that this might have to do with the added headers in _nrf24l01p_ng_adpt_send().

drivers/nrf24l01p_ng/nrf24l01p_ng_netdev.c Outdated Show resolved Hide resolved
drivers/nrf24l01p_ng/nrf24l01p_ng_communication.c Outdated Show resolved Hide resolved
drivers/nrf24l01p_ng/nrf24l01p_ng_netdev.c Outdated Show resolved Hide resolved
@fabian18
Copy link
Contributor Author

gnrc_netif: possibly lost interrupt.

😕 At least it´s reproducible for me this time.

I did some trial and error and noticed, if I increase the message queue in gnrc_networking/main.c and CONFIG_GNRC_NETIF_MSG_QUEUE_SIZE_EXP the problem seems to be gone.

ping6
> ping6 fe80::a0eb:24ff:fe6a:fd76%7 -c 64 -s 500
2020-12-21 09:57:13,563 #  ping6 fe80::a0eb:24ff:fe6a:fd76%7 -c 64 -s 500
2020-12-21 09:57:13,621 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=0 ttl=64 time=51.929 ms
2020-12-21 09:57:14,623 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=1 ttl=64 time=64.302 ms
2020-12-21 09:57:15,605 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=2 ttl=64 time=55.129 ms
2020-12-21 09:57:16,593 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=3 ttl=64 time=52.085 ms
2020-12-21 09:57:17,585 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=4 ttl=64 time=55.045 ms
2020-12-21 09:57:18,582 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=5 ttl=64 time=61.226 ms
2020-12-21 09:57:19,566 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=6 ttl=64 time=55.127 ms
2020-12-21 09:57:20,563 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=7 ttl=64 time=61.135 ms
2020-12-21 09:57:21,544 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=8 ttl=64 time=51.990 ms
2020-12-21 09:57:22,535 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=9 ttl=64 time=52.002 ms
2020-12-21 09:57:23,534 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=10 ttl=64 time=61.217 ms
2020-12-21 09:57:24,522 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=11 ttl=64 time=58.073 ms
2020-12-21 09:57:25,506 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=12 ttl=64 time=52.080 ms
2020-12-21 09:57:26,494 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=13 ttl=64 time=48.923 ms
2020-12-21 09:57:27,491 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=14 ttl=64 time=55.007 ms
2020-12-21 09:57:28,482 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=15 ttl=64 time=55.134 ms
2020-12-21 09:57:29,479 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=16 ttl=64 time=61.121 ms
2020-12-21 09:57:30,455 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=17 ttl=64 time=45.898 ms
2020-12-21 09:57:31,455 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=18 ttl=64 time=55.012 ms
2020-12-21 09:57:32,441 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=19 ttl=64 time=48.920 ms
2020-12-21 09:57:33,432 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=20 ttl=64 time=48.936 ms
2020-12-21 09:57:34,433 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=21 ttl=64 time=58.069 ms
2020-12-21 09:57:35,415 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=22 ttl=64 time=48.922 ms
2020-12-21 09:57:36,412 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=23 ttl=64 time=55.035 ms
2020-12-21 09:57:37,400 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=24 ttl=64 time=52.083 ms
2020-12-21 09:57:38,396 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=25 ttl=64 time=58.165 ms
2020-12-21 09:57:39,387 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=26 ttl=64 time=58.067 ms
2020-12-21 09:57:40,375 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=27 ttl=64 time=55.043 ms
2020-12-21 09:57:41,375 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=28 ttl=64 time=64.184 ms
2020-12-21 09:57:42,363 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=29 ttl=64 time=61.157 ms
2020-12-21 09:57:43,348 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=30 ttl=64 time=55.042 ms
2020-12-21 09:57:44,342 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=31 ttl=64 time=58.105 ms
2020-12-21 09:57:45,330 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=32 ttl=64 time=55.041 ms
2020-12-21 09:57:46,318 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=33 ttl=64 time=52.167 ms
2020-12-21 09:57:47,314 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=34 ttl=64 time=58.044 ms
2020-12-21 09:57:48,296 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=35 ttl=64 time=49.029 ms
2020-12-21 09:57:49,293 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=36 ttl=64 time=54.997 ms
2020-12-21 09:57:50,277 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=37 ttl=64 time=48.920 ms
2020-12-21 09:57:51,274 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=38 ttl=64 time=55.147 ms
2020-12-21 09:57:52,258 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=39 ttl=64 time=49.032 ms
2020-12-21 09:57:53,259 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=40 ttl=64 time=58.078 ms
2020-12-21 09:57:54,246 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=41 ttl=64 time=55.070 ms
2020-12-21 09:57:55,237 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=42 ttl=64 time=55.028 ms
2020-12-21 09:57:56,233 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=43 ttl=64 time=61.151 ms
2020-12-21 09:57:57,221 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=44 ttl=64 time=58.184 ms
2020-12-21 09:57:58,211 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=45 ttl=64 time=58.187 ms
2020-12-21 09:57:59,198 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=46 ttl=64 time=55.044 ms
2020-12-21 09:58:00,190 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=47 ttl=64 time=55.056 ms
2020-12-21 09:58:01,189 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=48 ttl=64 time=64.328 ms
2020-12-21 09:58:02,172 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=49 ttl=64 time=55.044 ms
2020-12-21 09:58:03,162 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=50 ttl=64 time=55.017 ms
2020-12-21 09:58:04,147 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=51 ttl=64 time=49.017 ms
2020-12-21 09:58:05,147 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=52 ttl=64 time=58.093 ms
2020-12-21 09:58:06,139 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=53 ttl=64 time=58.071 ms
2020-12-21 09:58:07,129 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=54 ttl=64 time=58.096 ms
2020-12-21 09:58:08,117 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=55 ttl=64 time=55.054 ms
2020-12-21 09:58:09,108 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=56 ttl=64 time=55.137 ms
2020-12-21 09:58:10,101 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=57 ttl=64 time=58.118 ms
2020-12-21 09:58:11,089 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=58 ttl=64 time=55.113 ms
2020-12-21 09:58:12,082 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=59 ttl=64 time=58.077 ms
2020-12-21 09:58:13,080 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=60 ttl=64 time=64.192 ms
2020-12-21 09:58:14,052 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=61 ttl=64 time=45.960 ms
2020-12-21 09:58:15,043 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=62 ttl=64 time=45.872 ms
2020-12-21 09:58:16,047 # 508 bytes from fe80::a0eb:24ff:fe6a:fd76%7: icmp_seq=63 ttl=64 time=58.352 ms
2020-12-21 09:58:16,047 # 
2020-12-21 09:58:16,052 # --- fe80::a0eb:24ff:fe6a:fd76 PING statistics ---
2020-12-21 09:58:16,057 # 64 packets transmitted, 64 packets received, 0% packet loss
2020-12-21 09:58:16,061 # round-trip min/avg/max = 45.872/55.404/64.328 ms

This appears to be natural to me because:
small fragments --> many fragments --> many frames --> many IRQ messages --> need larger message queue

May this be the simple solution?

@maribu
Copy link
Member

maribu commented Dec 21, 2020

This appears to be natural to me because:
small fragments --> many fragments --> many frames --> many IRQ messages --> need larger message queue

May this be the simple solution?

Sound very plausible to me. We discussed this is a few times recently in the context of the IEEE 802.15.4 Radio HAL. If I recall correctly, there was some consensus that this ideally should be managed by preventing the upper layers to send UDP datagrams at a faster rate than the driver and lower stacks can transmit the corresponding frames. That way, the packet queue would never overflow.

Additionally, there seems to me also be a consensus that the message queue is not a good fit for handling IRQ events. There already is code in master that mutliplexes an sys/ev event queue and a core/msg message queue, while the event queue is used for higher priority IRQ events. This can be unlocked with a pseudo module.

But IMO this is not a good solution, as simply multiplexing core/thread_flags with core/msg results in lower RAM/ROM consumption (I have a branch somewhere implementing this). The advantage of the event queue to also hook in other high priority events is IMO a false hope, as IRQ events need to remain of higher priority than any other event. And an actual event queue makes IMO only sense, if there is more than one potential event source. E.g. when multiple network drivers are handled with a single thread, it would make sense to have an event queue for the IRQ events for all network drivers driven by the single thread.

@benpicco
Copy link
Contributor

It looks like cc110x is provisioned for the same solution.

If I recall correctly, there was some consensus that this ideally should be managed by preventing the upper layers to send UDP datagrams at a faster rate than the driver and lower stacks can transmit the corresponding frames.

But IIRC there is noone yet to translate this into code 😉

@maribu
Copy link
Member

maribu commented Dec 21, 2020

But IIRC there is noone yet to translate this into code 😉

I have some work lying around based upon #14660 that goes a step in that direction. But only with the API change of #14660, we would have a clearly defined point at which the driver as completed a transmission.

Currently, e.g. the at86rf2xx driver blocks on the second call to send() until the first call is completed. So it would be infeasible to implement anything like this, as we just cannot know when a driver has finished the transmission. (There is the TX completed event, but its implementation is optional. Also, transmissions could fail - wired network devices on a shared bus can often detect a collision. It is not quite clear whether an "transmission aborted" should result in the tx completed event - I personally would say no. Hence, it is not really clear if we can indeed rely on those events to mark the end of an transmission attempt.)

However, my code would only make sure that the gnrc_netif would only fetch messages from the queue if it indeed can send out messages. There is nothing there to throttle the layers above - I wanted this groundwork to get in first. But I wonder if just using the blocking msg_send() instead of msg_try_send() when passing data to send down the stack would already solve the issue, once this is in place.

@maribu
Copy link
Member

maribu commented Dec 23, 2020

But IIRC there is noone yet to translate this into code 😉

Here you go: #15694

But that would still require #14660 to get in. And the change to gnrc_netif to make use of the new API - which I have laying around in some branch. But all parts are now translated to code, they just need to get upstream.

@maribu
Copy link
Member

maribu commented Dec 23, 2020

But that would still require #14660 to get in. And the change to gnrc_netif to make use of the new API - which I have laying around in some branch. But all parts are now translated to code, they just need to get upstream.

Well, for drivers that do block themselves (like e.g. stm32-eth or cc110x) this would already work as expected. For drivers that do not block or pseudo-block (I think pseudo-blocking is the best description for what the at86rf2xx does), this wouldn't work.

@benpicco
Copy link
Contributor

Fragmented packets now work with and without gnrc_netif_pktq up to a certain point(), then we get gnrc_netif: possibly lost interrupt. again. But I take this is an upper layer issue.

What's pretty cool is how fast the round-trip is with this driver:

2021-01-16 02:09:31,341 #  ping fe80::a0af:f6ff:fe18:3596 -i 3
2021-01-16 02:09:31,345 # 12 bytes from fe80::a0af:f6ff:fe18:3596%7: icmp_seq=0 ttl=64 time=1.624 ms
2021-01-16 02:09:31,348 # 12 bytes from fe80::a0af:f6ff:fe18:3596%7: icmp_seq=1 ttl=64 time=1.625 ms
2021-01-16 02:09:31,350 # 12 bytes from fe80::a0af:f6ff:fe18:3596%7: icmp_seq=2 ttl=64 time=1.625 ms
2021-01-16 02:09:31,350 # 
2021-01-16 02:09:31,351 # --- fe80::a0af:f6ff:fe18:3596 PING statistics ---
2021-01-16 02:09:31,352 # 3 packets transmitted, 3 packets received, 0% packet loss
2021-01-16 02:09:31,353 # round-trip min/avg/max = 1.624/1.624/1.625 ms

@benpicco
Copy link
Contributor

Please squash (& rebase)

@fabian18 fabian18 force-pushed the driver-nrf24l01p-netdev-minimal branch from 9f2c002 to 5b93427 Compare January 23, 2021 14:33
@benpicco
Copy link
Contributor

Looks like tests/driver_nrf24l01p_ng needs a Makefile.ci.

@fabian18 fabian18 force-pushed the driver-nrf24l01p-netdev-minimal branch from 5b93427 to e83d2a3 Compare January 24, 2021 15:47
@fabian18
Copy link
Contributor Author

fabian18 commented Jan 24, 2021

I have renamed:
_swap_bytes() -> _nrf24l01p_ng_swap_bytes() and
_copy_and_swap_bytes -> _nrf24l01p_ng_copy_and_swap_bytes()
because for some boards the compilation failed because _swap_bytes was already defined.

@fabian18
Copy link
Contributor Author

Ok, looks like I am not allowed to use binary integers.

fabian18 and others added 4 commits January 24, 2021 20:49
The driver uses the netdev interface. Due to the limited
capabilities of the transceiver (32 byte FIFO and no source address in the layer2 frame),
it relies on 6LowPAN compression and adds the source address to the frame for that.
@fabian18 fabian18 force-pushed the driver-nrf24l01p-netdev-minimal branch from e83d2a3 to 7d618af Compare January 24, 2021 20:15
Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

Looks good and still works - ACK!

btw.: what would be needed to adapt this for nrf24l01 (non-plus)?
I now have a bunch of these Chips as well and would like to try that out - from a previous iteration I remember that the 32 byte fifo always needs to be filled with these - is there anything else?

Another interesting bit is that the radio of the nrf518xx/nrf528xx series claims compatibility with nrf24l01p - do you know if this is related to nrfmin?

@fabian18
Copy link
Contributor Author

The adaptations for nrf24l01 don´t seem to be so complicated. The main drawback IMO is the static payload size that must be configured equally for sender and receiver. There is a section in the nrf24l01+ datasheet (Appendix B) that tells how to set up compatibility. There they say that you also must disable auto-ACK.

I have no experience with nrf518xx/nrf528xx.

@benpicco benpicco merged commit 71fe668 into RIOT-OS:master Jan 24, 2021
@maribu
Copy link
Member

maribu commented Jan 24, 2021

🎉

@fabian18
Copy link
Contributor Author

Hurray 😃 🎊
Big thanks to you benpicco!

jia200x pushed a commit to jia200x/RIOT that referenced this pull request Mar 9, 2021
This does two things:

The documentation of `luid_get()` is wrong, or at least confusing.

It talks about

> an 8-bit incrementing counter value into the most significant byte

while the implementation does

    ((uint8_t *)buf)[0] ^= lastused++;	// 0 is LSB!

Now it could be argued that the intention was that the ID is supposed
to be used in Big Endian contexts and that was an omission, however
to keep everyone's sanity, let's keep it simple and just state that this
actually changes the LSB.

Also add a `luid_get_lb()` function that does the same, but modifies the
most significant byte - or the last byte if looking at the index.

This can then be used directly by e.g. RIOT-OS#13743
@kaspar030 kaspar030 added this to the Release 2021.04 milestone Apr 23, 2021
@kaspar030 kaspar030 added the Release notes: added Set on PRs that have been processed into the release notes for the current release. label Apr 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Release notes: added Set on PRs that have been processed into the release notes for the current release. Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants