nrf-hal icon indicating copy to clipboard operation
nrf-hal copied to clipboard

Issues with PDM_NS & I2S on nrf9160

Open Sheap opened this issue 3 years ago • 11 comments

I'm having issues when interacting with the pdm peripheral via this library. Whatever I do, it results in an error: Error: bug? LR (0xffffffb8) didn't have the Thumb bit set which I've had little luck figuring out so far.

I couldn't find any examples of how to use the pdm peripheral in this library, so it's entirely possible that I've misinterpreted something important when combining the nrf9160 documentation and the documentation of this library. I'm pretty new to embedded development in Rust, any help would be appreciated.

The "lib" referred to here is the base file from the knurling application template

#![no_main]
#![no_std]

use lib as _; // global logger + panicking-behavior + memory layout
use rtic::app;

use nrf9160_hal::gpio::Level;
use nrf9160_hal::pac::pdm_ns::RegisterBlock;
use nrf9160_hal::gpio::p0::Parts;
use nrf9160_hal::pac::Peripherals;

unsafe fn activate_pdm_module (pdm_ns: &RegisterBlock, p: Peripherals, buffer_ptr: u32, buffer_size: u16) {
    let port0 = Parts::new(p.P0_NS);

    defmt::info!("configuring pin gpio settings");
    let clk_pin = port0.p0_30.into_push_pull_output(Level::Low); // TODO is push_pull right? might not matter - I think only direction matters
    let din_pin = port0.p0_31.into_floating_input(); // TODO again, might be wrong, might not matter

    defmt::info!("enabling pdm");
    pdm_ns.enable.modify(|_, w| w.enable().set_bit());

    defmt::info!("setting clk pin");
    pdm_ns.psel.clk.modify(|_, w| {
        w.pin().bits(clk_pin.degrade().pin());
        w.connect().clear_bit()
    });
    defmt::info!("setting din pin");
    pdm_ns.psel.din.modify(|_, w| {
        w.pin().bits(din_pin.degrade().pin());
        w.connect().clear_bit()
    });

    defmt::info!("linking buffer");
    pdm_ns.sample.ptr.modify(|_, w| w.sampleptr().bits(buffer_ptr));
    pdm_ns.sample.maxcnt.modify(|_, w| w.buffsize().bits(buffer_size));

    defmt::info!("setting mono");
    pdm_ns.mode.modify(|_, w| w.operation().mono()); // TODO switch to stereo when we have more cables
}

fn start_sampling (pdm_ns: &RegisterBlock) {
    defmt::info!("starting run - waiting for stability");
    pdm_ns.tasks_start.write(|w| w.tasks_start().set_bit());
    for _ in 0..50 {
        while pdm_ns.events_end.read().events_end().bit_is_clear() {}
        pdm_ns.events_end.write(|w| w.events_end().clear_bit());
    }
}

#[app(device = nrf9160_hal)]
const APP: () = {
    #[init]
    fn init(_: init::Context) {
        defmt::info!("initializing");
        defmt::info!("getting peripherals");
        let p = Peripherals::take().unwrap();

        defmt::info!("configuring data buffer");
        let buffer = [0u16; 2048];
        let buffer_ref = &buffer;
        let buffer_raw_ptr = buffer_ref as *const u16;
        let buffer_addr = buffer_raw_ptr as u32;

        unsafe {
            defmt::info!("activating pdm");
            let pdm_ns = &*nrf9160_hal::pac::PDM_NS::ptr();
            activate_pdm_module(pdm_ns, p, buffer_addr, 1024);
            defmt::info!("initialized");

            start_sampling(pdm_ns);
            pdm_ns.tasks_stop.write(|w| w.tasks_stop().set_bit());
            while pdm_ns.events_end.read().events_end().bit_is_clear() {}
            pdm_ns.events_end.write(|w| w.events_end().clear_bit());
            defmt::info!("run finished - data: {=[?]}!", buffer);
        }
    }

    #[idle]
    fn idle(_ctx: idle::Context) -> ! {
        loop {}
    }
};
   Compiling lib v0.1.0 (***)
    Finished dev [optimized + debuginfo] target(s) in 0.47s
     Running `probe-run --chip nRF9160_xxAA target/thumbv8m.main-none-eabihf/debug/rtic`
