Skip to content

[embassy-net-nrf91] patch greater rx_data_len size #4098

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

Merged
merged 1 commit into from
Jul 10, 2025

Conversation

wieerwill
Copy link
Contributor

Switching from a NRF9160 MCU to the newer NRF9151 there were some changes regarding LTE connections. I used the same code on both boards.

  1. the NRF9151 switched it's logic to use the external oscillator by default; this can be changed by setting HFXOSRC to 0 and reboot. In the same step it's also recommended and verified to use hfclk_source = HfclkSource::Internal in your init config, e.g.:
    let mut peripheral_config = embassy_nrf::config::Config::default();
    peripheral_config.hfclk_source = HfclkSource::Internal;
    peripheral_config.lfclk_source = LfclkSource::InternalRC;
    let p = embassy_nrf::init(peripheral_config);
    

Except of course if you got an explicit external clock in use.

  1. starting up the modem with correct configuration leads to a endless wait state while the modem starts up. Issue covered up here was a change in the rx_control_len from uint 16 to 32. Changing this leads to usage as usual.

Tested on the NRF9160-DK and a NRF9151 testboard.

Done:

  • describe errors and solution
  • add nrf9151 feature to crate; crate can be used as is in older projects and patched for newer MCU
  • patch rx_data_length
  • assert_eq got unique error messages
  • add feature note to Readme

TODO: examples to test and add to examples folder (possibly other PR in future)

@Dirbaio
Copy link
Member

Dirbaio commented Apr 15, 2025

The modem firmware tells us the list length for rx. It would be better to just use it, instead of validating it equals 16 or 32.

This is better because

  • it doesn't require a Cargo feature
  • It'll work if in the future Nordic decides to change the list length to e.g. 42.

It'll need a small refactor to not use a fixed-length array for the rx list. Could you do that?

@wieerwill
Copy link
Contributor Author

@Dirbaio thanks for your fast reply.

I too first thought that in the code we could just remove the assert_eq but it comes with faults: a change or defect in the modem would go unnoticed; e.g. a faulty value, wrong read address or error in the unsafe access could cause greater errors later on. As the LIST_LEN is used at other parts of the code too, it could cause problems if a length is read that is not divide-able by 8/16/32.

With the feature the check is still in place.
With the assert error messages any modem change at this part is easy fixable and searchable.
Future Changes of any nRF MCU can be detected with that with ease. And if Nordic decides to change the list length again it can be added with a clear visible and separated feature too.

If you still suggest to just use the the given list length from the modem, add this comment a 🚀 and i refactor it to not use a fixed-length array.

@Dirbaio
Copy link
Member

Dirbaio commented Apr 16, 2025

Yes, we really should change it.

There's two lists:

  • For TX (ie application -> modem), we decide the length, we allocate it, we tell the modem the length and address. Code for this can use LIST_LEN and fixed-size arrays.
  • For RX (ie modem -> application), the modem decides the length and allocates it. It tells us the length and address.

Nordic's lib uses the len provided by the modem. When I initially implemented embassy-net-nrf91, I saw the RX list length seemed to be always 16 and decided to just hardcode it because it was easier.

With modem firmware 2.0.0 (available for nrf9151, not for nrf9160) they changed the list length to 32.

@Dirbaio
Copy link
Member

Dirbaio commented May 26, 2025

New version is looking good! :)

Seems something went wrong while merging/rebasing, there's now 300 commits in the PR. Could you fix that? I'd also suggest squashing it down to one commit so the previous approach doesn't show up in the git history.

@wieerwill wieerwill force-pushed the support-nrf9151-modem branch from b372056 to fb986a2 Compare June 5, 2025 04:51
@wieerwill
Copy link
Contributor Author

cleaned and squashed the PR

with those changes i can access and communicate with both the nrf9160 and nrf9151 modem (verified trough AT commands). Sadly i only get the nrf9160 to establish a connection but not the nrf9151. the nrf9151 loops endless at stack.wait_config_up(), to make up for other faults i added the timeout as the on-board modem shuts itself down after 60 seconds.

currently i can not establish a LTE/NB-IoT connection with the nrf9151 and opened a question regarding this in the Nordic DevZone: https://devzone.nordicsemi.com/f/nordic-q-a/122021/nrf9151-replaces-nrf9160-lte-not-working-any-more

Copy link
Contributor Author

@wieerwill wieerwill left a comment

Choose a reason for hiding this comment

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

General feedback and comments explaining the changes

@@ -42,6 +42,7 @@ docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/g
docserver-builder -i ./embassy-usb-synopsys-otg -o webroot/crates/embassy-usb-synopsys-otg/git.zup

docserver-builder -i ./embassy-net -o webroot/crates/embassy-net/git.zup
docserver-builder -i ./embassy-net-nrf91 -o webroot/crates/embassy-net-nrf91/git.zup
Copy link
Contributor Author

Choose a reason for hiding this comment

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

embassy net nrf91 is missing in the embassy docs. this should add it so we have a nice and up to date documentation available online

