summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <dirbaio@dirbaio.net>2020-09-11 02:45:54 +0200
committerDario Nieuwenhuis <dirbaio@dirbaio.net>2020-09-11 02:45:54 +0200
commit8d57c0306b0a301684851cbc802f0528c243fe80 (patch)
tree90791480b4a1ad2bf6be1d9f7dc98e0ad4542c44
parenta9ffb6eb67d2ebe4425db6a3f5be5648379ba7e4 (diff)
downloadnrf-softdevice-8d57c0306b0a301684851cbc802f0528c243fe80.zip
Add features to support all nrf chips and softdevices.
-rw-r--r--.vscode/settings.json2
-rw-r--r--Cargo.toml3
-rw-r--r--example/Cargo.toml2
-rw-r--r--example/src/bin/ble_bas_central.rs6
-rw-r--r--example/src/bin/ble_bas_peripheral.rs6
-rw-r--r--example/src/bin/ble_peripheral_gattspam.rs6
-rw-r--r--nrf-softdevice/Cargo.toml30
-rw-r--r--nrf-softdevice/src/ble/connection.rs2
-rw-r--r--nrf-softdevice/src/ble/gap.rs254
-rw-r--r--nrf-softdevice/src/ble/gap_central.rs116
-rw-r--r--nrf-softdevice/src/ble/gap_peripheral.rs155
-rw-r--r--nrf-softdevice/src/ble/mod.rs210
-rw-r--r--nrf-softdevice/src/ble/types.rs12
-rw-r--r--nrf-softdevice/src/error.rs1
-rw-r--r--nrf-softdevice/src/events.rs9
-rw-r--r--nrf-softdevice/src/interrupt.rs153
-rw-r--r--nrf-softdevice/src/lib.rs25
-rwxr-xr-xtest-build.sh65
18 files changed, 660 insertions, 397 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index c0d9016..ca67c18 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,7 @@
{
"editor.formatOnSave": true,
+ "rust-analyzer.cargo.allFeatures": false,
+ "rust-analyzer.checkOnSave.allFeatures": false,
"rust-analyzer.cargo.target": "thumbv7em-none-eabihf",
"rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.cargo.loadOutDirsFromCheck": true,
diff --git a/Cargo.toml b/Cargo.toml
index 1f02d44..4afd34b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,6 +25,9 @@ cortex-m = { git = "https://github.com/Dirbaio/cortex-m"}
panic-probe = { git = "https://github.com/knurling-rs/probe-run", branch="main" }
defmt-rtt = { git = "https://github.com/knurling-rs/defmt", branch="main" }
defmt = { git = "https://github.com/knurling-rs/defmt", branch="main" }
+nrf52810-pac = { git = "https://github.com/Dirbaio/nrf52810-pac" }
+nrf52832-pac = { git = "https://github.com/Dirbaio/nrf52832-pac" }
+nrf52833-pac = { git = "https://github.com/Dirbaio/nrf52833-pac" }
nrf52840-pac = { git = "https://github.com/Dirbaio/nrf52840-pac" }
static-executor = { git = "https://github.com/Dirbaio/static-executor" }
static-executor-cortex-m = { git = "https://github.com/Dirbaio/static-executor" }
diff --git a/example/Cargo.toml b/example/Cargo.toml
index e25c06e..268db74 100644
--- a/example/Cargo.toml
+++ b/example/Cargo.toml
@@ -21,7 +21,7 @@ defmt = "0.1.0"
defmt-rtt = "0.1.0"
panic-probe = "0.1.0"
nrf52840-hal = { version = "0.11.0" }
-nrf-softdevice = { version = "0.1.0", path = "../nrf-softdevice", features = ["defmt-trace"] }
+nrf-softdevice = { version = "0.1.0", path = "../nrf-softdevice", features = ["defmt-trace", "nrf52840", "s140", "ble-peripheral", "ble-central"] }
nrf-softdevice-s140 = { version = "0.1.1", path = "../nrf-softdevice-s140" }
static-executor = { version = "0.1.0", features=["defmt"]}
static-executor-cortex-m = { version = "0.1.0" }
diff --git a/example/src/bin/ble_bas_central.rs b/example/src/bin/ble_bas_central.rs
index f465012..31bd312 100644
--- a/example/src/bin/ble_bas_central.rs
+++ b/example/src/bin/ble_bas_central.rs
@@ -10,7 +10,7 @@ use core::mem;
use cortex_m_rt::entry;
use defmt::info;
-use nrf_softdevice::{gap, gatt_client, raw, Address, Connection, Uuid};
+use nrf_softdevice::{gap_central, gatt_client, raw, Address, Connection, Uuid};
#[static_executor::task]
async fn softdevice_task() {
@@ -76,7 +76,9 @@ async fn ble_central_task() {
0x59, 0xf9, 0xb1, 0x9c, 0x01, 0xf5,
])];
- let conn = gap::connect(addrs).await.dexpect(intern!("connect"));
+ let conn = gap_central::connect(addrs)
+ .await
+ .dexpect(intern!("connect"));
info!("connected");
let client: BatteryServiceClient = gatt_client::discover(&conn)
diff --git a/example/src/bin/ble_bas_peripheral.rs b/example/src/bin/ble_bas_peripheral.rs
index a7e5225..533f0dc 100644
--- a/example/src/bin/ble_bas_peripheral.rs
+++ b/example/src/bin/ble_bas_peripheral.rs
@@ -10,7 +10,7 @@ use core::mem;
use cortex_m_rt::entry;
use defmt::info;
-use nrf_softdevice::{raw, Error, Uuid};
+use nrf_softdevice::{gap_peripheral, raw, Error, Uuid};
#[static_executor::task]
async fn softdevice_task() {
@@ -91,8 +91,8 @@ async fn bluetooth_task() {
];
loop {
- let conn = nrf_softdevice::gap::advertise(
- nrf_softdevice::gap::ConnectableAdvertisement::ScannableUndirected {
+ let conn = gap_peripheral::advertise(
+ gap_peripheral::ConnectableAdvertisement::ScannableUndirected {
adv_data,
scan_data,
},
diff --git a/example/src/bin/ble_peripheral_gattspam.rs b/example/src/bin/ble_peripheral_gattspam.rs
index ae71012..c7d843e 100644
--- a/example/src/bin/ble_peripheral_gattspam.rs
+++ b/example/src/bin/ble_peripheral_gattspam.rs
@@ -10,7 +10,7 @@ use core::mem;
use cortex_m_rt::entry;
use defmt::info;
-use nrf_softdevice::{raw, Error, Uuid};
+use nrf_softdevice::{gap_peripheral, raw, Error, Uuid};
#[static_executor::task]
async fn softdevice_task() {
@@ -95,8 +95,8 @@ async fn bluetooth_task() {
];
loop {
- let conn = nrf_softdevice::gap::advertise(
- nrf_softdevice::gap::ConnectableAdvertisement::ScannableUndirected {
+ let conn = gap_peripheral::advertise(
+ gap_peripheral::ConnectableAdvertisement::ScannableUndirected {
adv_data,
scan_data,
},
diff --git a/nrf-softdevice/Cargo.toml b/nrf-softdevice/Cargo.toml
index 4b7a3cb..ad0b06f 100644
--- a/nrf-softdevice/Cargo.toml
+++ b/nrf-softdevice/Cargo.toml
@@ -12,13 +12,37 @@ defmt-info = []
defmt-warn = []
defmt-error = []
+nrf52810 = ["nrf52810-pac"]
+nrf52832 = ["nrf52832-pac"]
+nrf52833 = ["nrf52833-pac"]
+nrf52840 = ["nrf52840-pac"]
+
+s112 = ["nrf-softdevice-s112"]
+s113 = ["nrf-softdevice-s113"]
+s122 = ["nrf-softdevice-s122"]
+s132 = ["nrf-softdevice-s132"]
+s140 = ["nrf-softdevice-s140"]
+
+ble-peripheral = []
+ble-central = []
+ble-l2cap = []
+
[dependencies]
num_enum = { version = "0.5.1", default-features = false }
async-flash = { version = "0.1.0", path = "../async-flash" }
-nrf-softdevice-s140 = { version = "0.1.1", path = "../nrf-softdevice-s140" }
cortex-m = "0.6.2"
cortex-m-rt = "0.6.12"
bare-metal = { version = "0.2.0", features = ["const-fn"] }
-nrf52840-pac = { version = "0.9.0", features = ["rt"] }
heapless = "0.5.5"
-defmt = "0.1.0" \ No newline at end of file
+defmt = "0.1.0"
+
+nrf52810-pac = { version = "0.9.0", features = ["rt"], optional = true }
+nrf52832-pac = { version = "0.9.0", features = ["rt"], optional = true }
+nrf52833-pac = { version = "0.9.0", features = ["rt"], optional = true }
+nrf52840-pac = { version = "0.9.0", features = ["rt"], optional = true }
+
+nrf-softdevice-s112 = { version = "0.1.1", path = "../nrf-softdevice-s112", optional = true }
+nrf-softdevice-s113 = { version = "0.1.1", path = "../nrf-softdevice-s113", optional = true }
+nrf-softdevice-s122 = { version = "0.1.1", path = "../nrf-softdevice-s122", optional = true }
+nrf-softdevice-s132 = { version = "0.1.1", path = "../nrf-softdevice-s132", optional = true }
+nrf-softdevice-s140 = { version = "0.1.1", path = "../nrf-softdevice-s140", optional = true }
diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs
index 4325961..8e51bba 100644
--- a/nrf-softdevice/src/ble/connection.rs
+++ b/nrf-softdevice/src/ble/connection.rs
@@ -46,7 +46,7 @@ impl ConnectionState {
refcount: Cell::new(0),
conn_handle: Cell::new(None),
disconnecting: Cell::new(false),
- role: Cell::new(Role::Central),
+ role: Cell::new(Role::whatever()),
gattc_portal: Portal::new(),
}
}
diff --git a/nrf-softdevice/src/ble/gap.rs b/nrf-softdevice/src/ble/gap.rs
index f3efc13..3bd9894 100644
--- a/nrf-softdevice/src/ble/gap.rs
+++ b/nrf-softdevice/src/ble/gap.rs
@@ -19,8 +19,10 @@ pub(crate) unsafe fn on_connected(_ble_evt: *const raw::ble_evt_t, gap_evt: &raw
state.role.set(role);
match role {
- Role::Central => CONNECT_SIGNAL.signal(Ok(conn)),
- Role::Peripheral => ADV_SIGNAL.signal(Ok(conn)),
+ #[cfg(feature = "ble-central")]
+ Role::Central => crate::gap_central::CONNECT_SIGNAL.signal(Ok(conn)),
+ #[cfg(feature = "ble-peripheral")]
+ Role::Peripheral => crate::gap_peripheral::ADV_SIGNAL.signal(Ok(conn)),
}
}
@@ -45,12 +47,6 @@ pub(crate) unsafe fn on_sec_params_request(
) {
}
-pub(crate) unsafe fn on_sec_info_request(
- _ble_evt: *const raw::ble_evt_t,
- _gap_evt: &raw::ble_gap_evt_t,
-) {
-}
-
pub(crate) unsafe fn on_passkey_display(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
@@ -89,8 +85,10 @@ pub(crate) unsafe fn on_conn_sec_update(
pub(crate) unsafe fn on_timeout(_ble_evt: *const raw::ble_evt_t, gap_evt: &raw::ble_gap_evt_t) {
let params = &gap_evt.params.timeout;
match params.src as u32 {
- raw::BLE_GAP_TIMEOUT_SRC_CONN => CONNECT_SIGNAL.signal(Err(ConnectError::Stopped)),
- x => warn!("unknown timeout src {:u32}", x),
+ #[cfg(feature = "ble-central")]
+ raw::BLE_GAP_TIMEOUT_SRC_CONN => crate::gap_central::CONNECT_SIGNAL
+ .signal(Err(crate::gap_central::ConnectError::Stopped)),
+ x => depanic!("unknown timeout src {:u32}", x),
}
}
@@ -100,27 +98,12 @@ pub(crate) unsafe fn on_rssi_changed(
) {
}
-pub(crate) unsafe fn on_adv_report(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) {
-}
-
pub(crate) unsafe fn on_sec_request(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
) {
}
-pub(crate) unsafe fn on_conn_param_update_request(
- _ble_evt: *const raw::ble_evt_t,
- _gap_evt: &raw::ble_gap_evt_t,
-) {
-}
-
-pub(crate) unsafe fn on_scan_req_report(
- _ble_evt: *const raw::ble_evt_t,
- _gap_evt: &raw::ble_gap_evt_t,
-) {
-}
-
pub(crate) unsafe fn on_phy_update_request(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
@@ -130,233 +113,16 @@ pub(crate) unsafe fn on_phy_update_request(
pub(crate) unsafe fn on_phy_update(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) {
}
+#[cfg(any(feature = "s113", feature = "s132", feature = "s140"))]
pub(crate) unsafe fn on_data_length_update_request(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
) {
}
+#[cfg(any(feature = "s113", feature = "s132", feature = "s140"))]
pub(crate) unsafe fn on_data_length_update(
_ble_evt: *const raw::ble_evt_t,
_gap_evt: &raw::ble_gap_evt_t,
) {
}
-
-pub(crate) unsafe fn on_qos_channel_survey_report(
- _ble_evt: *const raw::ble_evt_t,
- _gap_evt: &raw::ble_gap_evt_t,
-) {
-}
-
-pub(crate) unsafe fn on_adv_set_terminated(
- _ble_evt: *const raw::ble_evt_t,
- _gap_evt: &raw::ble_gap_evt_t,
-) {
- ADV_SIGNAL.signal(Err(AdvertiseError::Stopped))
-}
-
-pub enum ConnectableAdvertisement<'a> {
- ScannableUndirected {
- adv_data: &'a [u8],
- scan_data: &'a [u8],
- },
- NonscannableDirected {
- scan_data: &'a [u8],
- },
- NonscannableDirectedHighDuty {
- scan_data: &'a [u8],
- },
- ExtendedNonscannableUndirected {
- adv_data: &'a [u8],
- },
- ExtendedNonscannableDirected {
- adv_data: &'a [u8],
- },
-}
-
-enum NonconnectableAdvertisement {
- ScannableUndirected,
- NonscannableUndirected,
- ExtendedScannableUndirected,
- ExtendedScannableDirected,
- ExtendedNonscannableUndirected,
- ExtendedNonscannableDirected,
-}
-
-static mut ADV_HANDLE: u8 = raw::BLE_GAP_ADV_SET_HANDLE_NOT_SET as u8;
-
-#[derive(defmt::Format)]
-pub enum AdvertiseError {
- Stopped,
- Raw(Error),
-}
-
-impl From<Error> for AdvertiseError {
- fn from(err: Error) -> Self {
- AdvertiseError::Raw(err)
- }
-}
-
-pub async fn advertise(adv: ConnectableAdvertisement<'_>) -> Result<Connection, AdvertiseError> {
- // TODO make these configurable, only the right params based on type?
- let mut adv_params: raw::ble_gap_adv_params_t = unsafe { mem::zeroed() };
- adv_params.properties.type_ = raw::BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED as u8;
- adv_params.primary_phy = raw::BLE_GAP_PHY_1MBPS as u8;
- adv_params.secondary_phy = raw::BLE_GAP_PHY_1MBPS as u8;
- adv_params.duration = raw::BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED as u16;
- adv_params.interval = 100;
-
- let (adv_data, scan_data) = match adv {
- ConnectableAdvertisement::ScannableUndirected {
- adv_data,
- scan_data,
- } => (Some(adv_data), Some(scan_data)),
- ConnectableAdvertisement::NonscannableDirected { scan_data } => (None, Some(scan_data)),
- ConnectableAdvertisement::NonscannableDirectedHighDuty { scan_data } => {
- (None, Some(scan_data))
- }
- ConnectableAdvertisement::ExtendedNonscannableUndirected { adv_data } => {
- (Some(adv_data), None)
- }
- ConnectableAdvertisement::ExtendedNonscannableDirected { adv_data } => {
- (Some(adv_data), None)
- }
- };
-
- let map_data = |data: Option<&[u8]>| {
- if let Some(data) = data {
- assert!(data.len() < u16::MAX as usize);
- raw::ble_data_t {
- p_data: data.as_ptr() as _,
- len: data.len() as u16,
- }
- } else {
- raw::ble_data_t {
- p_data: ptr::null_mut(),
- len: 0,
- }
- }
- };
-
- let datas = raw::ble_gap_adv_data_t {
- adv_data: map_data(adv_data),
- scan_rsp_data: map_data(scan_data),
- };
-
- let ret = unsafe {
- raw::sd_ble_gap_adv_set_configure(&mut ADV_HANDLE as _, &datas as _, &adv_params as _)
- };
- Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_set_configure"))?;
-
- let ret = unsafe { raw::sd_ble_gap_adv_start(ADV_HANDLE, 1 as u8) };
- Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_start"))?;
-
- // TODO handle future drop
-
- info!("Advertising started!");
-
- // The advertising data needs to be kept alive for the entire duration of the advertising procedure.
-
- ADV_SIGNAL.wait().await
-}
-
-static ADV_SIGNAL: Signal<Result<Connection, AdvertiseError>> = Signal::new();
-
-#[derive(defmt::Format)]
-pub enum AdvertiseStopError {
- NotRunning,
- Raw(Error),
-}
-
-impl From<Error> for AdvertiseStopError {
- fn from(err: Error) -> Self {
- AdvertiseStopError::Raw(err)
- }
-}
-
-pub fn advertise_stop() -> Result<(), AdvertiseStopError> {
- let ret = unsafe { raw::sd_ble_gap_adv_stop(ADV_HANDLE) };
- match Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_stop")) {
- Ok(()) => Ok(()),
- Err(Error::InvalidState) => Err(AdvertiseStopError::NotRunning),
- Err(e) => Err(e.into()),
- }
-}
-
-#[derive(defmt::Format)]
-pub enum ConnectError {
- Stopped,
- Raw(Error),
-}
-
-impl From<Error> for ConnectError {
- fn from(err: Error) -> Self {
- ConnectError::Raw(err)
- }
-}
-
-static CONNECT_SIGNAL: Signal<Result<Connection, ConnectError>> = Signal::new();
-
-pub async fn connect(whitelist: &[Address]) -> Result<Connection, ConnectError> {
- let (addr, fp) = match whitelist.len() {
- 0 => depanic!("zero-length whitelist"),
- 1 => (
- &whitelist[0] as *const Address as *const raw::ble_gap_addr_t,
- raw::BLE_GAP_SCAN_FP_ACCEPT_ALL as u8,
- ),
- _ => depanic!("todo"),
- };
-
- // TODO make configurable
- let mut scan_params: raw::ble_gap_scan_params_t = unsafe { mem::zeroed() };
- scan_params.set_extended(1);
- scan_params.set_active(1);
- scan_params.scan_phys = raw::BLE_GAP_PHY_1MBPS as u8;
- scan_params.interval = 2732;
- scan_params.window = 500;
- scan_params.set_filter_policy(fp);
- scan_params.timeout = 123;
-
- // TODO make configurable
- let mut conn_params: raw::ble_gap_conn_params_t = unsafe { mem::zeroed() };
- conn_params.min_conn_interval = 50;
- conn_params.max_conn_interval = 200;
- conn_params.slave_latency = 4;
- conn_params.conn_sup_timeout = 400; // 4 s
-
- let ret = unsafe { raw::sd_ble_gap_connect(addr, &mut scan_params, &mut conn_params, 1) };
- match Error::convert(ret) {
- Ok(()) => {}
- Err(err) => {
- warn!("sd_ble_gap_connect err {:?}", err);
- return Err(ConnectError::Raw(err));
- }
- }
-
- info!("connect started");
-
- // TODO handle future drop
-
- CONNECT_SIGNAL.wait().await
-}
-
-#[derive(defmt::Format)]
-pub enum ConnectStopError {
- NotRunning,
- Raw(Error),
-}
-
-impl From<Error> for ConnectStopError {
- fn from(err: Error) -> Self {
- ConnectStopError::Raw(err)
- }
-}
-
-pub fn connect_stop() -> Result<(), ConnectStopError> {
- let ret = unsafe { raw::sd_ble_gap_connect_cancel() };
- match Error::convert(ret).dewarn(intern!("sd_ble_gap_connect_cancel")) {
- Ok(()) => Ok(()),
- Err(Error::InvalidState) => Err(ConnectStopError::NotRunning),
- Err(e) => Err(e.into()),
- }
-}
diff --git a/nrf-softdevice/src/ble/gap_central.rs b/nrf-softdevice/src/ble/gap_central.rs
new file mode 100644
index 0000000..3b38ff6
--- /dev/null
+++ b/nrf-softdevice/src/ble/gap_central.rs
@@ -0,0 +1,116 @@
+use core::mem;
+use core::ptr;
+
+use crate::ble::types::*;
+use crate::error::Error;
+use crate::raw;
+use crate::util::*;
+use crate::{Connection, ConnectionState, Role};
+
+
+pub(crate) unsafe fn on_adv_report(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) {
+}
+
+pub(crate) unsafe fn on_qos_channel_survey_report(
+ _ble_evt: *const raw::ble_evt_t,
+ _gap_evt: &raw::ble_gap_evt_t,
+) {
+}
+
+pub(crate) unsafe fn on_conn_param_update_request(
+ _ble_evt: *const raw::ble_evt_t,
+ _gap_evt: &raw::ble_gap_evt_t,
+) {
+}
+
+#[derive(defmt::Format)]
+pub enum ConnectError {
+ Stopped,
+ Raw(Error),
+}
+
+impl From<Error> for ConnectError {
+ fn from(err: Error) -> Self {
+ ConnectError::Raw(err)
+ }
+}
+
+pub(crate) static CONNECT_SIGNAL: Signal<Result<Connection, ConnectError>> = Signal::new();
+
+pub async fn connect(whitelist: &[Address]) -> Result<Connection, ConnectError> {
+ let (addr, fp) = match whitelist.len() {
+ 0 => depanic!("zero-length whitelist"),
+ 1 => (
+ &whitelist[0] as *const Address as *const raw::ble_gap_addr_t,
+ raw::BLE_GAP_SCAN_FP_ACCEPT_ALL as u8,
+ ),
+ _ => depanic!("todo"),
+ };
+
+ // in units of 625us
+ let scan_interval: u32 = 2732;
+ let scan_window: u32 = 500;
+
+ // TODO make configurable
+ let mut scan_params: raw::ble_gap_scan_params_t = unsafe { mem::zeroed() };
+ scan_params.set_extended(1);
+ scan_params.set_active(1);
+ scan_params.scan_phys = raw::BLE_GAP_PHY_1MBPS as u8;
+ scan_params.set_filter_policy(fp);
+ scan_params.timeout = 123;
+
+ // s122 has these in us instead of 625us :shrug:
+ #[cfg(not(feature="s122"))]
+ {
+ scan_params.interval = scan_interval as u16;
+ scan_params.window = scan_interval as u16;
+ }
+ #[cfg(feature="s122")]
+ {
+ scan_params.interval_us = scan_interval * 625;
+ scan_params.window_us = scan_interval * 625;
+ }
+
+ // TODO make configurable
+ let mut conn_params: raw::ble_gap_conn_params_t = unsafe { mem::zeroed() };
+ conn_params.min_conn_interval = 50;
+ conn_params.max_conn_interval = 200;
+ conn_params.slave_latency = 4;
+ conn_params.conn_sup_timeout = 400; // 4 s
+
+ let ret = unsafe { raw::sd_ble_gap_connect(addr, &mut scan_params, &mut conn_params, 1) };
+ match Error::convert(ret) {
+ Ok(()) => {}
+ Err(err) => {
+ warn!("sd_ble_gap_connect err {:?}", err);
+ return Err(ConnectError::Raw(err));
+ }
+ }
+
+ info!("connect started");
+
+ // TODO handle future drop
+
+ CONNECT_SIGNAL.wait().await
+}
+
+#[derive(defmt::Format)]
+pub enum ConnectStopError {
+ NotRunning,
+ Raw(Error),
+}
+
+impl From<Error> for ConnectStopError {
+ fn from(err: Error) -> Self {
+ ConnectStopError::Raw(err)
+ }
+}
+
+pub fn connect_stop() -> Result<(), ConnectStopError> {
+ let ret = unsafe { raw::sd_ble_gap_connect_cancel() };
+ match Error::convert(ret).dewarn(intern!("sd_ble_gap_connect_cancel")) {
+ Ok(()) => Ok(()),
+ Err(Error::InvalidState) => Err(ConnectStopError::NotRunning),
+ Err(e) => Err(e.into()),
+ }
+}
diff --git a/nrf-softdevice/src/ble/gap_peripheral.rs b/nrf-softdevice/src/ble/gap_peripheral.rs
new file mode 100644
index 0000000..bd05dbb
--- /dev/null
+++ b/nrf-softdevice/src/ble/gap_peripheral.rs
@@ -0,0 +1,155 @@
+use core::mem;
+use core::ptr;
+
+use crate::ble::types::*;
+use crate::error::Error;
+use crate::raw;
+use crate::util::*;
+use crate::{Connection, ConnectionState, Role};
+
+pub(crate) unsafe fn on_adv_set_terminated(
+ _ble_evt: *const raw::ble_evt_t,
+ _gap_evt: &raw::ble_gap_evt_t,
+) {
+ ADV_SIGNAL.signal(Err(AdvertiseError::Stopped))
+}
+
+pub(crate) unsafe fn on_scan_req_report(
+ _ble_evt: *const raw::ble_evt_t,
+ _gap_evt: &raw::ble_gap_evt_t,
+) {
+}
+
+pub(crate) unsafe fn on_sec_info_request(
+ _ble_evt: *const raw::ble_evt_t,
+ _gap_evt: &raw::ble_gap_evt_t,
+) {
+}
+
+pub enum ConnectableAdvertisement<'a> {
+ ScannableUndirected {
+ adv_data: &'a [u8],
+ scan_data: &'a [u8],
+ },
+ NonscannableDirected {
+ scan_data: &'a [u8],
+ },
+ NonscannableDirectedHighDuty {
+ scan_data: &'a [u8],
+ },
+ ExtendedNonscannableUndirected {
+ adv_data: &'a [u8],
+ },
+ ExtendedNonscannableDirected {
+ adv_data: &'a [u8],
+ },
+}
+
+enum NonconnectableAdvertisement {
+ ScannableUndirected,
+ NonscannableUndirected,
+ ExtendedScannableUndirected,
+ ExtendedScannableDirected,
+ ExtendedNonscannableUndirected,
+ ExtendedNonscannableDirected,
+}
+
+static mut ADV_HANDLE: u8 = raw::BLE_GAP_ADV_SET_HANDLE_NOT_SET as u8;
+
+#[derive(defmt::Format)]
+pub enum AdvertiseError {
+ Stopped,
+ Raw(Error),
+}
+
+impl From<Error> for AdvertiseError {
+ fn from(err: Error) -> Self {
+ AdvertiseError::Raw(err)
+ }
+}
+
+pub async fn advertise(adv: ConnectableAdvertisement<'_>) -> Result<Connection, AdvertiseError> {
+ // TODO make these configurable, only the right params based on type?
+ let mut adv_params: raw::ble_gap_adv_params_t = unsafe { mem::zeroed() };
+ adv_params.properties.type_ = raw::BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED as u8;
+ adv_params.primary_phy = raw::BLE_GAP_PHY_1MBPS as u8;
+ adv_params.secondary_phy = raw::BLE_GAP_PHY_1MBPS as u8;
+ adv_params.duration = raw::BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED as u16;
+ adv_params.interval = 100;
+
+ let (adv_data, scan_data) = match adv {
+ ConnectableAdvertisement::ScannableUndirected {
+ adv_data,
+ scan_data,
+ } => (Some(adv_data), Some(scan_data)),
+ ConnectableAdvertisement::NonscannableDirected { scan_data } => (None, Some(scan_data)),
+ ConnectableAdvertisement::NonscannableDirectedHighDuty { scan_data } => {
+ (None, Some(scan_data))
+ }
+ ConnectableAdvertisement::ExtendedNonscannableUndirected { adv_data } => {
+ (Some(adv_data), None)
+ }
+ ConnectableAdvertisement::ExtendedNonscannableDirected { adv_data } => {
+ (Some(adv_data), None)
+ }
+ };
+
+ let map_data = |data: Option<&[u8]>| {
+ if let Some(data) = data {
+ assert!(data.len() < u16::MAX as usize);
+ raw::ble_data_t {
+ p_data: data.as_ptr() as _,
+ len: data.len() as u16,
+ }
+ } else {
+ raw::ble_data_t {
+ p_data: ptr::null_mut(),
+ len: 0,
+ }
+ }
+ };
+
+ let datas = raw::ble_gap_adv_data_t {
+ adv_data: map_data(adv_data),
+ scan_rsp_data: map_data(scan_data),
+ };
+
+ let ret = unsafe {
+ raw::sd_ble_gap_adv_set_configure(&mut ADV_HANDLE as _, &datas as _, &adv_params as _)
+ };
+ Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_set_configure"))?;
+
+ let ret = unsafe { raw::sd_ble_gap_adv_start(ADV_HANDLE, 1 as u8) };
+ Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_start"))?;
+
+ // TODO handle future drop
+
+ info!("Advertising started!");
+
+ // The advertising data needs to be kept alive for the entire duration of the advertising procedure.
+
+ ADV_SIGNAL.wait().await
+}
+
+pub(crate) static ADV_SIGNAL: Signal<Result<Connection, AdvertiseError>> = Signal::new();
+
+#[derive(defmt::Format)]
+pub enum AdvertiseStopError {
+ NotRunning,
+ Raw(Error),
+}
+
+impl From<Error> for AdvertiseStopError {
+ fn from(err: Error) -> Self {
+ AdvertiseStopError::Raw(err)
+ }
+}
+
+pub fn advertise_stop() -> Result<(), AdvertiseStopError> {
+ let ret = unsafe { raw::sd_ble_gap_adv_stop(ADV_HANDLE) };
+ match Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_stop")) {
+ Ok(()) => Ok(()),
+ Err(Error::InvalidState) => Err(AdvertiseStopError::NotRunning),
+ Err(e) => Err(e.into()),
+ }
+}
diff --git a/nrf-softdevice/src/ble/mod.rs b/nrf-softdevice/src/ble/mod.rs
index df02d51..604ce24 100644
--- a/nrf-softdevice/src/ble/mod.rs
+++ b/nrf-softdevice/src/ble/mod.rs
@@ -7,141 +7,99 @@ mod types;
pub use types::*;
pub mod gap;
+#[cfg(feature = "ble-central")]
+pub mod gap_central;
+#[cfg(feature = "ble-peripheral")]
+pub mod gap_peripheral;
pub mod gatt_client;
pub mod gatt_server;
+
+#[cfg(feature = "ble-l2cap")]
pub mod l2cap;
fn on_user_mem_request(_ble_evt: *const raw::ble_evt_t, _common_evt: &raw::ble_common_evt_t) {}
fn on_user_mem_release(_ble_evt: *const raw::ble_evt_t, _common_evt: &raw::ble_common_evt_t) {}
-macro_rules! match_event {
- ($evt_ptr:ident, $($id:ident => $func:path[$field:ident]),* $(,)? ) => {
- let evt = &*$evt_ptr;
- defmt::trace!("ble evt {:istr}", evt_str(evt.header.evt_id as u32));
- match evt.header.evt_id as u32 {
- $(raw::$id => $func($evt_ptr, get_union_field($evt_ptr, &evt.evt.$field)) ),* ,
- x => depanic!("Unknown ble evt {:u32}", x),
- }
- };
-}
-
#[rustfmt::skip]
-pub(crate) unsafe fn on_evt(evt_ptr: *const raw::ble_evt_t) {
- match_event!(evt_ptr,
- BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST => on_user_mem_request[common_evt],
- BLE_COMMON_EVTS_BLE_EVT_USER_MEM_RELEASE => on_user_mem_release[common_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED => gap::on_connected[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => gap::on_disconnected[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => gap::on_conn_param_update[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_SEC_PARAMS_REQUEST => gap::on_sec_params_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_SEC_INFO_REQUEST => gap::on_sec_info_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_PASSKEY_DISPLAY => gap::on_passkey_display[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_KEY_PRESSED => gap::on_key_pressed[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_KEY_REQUEST => gap::on_auth_key_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_LESC_DHKEY_REQUEST => gap::on_lesc_dhkey_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_STATUS => gap::on_auth_status[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_CONN_SEC_UPDATE => gap::on_conn_sec_update[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => gap::on_timeout[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_RSSI_CHANGED => gap::on_rssi_changed[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_ADV_REPORT => gap::on_adv_report[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_SEC_REQUEST => gap::on_sec_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST => gap::on_conn_param_update_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_SCAN_REQ_REPORT => gap::on_scan_req_report[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE_REQUEST => gap::on_phy_update_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE => gap::on_phy_update[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST => gap::on_data_length_update_request[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE => gap::on_data_length_update[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT => gap::on_qos_channel_survey_report[gap_evt],
- BLE_GAP_EVTS_BLE_GAP_EVT_ADV_SET_TERMINATED => gap::on_adv_set_terminated[gap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REQUEST => l2cap::on_ch_setup_request[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REFUSED => l2cap::on_ch_setup_refused[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP => l2cap::on_ch_setup[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RELEASED => l2cap::on_ch_released[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED => l2cap::on_ch_sdu_buf_released[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_CREDIT => l2cap::on_ch_credit[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RX => l2cap::on_ch_rx[l2cap_evt],
- BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_TX => l2cap::on_ch_tx[l2cap_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => gatt_client::on_prim_srvc_disc_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_REL_DISC_RSP => gatt_client::on_rel_disc_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => gatt_client::on_char_disc_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => gatt_client::on_desc_disc_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_ATTR_INFO_DISC_RSP => gatt_client::on_attr_info_disc_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP => gatt_client::on_char_val_by_uuid_read_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => gatt_client::on_read_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VALS_READ_RSP => gatt_client::on_char_vals_read_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => gatt_client::on_write_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_HVX => gatt_client::on_hvx[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => gatt_client::on_exchange_mtu_rsp[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => gatt_client::on_timeout[gattc_evt],
- BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => gatt_client::on_write_cmd_tx_complete[gattc_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_WRITE => gatt_server::on_write[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST => gatt_server::on_rw_authorize_request[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_SYS_ATTR_MISSING => gatt_server::on_sys_attr_missing[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_HVC => gatt_server::on_hvc[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_SC_CONFIRM => gatt_server::on_sc_confirm[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST => gatt_server::on_exchange_mtu_request[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT => gatt_server::on_timeout[gatts_evt],
- BLE_GATTS_EVTS_BLE_GATTS_EVT_HVN_TX_COMPLETE => gatt_server::on_hvn_tx_complete[gatts_evt],
- );
-}
+pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) {
+ let evt = &*ble_evt;
+ //defmt::trace!("ble evt {:istr}", evt_str(evt.header.evt_id as u32));
+ match evt.header.evt_id as u32 {
+ raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST => on_user_mem_request(ble_evt, get_union_field(ble_evt, &evt.evt.common_evt)),
+ raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_RELEASE => on_user_mem_release(ble_evt, get_union_field(ble_evt, &evt.evt.common_evt)),
+
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED => gap::on_connected(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => gap::on_disconnected(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => gap::on_conn_param_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_PARAMS_REQUEST => gap::on_sec_params_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(feature="ble-peripheral")]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_INFO_REQUEST => gap_peripheral::on_sec_info_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_PASSKEY_DISPLAY => gap::on_passkey_display(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_KEY_PRESSED => gap::on_key_pressed(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_KEY_REQUEST => gap::on_auth_key_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_LESC_DHKEY_REQUEST => gap::on_lesc_dhkey_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_STATUS => gap::on_auth_status(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_SEC_UPDATE => gap::on_conn_sec_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => gap::on_timeout(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_RSSI_CHANGED => gap::on_rssi_changed(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(feature="ble-central")]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_REPORT => gap_central::on_adv_report(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_REQUEST => gap::on_sec_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(feature="ble-central")]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST => gap_central::on_conn_param_update_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(feature="ble-peripheral")]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_SCAN_REQ_REPORT => gap_peripheral::on_scan_req_report(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE_REQUEST => gap::on_phy_update_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE => gap::on_phy_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(any(feature="s113", feature="s132", feature="s140"))]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST => gap::on_data_length_update_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(any(feature="s113", feature="s132", feature="s140"))]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE => gap::on_data_length_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(feature="ble-central")]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT => gap_central::on_qos_channel_survey_report(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+ #[cfg(feature="ble-peripheral")]
+ raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_SET_TERMINATED => gap_peripheral::on_adv_set_terminated(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)),
+
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REQUEST => l2cap::on_ch_setup_request(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REFUSED => l2cap::on_ch_setup_refused(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP => l2cap::on_ch_setup(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RELEASED => l2cap::on_ch_released(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED => l2cap::on_ch_sdu_buf_released(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_CREDIT => l2cap::on_ch_credit(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RX => l2cap::on_ch_rx(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+ #[cfg(feature="ble-l2cap")]
+ raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_TX => l2cap::on_ch_tx(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)),
+
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => gatt_client::on_prim_srvc_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_REL_DISC_RSP => gatt_client::on_rel_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => gatt_client::on_char_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => gatt_client::on_desc_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_ATTR_INFO_DISC_RSP => gatt_client::on_attr_info_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP => gatt_client::on_char_val_by_uuid_read_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => gatt_client::on_read_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VALS_READ_RSP => gatt_client::on_char_vals_read_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => gatt_client::on_write_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_HVX => gatt_client::on_hvx(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => gatt_client::on_exchange_mtu_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => gatt_client::on_timeout(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+ raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => gatt_client::on_write_cmd_tx_complete(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)),
+
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_WRITE => gatt_server::on_write(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST => gatt_server::on_rw_authorize_request(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SYS_ATTR_MISSING => gatt_server::on_sys_attr_missing(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVC => gatt_server::on_hvc(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SC_CONFIRM => gatt_server::on_sc_confirm(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST => gatt_server::on_exchange_mtu_request(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT => gatt_server::on_timeout(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
+ raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVN_TX_COMPLETE => gatt_server::on_hvn_tx_complete(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)),
-#[rustfmt::skip]
-fn evt_str(evt: u32) -> defmt::Str {
- match evt {
- raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST => defmt::intern!("USER_MEM_REQUEST"),
- raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_RELEASE => defmt::intern!("USER_MEM_RELEASE"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED => defmt::intern!("GAP CONNECTED"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => defmt::intern!("GAP DISCONNECTED"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => defmt::intern!("GAP CONN_PARAM_UPDATE"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_PARAMS_REQUEST => defmt::intern!("GAP SEC_PARAMS_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_INFO_REQUEST => defmt::intern!("GAP SEC_INFO_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_PASSKEY_DISPLAY => defmt::intern!("GAP PASSKEY_DISPLAY"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_KEY_PRESSED => defmt::intern!("GAP KEY_PRESSED"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_KEY_REQUEST => defmt::intern!("GAP AUTH_KEY_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_LESC_DHKEY_REQUEST => defmt::intern!("GAP LESC_DHKEY_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_STATUS => defmt::intern!("GAP AUTH_STATUS"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_SEC_UPDATE => defmt::intern!("GAP CONN_SEC_UPDATE"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => defmt::intern!("GAP TIMEOUT"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_RSSI_CHANGED => defmt::intern!("GAP RSSI_CHANGED"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_REPORT => defmt::intern!("GAP ADV_REPORT"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_REQUEST => defmt::intern!("GAP SEC_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST => defmt::intern!("GAP CONN_PARAM_UPDATE_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_SCAN_REQ_REPORT => defmt::intern!("GAP SCAN_REQ_REPORT"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE_REQUEST => defmt::intern!("GAP PHY_UPDATE_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE => defmt::intern!("GAP PHY_UPDATE"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST => defmt::intern!("GAP DATA_LENGTH_UPDATE_REQUEST"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE => defmt::intern!("GAP DATA_LENGTH_UPDATE"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT => defmt::intern!("GAP QOS_CHANNEL_SURVEY_REPORT"),
- raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_SET_TERMINATED => defmt::intern!("GAP ADV_SET_TERMINATED"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REQUEST => defmt::intern!("L2CAP CH_SETUP_REQUEST"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REFUSED => defmt::intern!("L2CAP CH_SETUP_REFUSED"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP => defmt::intern!("L2CAP CH_SETUP"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RELEASED => defmt::intern!("L2CAP CH_RELEASED"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED => defmt::intern!("L2CAP CH_SDU_BUF_RELEASED"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_CREDIT => defmt::intern!("L2CAP CH_CREDIT"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RX => defmt::intern!("L2CAP CH_RX"),
- raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_TX => defmt::intern!("L2CAP CH_TX"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => defmt::intern!("GATTC PRIM_SRVC_DISC_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_REL_DISC_RSP => defmt::intern!("GATTC REL_DISC_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => defmt::intern!("GATTC CHAR_DISC_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => defmt::intern!("GATTC DESC_DISC_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_ATTR_INFO_DISC_RSP => defmt::intern!("GATTC ATTR_INFO_DISC_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP => defmt::intern!("GATTC CHAR_VAL_BY_UUID_READ_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => defmt::intern!("GATTC READ_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VALS_READ_RSP => defmt::intern!("GATTC CHAR_VALS_READ_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => defmt::intern!("GATTC WRITE_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_HVX => defmt::intern!("GATTC HVX"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => defmt::intern!("GATTC EXCHANGE_MTU_RSP"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => defmt::intern!("GATTC TIMEOUT"),
- raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => defmt::intern!("GATTC WRITE_CMD_TX_COMPLETE"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_WRITE => defmt::intern!("GATTS WRITE"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST => defmt::intern!("GATTS RW_AUTHORIZE_REQUEST"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SYS_ATTR_MISSING => defmt::intern!("GATTS SYS_ATTR_MISSING"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVC => defmt::intern!("GATTS HVC"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SC_CONFIRM => defmt::intern!("GATTS SC_CONFIRM"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST => defmt::intern!("GATTS EXCHANGE_MTU_REQUEST"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT => defmt::intern!("GATTS TIMEOUT"),
- raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVN_TX_COMPLETE => defmt::intern!("GATTS HVN_TX_COMPLETE"),
x => depanic!("Unknown ble evt {:u32}", x),
}
}
diff --git a/nrf-softdevice/src/ble/types.rs b/nrf-softdevice/src/ble/types.rs
index f769aa2..87d4087 100644
--- a/nrf-softdevice/src/ble/types.rs
+++ b/nrf-softdevice/src/ble/types.rs
@@ -3,18 +3,30 @@ use crate::raw;
#[derive(defmt::Format, Copy, Clone, Eq, PartialEq)]
pub enum Role {
+ #[cfg(feature = "ble-central")]
Central,
+ #[cfg(feature = "ble-peripheral")]
Peripheral,
}
impl Role {
pub fn from_raw(raw: u8) -> Self {
match raw as u32 {
+ #[cfg(feature = "ble-central")]
raw::BLE_GAP_ROLE_CENTRAL => Self::Central,
+ #[cfg(feature = "ble-peripheral")]
raw::BLE_GAP_ROLE_PERIPH => Self::Peripheral,
_ => depanic!("unknown role {:u8}", raw),
}
}
+
+ pub(crate) const fn whatever() -> Self {
+ #[cfg(not(feature = "ble-peripheral"))]
+ return Self::Central;
+
+ #[cfg(feature = "ble-peripheral")]
+ return Self::Peripheral;
+ }
}
#[repr(transparent)]
diff --git a/nrf-softdevice/src/error.rs b/nrf-softdevice/src/error.rs
index ec630dd..c2d22ed 100644
--- a/nrf-softdevice/src/error.rs
+++ b/nrf-softdevice/src/error.rs
@@ -53,6 +53,7 @@ pub enum Error {
BleInvalidRole = raw::BLE_ERROR_INVALID_ROLE,
BleBlockedByOtherLinks = raw::BLE_ERROR_BLOCKED_BY_OTHER_LINKS,
BleGapUuidListMismatch = raw::BLE_ERROR_GAP_UUID_LIST_MISMATCH,
+ #[cfg(feature="ble-peripheral")]
BleGapDiscoverableWithWhitelist = raw::BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST,
BleGapInvalidBleAddr = raw::BLE_ERROR_GAP_INVALID_BLE_ADDR,
BleGapWhitelistInUse = raw::BLE_ERROR_GAP_WHITELIST_IN_USE,
diff --git a/nrf-softdevice/src/events.rs b/nrf-softdevice/src/events.rs
index 79f4be7..aa0196f 100644
--- a/nrf-softdevice/src/events.rs
+++ b/nrf-softdevice/src/events.rs
@@ -21,8 +21,11 @@ enum SocEvent {
RadioSignalCallbackInvalidReturn = raw::NRF_SOC_EVTS_NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN,
RadioSessionIdle = raw::NRF_SOC_EVTS_NRF_EVT_RADIO_SESSION_IDLE,
RadioSessionClosed = raw::NRF_SOC_EVTS_NRF_EVT_RADIO_SESSION_CLOSED,
+ #[cfg(any(feature="s113", feature="s122", feature="s140"))]
PowerUsbPowerReady = raw::NRF_SOC_EVTS_NRF_EVT_POWER_USB_POWER_READY,
+ #[cfg(any(feature="s113", feature="s122", feature="s140"))]
PowerUsbDetected = raw::NRF_SOC_EVTS_NRF_EVT_POWER_USB_DETECTED,
+ #[cfg(any(feature="s113", feature="s122", feature="s140"))]
PowerUsbRemoved = raw::NRF_SOC_EVTS_NRF_EVT_POWER_USB_REMOVED,
}
@@ -74,7 +77,13 @@ pub async fn run() {
}
}
}
+#[cfg(feature = "nrf52810")]
+#[interrupt]
+unsafe fn SWI2() {
+ SWI2_SIGNAL.signal(());
+}
+#[cfg(not(feature = "nrf52810"))]
#[interrupt]
unsafe fn SWI2_EGU2() {
SWI2_SIGNAL.signal(());
diff --git a/nrf-softdevice/src/interrupt.rs b/nrf-softdevice/src/interrupt.rs
index 8a3965e..d4dbb3d 100644
--- a/nrf-softdevice/src/interrupt.rs
+++ b/nrf-softdevice/src/interrupt.rs
@@ -8,6 +8,21 @@ pub use crate::pac::Interrupt;
pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt]
pub use bare_metal::{CriticalSection, Mutex};
+#[cfg(feature = "nrf52810")]
+const RESERVED_IRQS: [u32; 2] = [
+ (1 << (Interrupt::POWER_CLOCK as u8))
+ | (1 << (Interrupt::RADIO as u8))
+ | (1 << (Interrupt::RTC0 as u8))
+ | (1 << (Interrupt::TIMER0 as u8))
+ | (1 << (Interrupt::RNG as u8))
+ | (1 << (Interrupt::ECB as u8))
+ | (1 << (Interrupt::CCM_AAR as u8))
+ | (1 << (Interrupt::TEMP as u8))
+ | (1 << (Interrupt::SWI5 as u8)),
+ 0,
+];
+
+#[cfg(not(feature = "nrf52810"))]
const RESERVED_IRQS: [u32; 2] = [
(1 << (Interrupt::POWER_CLOCK as u8))
| (1 << (Interrupt::RADIO as u8))
@@ -130,18 +145,8 @@ where
#[inline]
fn is_app_accessible_irq(irq: Interrupt) -> bool {
- match irq {
- Interrupt::POWER_CLOCK
- | Interrupt::RADIO
- | Interrupt::RTC0
- | Interrupt::TIMER0
- | Interrupt::RNG
- | Interrupt::ECB
- | Interrupt::CCM_AAR
- | Interrupt::TEMP
- | Interrupt::SWI5_EGU5 => false,
- _ => true,
- }
+ let nr = irq.number();
+ (RESERVED_IRQS[usize::from(nr / 32)] & 1 << (nr % 32)) == 0
}
#[inline]
@@ -253,6 +258,130 @@ pub fn set_priority(irq: Interrupt, prio: Priority) {
}
}
+#[cfg(feature = "nrf52810")]
+fn irq_str(irq: Interrupt) -> defmt::Str {
+ match irq {
+ POWER_CLOCK => defmt::intern!("POWER_CLOCK"),
+ RADIO => defmt::intern!("RADIO"),
+ UARTE0_UART0 => defmt::intern!("UARTE0_UART0"),
+ TWIM0_TWIS0_TWI0 => defmt::intern!("TWIM0_TWIS0_TWI0"),
+ SPIM0_SPIS0_SPI0 => defmt::intern!("SPIM0_SPIS0_SPI0"),
+ GPIOTE => defmt::intern!("GPIOTE"),
+ SAADC => defmt::intern!("SAADC"),
+ TIMER0 => defmt::intern!("TIMER0"),
+ TIMER1 => defmt::intern!("TIMER1"),
+ TIMER2 => defmt::intern!("TIMER2"),
+ RTC0 => defmt::intern!("RTC0"),
+ TEMP => defmt::intern!("TEMP"),
+ RNG => defmt::intern!("RNG"),
+ ECB => defmt::intern!("ECB"),
+ CCM_AAR => defmt::intern!("CCM_AAR"),
+ WDT => defmt::intern!("WDT"),
+ RTC1 => defmt::intern!("RTC1"),
+ QDEC => defmt::intern!("QDEC"),
+ COMP => defmt::intern!("COMP"),
+ SWI0_EGU0 => defmt::intern!("SWI0_EGU0"),
+ SWI1_EGU1 => defmt::intern!("SWI1_EGU1"),
+ SWI2 => defmt::intern!("SWI2"),
+ SWI3 => defmt::intern!("SWI3"),
+ SWI4 => defmt::intern!("SWI4"),
+ SWI5 => defmt::intern!("SWI5"),
+ PWM0 => defmt::intern!("PWM0"),
+ PDM => defmt::intern!("PDM"),
+ }
+}
+
+#[cfg(feature = "nrf52832")]
+fn irq_str(irq: Interrupt) -> defmt::Str {
+ match irq {
+ POWER_CLOCK => defmt::intern!("POWER_CLOCK"),
+ RADIO => defmt::intern!("RADIO"),
+ UARTE0_UART0 => defmt::intern!("UARTE0_UART0"),
+ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => defmt::intern!("SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0"),
+ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => defmt::intern!("SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1"),
+ NFCT => defmt::intern!("NFCT"),
+ GPIOTE => defmt::intern!("GPIOTE"),
+ SAADC => defmt::intern!("SAADC"),
+ TIMER0 => defmt::intern!("TIMER0"),
+ TIMER1 => defmt::intern!("TIMER1"),
+ TIMER2 => defmt::intern!("TIMER2"),
+ RTC0 => defmt::intern!("RTC0"),
+ TEMP => defmt::intern!("TEMP"),
+ RNG => defmt::intern!("RNG"),
+ ECB => defmt::intern!("ECB"),
+ CCM_AAR => defmt::intern!("CCM_AAR"),
+ WDT => defmt::intern!("WDT"),
+ RTC1 => defmt::intern!("RTC1"),
+ QDEC => defmt::intern!("QDEC"),
+ COMP_LPCOMP => defmt::intern!("COMP_LPCOMP"),
+ SWI0_EGU0 => defmt::intern!("SWI0_EGU0"),
+ SWI1_EGU1 => defmt::intern!("SWI1_EGU1"),
+ SWI2_EGU2 => defmt::intern!("SWI2_EGU2"),
+ SWI3_EGU3 => defmt::intern!("SWI3_EGU3"),
+ SWI4_EGU4 => defmt::intern!("SWI4_EGU4"),
+ SWI5_EGU5 => defmt::intern!("SWI5_EGU5"),
+ TIMER3 => defmt::intern!("TIMER3"),
+ TIMER4 => defmt::intern!("TIMER4"),
+ PWM0 => defmt::intern!("PWM0"),
+ PDM => defmt::intern!("PDM"),
+ MWU => defmt::intern!("MWU"),
+ PWM1 => defmt::intern!("PWM1"),
+ PWM2 => defmt::intern!("PWM2"),
+ SPIM2_SPIS2_SPI2 => defmt::intern!("SPIM2_SPIS2_SPI2"),
+ RTC2 => defmt::intern!("RTC2"),
+ I2S => defmt::intern!("I2S"),
+ FPU => defmt::intern!("FPU"),
+ }
+}
+
+#[cfg(feature = "nrf52833")]
+fn irq_str(irq: Interrupt) -> defmt::Str {
+ match irq {
+ POWER_CLOCK => defmt::intern!("POWER_CLOCK"),
+ RADIO => defmt::intern!("RADIO"),
+ UARTE0_UART0 => defmt::intern!("UARTE0_UART0"),
+ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => defmt::intern!("SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0"),
+ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => defmt::intern!("SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1"),
+ NFCT => defmt::intern!("NFCT"),
+ GPIOTE => defmt::intern!("GPIOTE"),
+ SAADC => defmt::intern!("SAADC"),
+ TIMER0 => defmt::intern!("TIMER0"),
+ TIMER1 => defmt::intern!("TIMER1"),
+ TIMER2 => defmt::intern!("TIMER2"),
+ RTC0 => defmt::intern!("RTC0"),
+ TEMP => defmt::intern!("TEMP"),
+ RNG => defmt::intern!("RNG"),
+ ECB => defmt::intern!("ECB"),
+ CCM_AAR => defmt::intern!("CCM_AAR"),
+ WDT => defmt::intern!("WDT"),
+ RTC1 => defmt::intern!("RTC1"),
+ QDEC => defmt::intern!("QDEC"),
+ COMP_LPCOMP => defmt::intern!("COMP_LPCOMP"),
+ SWI0_EGU0 => defmt::intern!("SWI0_EGU0"),
+ SWI1_EGU1 => defmt::intern!("SWI1_EGU1"),
+ SWI2_EGU2 => defmt::intern!("SWI2_EGU2"),
+ SWI3_EGU3 => defmt::intern!("SWI3_EGU3"),
+ SWI4_EGU4 => defmt::intern!("SWI4_EGU4"),
+ SWI5_EGU5 => defmt::intern!("SWI5_EGU5"),
+ TIMER3 => defmt::intern!("TIMER3"),
+ TIMER4 => defmt::intern!("TIMER4"),
+ PWM0 => defmt::intern!("PWM0"),
+ PDM => defmt::intern!("PDM"),
+ MWU => defmt::intern!("MWU"),
+ PWM1 => defmt::intern!("PWM1"),
+ PWM2 => defmt::intern!("PWM2"),
+ SPIM2_SPIS2_SPI2 => defmt::intern!("SPIM2_SPIS2_SPI2"),
+ RTC2 => defmt::intern!("RTC2"),
+ I2S => defmt::intern!("I2S"),
+ FPU => defmt::intern!("FPU"),
+ USBD => defmt::intern!("USBD"),
+ UARTE1 => defmt::intern!("UARTE1"),
+ PWM3 => defmt::intern!("PWM3"),
+ SPIM3 => defmt::intern!("SPIM3"),
+ }
+}
+
+#[cfg(feature = "nrf52840")]
fn irq_str(irq: Interrupt) -> defmt::Str {
match irq {
POWER_CLOCK => defmt::intern!("POWER_CLOCK"),
diff --git a/nrf-softdevice/src/lib.rs b/nrf-softdevice/src/lib.rs
index dce15d1..43ae36a 100644
--- a/nrf-softdevice/src/lib.rs
+++ b/nrf-softdevice/src/lib.rs
@@ -7,9 +7,24 @@
pub(crate) mod util;
-// This is here so that the rest of the crate can easily use the right PAC and SD crates.
-// TODO change this dynamically based on features.
+#[cfg(feature = "nrf52810")]
+pub use nrf52810_pac as pac;
+#[cfg(feature = "nrf52832")]
+pub use nrf52832_pac as pac;
+#[cfg(feature = "nrf52833")]
+pub use nrf52833_pac as pac;
+#[cfg(feature = "nrf52840")]
pub use nrf52840_pac as pac;
+
+#[cfg(feature = "s112")]
+pub use nrf_softdevice_s112 as raw;
+#[cfg(feature = "s113")]
+pub use nrf_softdevice_s113 as raw;
+#[cfg(feature = "s122")]
+pub use nrf_softdevice_s122 as raw;
+#[cfg(feature = "s132")]
+pub use nrf_softdevice_s132 as raw;
+#[cfg(feature = "s140")]
pub use nrf_softdevice_s140 as raw;
pub mod interrupt;
@@ -41,6 +56,7 @@ pub struct Config {
pub conn_gattc: Option<raw::ble_gattc_conn_cfg_t>,
pub conn_gatts: Option<raw::ble_gatts_conn_cfg_t>,
pub conn_gatt: Option<raw::ble_gatt_conn_cfg_t>,
+ #[cfg(feature = "ble-l2cap")]
pub conn_l2cap: Option<raw::ble_l2cap_conn_cfg_t>,
pub common_vs_uuid: Option<raw::ble_common_cfg_vs_uuid_t>,
pub gap_role_count: Option<raw::ble_gap_cfg_role_count_t>,
@@ -138,6 +154,7 @@ pub unsafe fn enable(config: &Config) {
);
}
+ #[cfg(feature = "ble-l2cap")]
if let Some(val) = config.conn_l2cap {
cfg_set(
raw::BLE_CONN_CFGS_BLE_CONN_CFG_L2CAP,
@@ -244,6 +261,9 @@ pub unsafe fn enable(config: &Config) {
warn!("You're giving more RAM to the softdevice than needed. You can change your app's RAM start address to {:u32}", wanted_app_ram_base);
}
+ #[cfg(feature = "nrf52810")]
+ interrupt::enable(interrupt::Interrupt::SWI2);
+ #[cfg(not(feature = "nrf52810"))]
interrupt::enable(interrupt::Interrupt::SWI2_EGU2);
}
@@ -253,6 +273,7 @@ fn cfg_id_str(id: u32) -> defmt::Str {
raw::BLE_CONN_CFGS_BLE_CONN_CFG_GATTC => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_GATTC"),
raw::BLE_CONN_CFGS_BLE_CONN_CFG_GATTS => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_GATTS"),
raw::BLE_CONN_CFGS_BLE_CONN_CFG_GATT => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_GATT"),
+ #[cfg(feature = "ble-l2cap")]
raw::BLE_CONN_CFGS_BLE_CONN_CFG_L2CAP => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_L2CAP"),
raw::BLE_COMMON_CFGS_BLE_COMMON_CFG_VS_UUID => {
defmt::intern!("BLE_COMMON_CFGS_BLE_COMMON_CFG_VS_UUID")
diff --git a/test-build.sh b/test-build.sh
new file mode 100755
index 0000000..b044a90
--- /dev/null
+++ b/test-build.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+# Test that build works with all supported combinations.
+# TODO l2cap in s113, s132, s140
+
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s112,nrf52810,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s112,nrf52832,ble-peripheral
+
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52810,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52832,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52833,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52840,ble-peripheral
+
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s122,nrf52833,ble-central
+
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52810,ble-central
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52810,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52810,ble-central,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52832,ble-central
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52832,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52832,ble-central,ble-peripheral
+
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52833,ble-central
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52833,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52833,ble-central,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52840,ble-central
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52840,ble-peripheral
+cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52840,ble-central,ble-peripheral
+
+# https://www.nordicsemi.com/Software-and-tools/Software/Bluetooth-Software
+
+# | Central Peripheral | nrf52805 nrf52810 nrf52811 nrf52820 nrf52832 nrf52833, nrf52840
+# -----|---------------------|--------------------------------------------------------------------------
+# s112 | X | X X X X X
+# s113 | X | X X X X X X X
+# s122 | X | X X
+# s132 | X X | X X
+# s140 | X X | X X X X
+
+# s112 nrf52805
+# s112 nrf52810
+# s112 nrf52811
+# s112 nrf52820
+# s112 nrf52832
+#
+# s113 nrf52805
+# s113 nrf52810
+# s113 nrf52811
+# s113 nrf52820
+# s113 nrf52832
+# s113 nrf52833
+# s113 nrf52840
+#
+# s122 nrf52820
+# s122 nrf52833
+#
+# s132 nrf52810
+# s132 nrf52832
+#
+# s140 nrf52811
+# s140 nrf52820
+# s140 nrf52833
+# s140 nrf52840 \ No newline at end of file