(HOST) INFO  flashing program (8.46 KiB)
(HOST) INFO  success!
────────────────────────────────────────────────────────────────────────────────
0 INFO  initializing
└─ rtic::init @ src/bin/rtic.rs:54
1 INFO  getting peripherals
└─ rtic::init @ src/bin/rtic.rs:55
2 INFO  configuring data buffer
└─ rtic::init @ src/bin/rtic.rs:58
3 INFO  activating pdm
└─ rtic::init @ src/bin/rtic.rs:65
4 INFO  configuring pin gpio settings
└─ rtic::activate_pdm_module @ src/bin/rtic.rs:15
5 INFO  enabling pdm
└─ rtic::activate_pdm_module @ src/bin/rtic.rs:19
────────────────────────────────────────────────────────────────────────────────
Error: bug? LR (0xffffffb8) didn't have the Thumb bit set

Sheap avatar May 27 '21 07:05 Sheap

It looks like this error originates in probe-run. I have no idea whether probe-run is at fault here or if something is wrong in this HAL (or if it's something completely different), but I suggest opening an issue in the probe-run repository. At least the maintainers there might have a better idea of what could be causing this.

Have you tried running the same code without probe-run, for example using cargo embed? That could be useful in narrowing down the cause of the problem.

hannobraun avatar May 27 '21 10:05 hannobraun

I have opened https://github.com/knurling-rs/probe-run/pull/216 to fix the probe-run issue, it would be great if you could test that as I don't have any thumbv8 hardware at hand

jonas-schievink avatar May 27 '21 11:05 jonas-schievink

I'll look into testing your probe-run changes when I can.

However, I don't believe probe-run is the root cause of the issue. It seems to be handling the crash differently, but using cargo-embed doesn't get any further.

13:46:06.110 initializing
13:46:06.110 getting peripherals
13:46:06.110 configuring data buffer
13:46:06.110 activating pdm
13:46:06.110 configuring pin gpio settings
13:46:06.110 enabling pdm

and then nothing further.

Sheap avatar May 27 '21 11:05 Sheap

If the bug in probe-run is fixed, it should print a backtrace, which might help diagnose what's wrong

jonas-schievink avatar May 27 '21 11:05 jonas-schievink

replicating your changes in my local probe run simply changes the error to: Error: LR contains invalid EXC_RETURN value 0xFFFFFFB8

I don't see a backtrace

Sheap avatar May 27 '21 12:05 Sheap

Thanks for testing, I've pushed another commit to that PR that should hopefully fix this.

jonas-schievink avatar May 27 '21 13:05 jonas-schievink

Now getting:

Error: debug information is missing. Likely fixes:
1. compile the Rust code with `debug = 1` or higher. This is configured in the `profile.{release,bench}` sections of Cargo.toml (`profile.{dev,test}` default to `debug = 2`)
2. use a recent version of the `cortex-m` crates (e.g. cortex-m 0.6.3 or newer). Check versions in Cargo.lock
3. if linking to C code, compile the C code with the `-g` flag

Caused by:
    Do not have unwind info for the given address.

None of the fixes mentioned are relevant - I have debug = 2, cortex-m 0.6.7, and I don't believe there's any C code linked.

Sheap avatar May 27 '21 13:05 Sheap

To test if the issue was specific to the pdm peripheral, I bought some i2s microphones. I'm getting similar errors there. Within rtic, as soon as I call I2S::new_controller(), it crashes with the same error. Outside of rtic, it doesn't crash, but just stalls at the same point. I copied the contents of new_controller out into my own function to see where exactly it's crashing, and it's the first line.

Has anybody successfully used the i2s or pdm modules on the nrf9160?

Sheap avatar Jun 15 '21 08:06 Sheap

It looks like the root cause is in the SPM. I followed this guide, and it seems to have gotten me there.

However, this feels like a hacky solution. The SPM has been updated since then, and it looks like there are I2S0_NS and PDM0_NS already listed, and I would expect would work.

Sheap avatar Jun 16 '21 14:06 Sheap

Yay, security! Which version of SPM are you using?

jonathanpallant avatar Jun 16 '21 14:06 jonathanpallant

Assuming the version of SPM maps to the version of the nrf connect sdk: 1.5.1. It looks like what I thought was a hacky solution has actually made it into the release candidates for 1.6, so maybe it wasn't so hacky after all. It looks like everything is due to resolve itself in later versions of other repos, so we can probably close this

Sheap avatar Jun 16 '21 15:06 Sheap