@@ -48,6 +48,8 @@ pub enum Error {
AtParseError,
/// Error parsing IP addresses.
AddrParseError,
/// Timed out waiting for network attach.
AttachTimeout,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

additionally add a optional Timeout, that if the modem connection timer (usually 60 seconds) clocks out, the modem connection process is handled gracefully and returns a readable error

@@ -66,7 +68,7 @@ pub struct Status {
/// Gateway if assigned.
pub gateway: Option<IpAddr>,
/// DNS servers if assigned.
pub dns: Vec<IpAddr, 2>,
pub dns: Vec<IpAddr, 3>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

according to docs and comments, three DNS addresses were supposed

@@ -143,13 +145,17 @@ impl<'a> Control<'a> {
.map_err(|_| Error::BufferTooSmall)?;
let _ = self.control.at_command(op, &mut buf).await;
// Ignore ERROR which means no pin required
trace!("SIM PIN configured");
} else {
trace!("No SIM PIN to send");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

more versatile log output if trace is active

const MAX_TIMEOUT: Duration = Duration::from_secs(60);

let mut elapsed = Duration::from_secs(0);
loop {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the modem attach timeout logic

assert!(shmem_len != 0);
trace!(" shmem_ptr = {}, shmem_len = {}", shmem_ptr, shmem_len);

assert!(shmem_len != 0, "shmem length must not be zero");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

return users readable error feedback

@@ -202,6 +217,8 @@ async fn new_internal<'a>(

rx_control_list: ptr::null_mut(),
rx_data_list: ptr::null_mut(),
rx_control_len: 0,
rx_data_len: 0,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

added new variable RX lengths

trace!("modem control list length: {}", rx_control_len);
trace!("modem data list length: {}", rx_data_len);
self.rx_control_len = rx_control_len;
self.rx_data_len = rx_data_len;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

get and set the RX Lengths we got from the modem

} else {
self.rx_data_len
};
for i in 0..max {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

either who is in control gets to tell the iteration length

// AT response
3 => self.handle_resp(msg),
// AT notification
4 => false,
4 => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

get some more useful tracing logs about AT notifications

@wieerwill
Copy link
Contributor Author

Hi @diondokter you were recommended to me and i saw you wrote the nrf-modem crate and did some embassy work here too. could you please take a look into this?

@diondokter
Copy link
Contributor

Hi, I've never looked at the internals of libmodem properly, so I don't have a lot of info on that front. Not sure what I can help with...

@wieerwill
Copy link
Contributor Author

Hi, I've never looked at the internals of libmodem properly, so I don't have a lot of info on that front. Not sure what I can help with...

thanks for your lightning fast reply. could you verify the changes of this PR work on a NRF9151? i got a hard time testing and figuring out the internals of the modem and NRF and only got a custom PCB instead of the DevBoard therefore i want to make sure this works and does not throw up elsewhere. especially connecting to LTE/NB-IoT Networks

@diondokter
Copy link
Contributor

I only have an nRF9160 :(
All the support for other 91-series chips in nrf-modem has been submitted by other people (but libmodem smoothes over them a lot)

@wieerwill wieerwill force-pushed the support-nrf9151-modem branch from fb986a2 to 83c9ea0 Compare June 17, 2025 05:04
Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

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

The changes look good, but I'd need to get a nrf9151 to verify it.

@lulf
Copy link
Member

lulf commented Jun 30, 2025

fyi, I got hold of an nrf9151, so I will give it a spin in the coming days.

Copy link
Member

@lulf lulf 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 got around to test it, and it works nicely on my nrf9151-dk. Nice work! I also verified it still works on my nrf9160 DK.

I left one comment regarding the timeout that I think needs to be configurable, as I had to adjust that for the attach to succeed.

trace!("waiting for attached");
// Poll every second, up to 60 seconds, then error out
const POLL_INTERVAL: Duration = Duration::from_secs(1);
const MAX_TIMEOUT: Duration = Duration::from_secs(60);
Copy link
Member

Choose a reason for hiding this comment

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

This should be configurable, maybe via some kind of config type passed when creating the context. Because in my case it can take longer than 60 secs, and I've seen some cases where it could take up to 20 minutes to attach in testing (probably some kind of rate limiting if you attach too frequently).

@Dirbaio Dirbaio force-pushed the support-nrf9151-modem branch from 00c144c to a8e905f Compare July 10, 2025 18:20
@Dirbaio
Copy link
Member

Dirbaio commented Jul 10, 2025

Thanks for the PR! I've rebased it and removed unrelated things to the main point of the PR (nrf9151)

  • Removed the attach timeout. In async Rust it's generally idiomatic to not build timeouts into things, because the user can add their own from outside with with_timeout or select.
  • Removed URC printing. It's nice to have, feel free to send it again in a separate PR. IMO we should ideally add a proper public API for it insetad of just logging it.
  • Kept only some of the extra tracing

@Dirbaio Dirbaio enabled auto-merge July 10, 2025 18:23
@Dirbaio Dirbaio added this pull request to the merge queue Jul 10, 2025
Merged via the queue into embassy-rs:main with commit c511d16 Jul 10, 2025
7 checks passed
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.

4 participants