embassy-rs / nrf-softdevice

Apache License 2.0
264 stars 79 forks source link

ERROR panicked at 'sd_softdevice_enable err SdmIncorrectInterruptConfiguration' #194

Closed dzervas closed 1 year ago

dzervas commented 1 year ago

I'm trying to at least get softdevice enabled but I stumble upon this panic error

I know that it's relevant to #16 and #18 but I'm not sure how to solve it. I don't use RTIC.

My target is an nrf52840 and the code about the SoftDevice is:

    info!("Starting SoftDevice BLE shit");

    let sd_config = nrf_softdevice::Config {
        clock: Some(raw::nrf_clock_lf_cfg_t {
            source: raw::NRF_CLOCK_LF_SRC_XTAL as u8,
            rc_ctiv: 0,
            rc_temp_ctiv: 0,
            accuracy: raw::NRF_CLOCK_LF_ACCURACY_20_PPM as u8,
            // rc_ctiv: 16,
            // rc_temp_ctiv: 2,
            // accuracy: raw::NRF_CLOCK_LF_ACCURACY_500_PPM as u8,
        }),
        conn_gap: Some(raw::ble_gap_conn_cfg_t {
            conn_count: 6,
            event_length: 24,
        }),
        conn_gatt: Some(raw::ble_gatt_conn_cfg_t { att_mtu: 256 }),
        gatts_attr_tab_size: Some(raw::ble_gatts_cfg_attr_tab_size_t { attr_tab_size: 32768 }),
        gap_role_count: Some(raw::ble_gap_cfg_role_count_t {
            adv_set_count: 1,
            periph_role_count: 3,
            central_role_count: 3,
            central_sec_count: 0,
            _bitfield_1: raw::ble_gap_cfg_role_count_t::new_bitfield_1(0),
        }),
        gap_device_name: Some(raw::ble_gap_cfg_device_name_t {
            p_value: b"HelloRust" as *const u8 as _,
            current_len: 9,
            max_len: 9,
            write_perm: unsafe { mem::zeroed() },
            _bitfield_1: raw::ble_gap_cfg_device_name_t::new_bitfield_1(raw::BLE_GATTS_VLOC_STACK as u8),
        }),
        ..Default::default()
    };

        // Tried that, changed nothing
    //unsafe { cortex_m::interrupt::enable(); }

    let sd = Softdevice::enable(&sd_config);

    spawner.spawn(softdevice_task(sd)).unwrap();

    info!("Starting advertisement");

    let adv_data = &[
        0x02,
        raw::BLE_GAP_AD_TYPE_FLAGS as u8,
        raw::BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE as u8,
        0x03,
        raw::BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE as u8,
        0x09,
        0x18,
        0x0a,
        raw::BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME as u8,
        b'H',
        b'e',
        b'l',
        b'l',
        b'o',
        b'R',
        b'u',
        b's',
        b't',
    ];
    #[rustfmt::skip]
    let scan_data = &[
        0x03, raw::BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE as u8, 0x09, 0x18,
    ];

    let mut config = peripheral::Config::default();
    config.interval = 50;
    let adv = peripheral::NonconnectableAdvertisement::ScannableUndirected {
        adv_data,
        scan_data,
    };
    unwrap!(peripheral::advertise(sd, adv, &config).await);

I'm almost sure that something's wrong with my features. Here are my deps and features:

