RKTK API Docs RKTK Home Repo

rktk_drivers_nrf/softdevice/
mod.rs

1//! Drivers that needs softdevice instance.
2
3use core::mem;
4
5use nrf_softdevice::{SocEvent, Softdevice, raw};
6use rktk::utils::Channel;
7
8#[cfg(feature = "softdevice-ble")]
9pub mod ble;
10pub mod flash;
11#[cfg(feature = "softdevice-ble")]
12pub mod split;
13pub mod vbus;
14
15/// Initialize the softdevice and return the instance.
16///
17/// # Usage
18/// This function enables softdevice, but doesn't start. To start softdevice, call `start_softdevice`.
19///
20/// ```
21/// let sd = init_softdevice(...);  // <-- Get mutable reference to softdevice
22/// start_server(sd).await;         // <-- Use softdevice for function which requires mutable reference to softdevice.
23/// start_softdevice(sd).await;     // <-- Starts softdevice. This function borrows softdevice forever, so from this point, you can only use immutable reference to softdevice.
24/// get_flash(sd).await;            // <-- get_flash does not require mutable reference to softdevice, so you can use this after starting softdevice;
25/// ```
26#[allow(clippy::mut_from_ref)]
27pub fn init_softdevice(ble_gap_name: &'static str) -> &'static mut Softdevice {
28    let config = nrf_softdevice::Config {
29        clock: Some(raw::nrf_clock_lf_cfg_t {
30            source: raw::NRF_CLOCK_LF_SRC_RC as u8,
31            rc_ctiv: 16,
32            rc_temp_ctiv: 2,
33            accuracy: raw::NRF_CLOCK_LF_ACCURACY_500_PPM as u8,
34        }),
35        conn_gap: Some(raw::ble_gap_conn_cfg_t {
36            conn_count: 6,
37            event_length: 24,
38        }),
39        conn_gatt: Some(raw::ble_gatt_conn_cfg_t { att_mtu: 256 }),
40        gatts_attr_tab_size: Some(raw::ble_gatts_cfg_attr_tab_size_t {
41            attr_tab_size: raw::BLE_GATTS_ATTR_TAB_SIZE_DEFAULT,
42        }),
43        gap_role_count: Some(raw::ble_gap_cfg_role_count_t {
44            adv_set_count: 1,
45            periph_role_count: 3,
46            central_role_count: 3,
47            central_sec_count: 0,
48            _bitfield_1: raw::ble_gap_cfg_role_count_t::new_bitfield_1(0),
49        }),
50        gap_device_name: Some(raw::ble_gap_cfg_device_name_t {
51            p_value: ble_gap_name.as_ptr() as _,
52            current_len: 9,
53            max_len: 9,
54            write_perm: unsafe { mem::zeroed() },
55            _bitfield_1: raw::ble_gap_cfg_device_name_t::new_bitfield_1(
56                raw::BLE_GATTS_VLOC_STACK as u8,
57            ),
58        }),
59        conn_l2cap: Some(raw::ble_l2cap_conn_cfg_t {
60            ch_count: 1,
61            rx_mps: 247,
62            tx_mps: 247,
63            rx_queue_size: 10,
64            tx_queue_size: 10,
65        }),
66        ..Default::default()
67    };
68
69    Softdevice::enable(&config)
70}
71
72/// Starts softdevice task
73pub fn start_softdevice(spawner: embassy_executor::Spawner, sd: &'static Softdevice) {
74    spawner.spawn(softdevice_task(sd)).unwrap();
75}
76
77#[embassy_executor::task]
78async fn softdevice_task(sd: &'static Softdevice) -> ! {
79    unsafe {
80        nrf_softdevice::raw::sd_power_usbpwrrdy_enable(1);
81        nrf_softdevice::raw::sd_power_usbdetected_enable(1);
82        nrf_softdevice::raw::sd_power_usbremoved_enable(1);
83        nrf_softdevice::raw::sd_clock_hfclk_request();
84    }
85
86    sd.run_with_callback(|ev| {
87        let _ = SD_SOCEVENT_CHAN.try_send(ev);
88    })
89    .await
90}
91
92pub type SdEventChan = Channel<SocEvent, 8>;
93pub static SD_SOCEVENT_CHAN: SdEventChan = Channel::new();