[dependencies]
embassy-executor   = { version = "0.3.0", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-futures    = "0.1.0"
embassy-sync       = { version = "0.3.0" }
embassy-time       = "0.1.3"
embassy-usb        = { git = "https://github.com/embassy-rs/embassy", tag = "embassy-sync-v0.3.0", optional = true, features = ["defmt", "msos-descriptor"] }
# embassy-usb-driver = { git = "https://github.com/embassy-rs/embassy", tag = "embassy-sync-v0.3.0", optional = true, features = ["defmt"] }

embassy-rp    = { git = "https://github.com/embassy-rs/embassy", optional = true, tag = "embassy-sync-v0.3.0"}
embassy-nrf   = { git = "https://github.com/embassy-rs/embassy", optional = true, tag = "embassy-sync-v0.3.0", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"]}
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy", optional = true, tag = "embassy-sync-v0.3.0"}
# esp-hal = { version = "0.12.0", optional = true }
# TODO: Add esp-wifi and esp-hal

defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = { version = "0.3.1", features = ["defmt", "defmt-error", "print-defmt"] }
fixed = "1.24.0"
static_cell = "1.2"

# cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
cortex-m = "0.7.7"
cortex-m-rt = "0.7.3"
rand = { version = "0.8.5", default-features = false }
futures = { version = "0.3.28", default-features = false, features = ["async-await"] }

embedded-hal = { version = "0.2.7" }
embedded-hal-async = { version = "1.0.0-rc.1", optional = true }
embedded-hal-bus = { version = "0.1.0-rc.1" }

usbd-hid = "0.6.1"
embedded-alloc = "0.5.0"
usb-device = { version = "0.2.9", features = ["defmt"] }

# TODO: Needs critical-section-impl?
nrf-softdevice = { git = "https://github.com/embassy-rs/nrf-softdevice", features = ["defmt", "nrf52840", "s140", "ble-central", "ble-peripheral", "ble-l2cap", "ble-gatt-server", "ble-gatt-client", "ble-rssi", "ble-sec", "critical-section-impl" ] }
# nrf-softdevice-s140 = { git = "https://github.com/embassy-rs/nrf-softdevice" }

[features]
default = [
    "nrf",
    "nrf52840",
    "nightly",
]

# Hardware targets
rp = ["dep:embassy-rp"]
nrf = ["dep:embassy-nrf"]
stm32 = ["dep:embassy-stm32"]
nrf52840 = []
nightly = [
    "static_cell/nightly",
    "embassy-usb",
    "embedded-hal-async",
    "embassy-executor/nightly",
    "embassy-nrf/nightly",
    "nrf-softdevice/nightly"
]

Shouldn't the interrupts be enabled by default?

dzervas commented 1 year ago

Oh and the error:

INFO Starting SoftDevice BLE shit
└─ src/main.rs:179
ERROR panicked at 'sd_softdevice_enable err SdmIncorrectInterruptConfiguration'
└─ /home/dzervas/.cargo/git/checkouts/nrf-softdevice-03ef4aef10e777e4/3b08bda/nrf-softdevice/src/fmt.rs:101
ERROR panicked at /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/defmt-0.3.5/src/lib.rs:368:5:
explicit panic
└─ /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/panic-probe-0.3.1/src/lib.rs:104
DEBUG probe_rs::debug::unit_info: Found DIE, now checking for inlined functions: name=None
DEBUG probe_rs::debug::unit_info: Found DIE, now checking for inlined functions: name=None
DEBUG probe_rs::debug::unit_info: Found DIE, now checking for inlined functions: name=None
DEBUG probe_rs::debug::unit_info: Found DIE, now checking for inlined functions: name=None
DEBUG probe_rs::debug::unit_info: Found DIE, now checking for inlined functions: name=None
DEBUG probe_rs::debug::unit_info: Found DIE, now checking for inlined functions: name=None
Frame 0: div_half_u128 @ 0x00000a60
Frame 1: __udf @ 0x0004f61a inline
       ./asm/lib.rs:48:1
Frame 2: __udf @ 0x000000000004f61a
       ./asm/lib.rs:51:17
Frame 3: udf @ 0x0004f4a8
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cortex-m-0.7.7/src/asm.rs:43:5
Frame 4: hard_fault @ 0x0004f52e
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/panic-probe-0.3.1/src/lib.rs:86:5
Frame 5: panic @ 0x0004f500
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/panic-probe-0.3.1/src/lib.rs:54:9
Frame 6: panic_fmt @ 0x00050ed8
       /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/panicking.rs:72:14
Frame 7: panic_display<&str> @ 0x00050f72 inline
       /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/panicking.rs:178:5
Frame 8: panic_explicit @ 0x0000000000050f42
       /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/panicking.rs:160:5
Frame 9: panic_cold_explicit @ 0x00050bf2
       /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/panic.rs:87:13
Frame 10: default_panic @ 0x00050b4a
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/defmt-0.3.5/src/lib.rs:368:5
Frame 11: panic @ 0x000449e2 inline
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/defmt-0.3.5/src/export/mod.rs:133:14
Frame 12: <unknown function @ 0x000449e2> @ 0x00000000000449de
       /home/dzervas/.cargo/git/checkouts/nrf-softdevice-03ef4aef10e777e4/3b08bda/nrf-softdevice/src/softdevice.rs:108:25
Frame 13: {async_fn#0} @ 0x0002faaa
       /home/dzervas/Lab/clackrust/src/main.rs:216:11
Frame 14: <unknown function @ 0x000279fa> @ 0x000279fa
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.3.0/src/raw/mod.rs:161:15
Frame 15: {closure#0} @ 0x0004a59c
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.3.0/src/raw/mod.rs:411:17
Frame 16: <unknown function @ 0x00049fae> @ 0x00049fae
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.3.0/src/raw/run_queue.rs:85:13
Frame 17: <unknown function @ 0x0004a506> @ 0x0004a506
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.3.0/src/raw/mod.rs:391:13
Frame 18: <unknown function @ 0x0004a5f6> @ 0x0004a5f6
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.3.0/src/raw/mod.rs:533:6
Frame 19: <unknown function @ 0x0002dcbc> @ 0x0002dcbc
       /home/dzervas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-executor-0.3.0/src/arch/cortex_m.rs:108:21
Frame 20: __cortex_m_rt_main @ 0x000341e8
       /home/dzervas/Lab/clackrust/src/main.rs:84:1
Frame 21: __cortex_m_rt_main_trampoline @ 0x000341cc
       /home/dzervas/Lab/clackrust/src/main.rs:84:1
Frame 22: <unknown function @ 0x00027126> @ 0x00027126
Frame 23: <unknown function @ 0x00027126> @ 0x00027126
Dirbaio commented 1 year ago

this is because you've enabled some interrupt at a softdevice-reserved priority. make sure to follow https://github.com/embassy-rs/nrf-softdevice#interrupts

dzervas commented 1 year ago

Oh great, now i start missing info in the readme... :joy:

Ok so I also use the usb driver so I did the following before even enabling the hardware peripherals and did the timer and GPIOTE priority fix that you describe in the readme

Interrupt::USBD.set_priority(Priority::
Interrupt::POWER_CLOCK.set_priority(Priority::P2);

Here are all my enabled interrupts:

Interrupt 0: Enabled = true, Priority = P2
└─ src/main.rs:197
Interrupt 6: Enabled = true, Priority = P2
└─ src/main.rs:197
Interrupt 17: Enabled = true, Priority = P2
└─ src/main.rs:197
Interrupt 39: Enabled = true, Priority = P2
└─ src/main.rs:197

But I still get the exact same panic

Dirbaio commented 1 year ago

POWER_CLOCK is reserved to the softdevice. If you want to use VBUS detect must do it through the softdevice's SoC events, not directly with POWER.

dzervas commented 1 year ago

oh so the softdevice exports events instead of interrupts to be able to use such functionality can you give me an example on how to setup the nrf driver to use events?

Dirbaio commented 1 year ago

there's no example (PRs welcome!). You'd do it with this, calling the methods there when the events fire: https://docs.embassy.dev/embassy-nrf/git/nrf52840/usb/vbus_detect/struct.SoftwareVbusDetect.html

dzervas commented 1 year ago

At this point I'm too bored to do a PR but I'll come back

For now to make it work you need:

lazy_static! {
    pub static ref VBUS_DETECT: SoftwareVbusDetect = SoftwareVbusDetect::new(false, false);
}

#[task]
async fn softdevice_task(sd: &'static Softdevice) {
    info!("SoftDevice task started");
    sd.run_with_callback(|event: SocEvent| {
        info!("SoftDevice event: {:?}", event);

        match event {
            SocEvent::PowerUsbRemoved => VBUS_DETECT.detected(false),
            SocEvent::PowerUsbDetected => VBUS_DETECT.detected(true),
            SocEvent::PowerUsbPowerReady => VBUS_DETECT.ready(),
            _ => {}
        };
    }).await;
    info!("SoftDevice task finished");
}

#[embassy_executor::main]
async fn main(spawner: Spawner) {
...
    let driver = Driver::new(p.USBD, Irqs, &*VBUS_DETECT);
...
    let sd = Softdevice::enable(Default::default());

    spawner.spawn(softdevice_task(sd)).unwrap();
}

I'm omitting any code covered by the readme

aloebs29 commented 6 months ago

Thanks for sharing your solution @dzervas. For anyone in the future implementing SoftwareVbusDetect, it looks like you may need to enable these events in the soft device (can't find anything in the soft device documentation that says what their default state is).

Here's an example where those events are explicitly enabled: https://github.com/matoushybl/air-force-one/blob/9dab9a5785fb3a71890e25806152a8e5846b1d1b/bridge-fw/src/main.rs#L294-L297 And the relevant documentation (at least for my version of the soft device): https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s140.api.v7.3.0%2Fgroup___n_r_f___s_o_c___f_u_n_c_t_i_o_n_s.html&cp=5_7_4_1_2_7_2_27&anchor=gadf77ee1a740e17981163be1903a96f10