Skip to content

Commit 739a289

Browse files
committed
feat(example): use internal flash in nrf-sdc bonding example, update deps, fix bonding example issue
Signed-off-by: Haobo Gu <[email protected]>
1 parent 1d873e8 commit 739a289

File tree

4 files changed

+69
-59
lines changed

4 files changed

+69
-59
lines changed

examples/apps/src/ble_bas_peripheral_bonding.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use trouble_host::prelude::*;
1212
const CONNECTIONS_MAX: usize = 1;
1313

1414
/// Max number of L2CAP channels.
15-
const L2CAP_CHANNELS_MAX: usize = 2; // Signal + att
15+
const L2CAP_CHANNELS_MAX: usize = 4; // Signal + att
1616

1717
// GATT Server definition
1818
#[gatt_server]
@@ -46,7 +46,6 @@ pub(crate) struct HidService {
4646
pub(crate) output_keyboard: [u8; 1],
4747
}
4848

49-
5049
/// Battery service
5150
#[gatt_service(uuid = service::BATTERY)]
5251
struct BatteryService {
@@ -74,8 +73,7 @@ impl Key for StoredAddr {
7473
fn deserialize_from(buffer: &[u8]) -> Result<(Self, usize), SerializationError> {
7574
if buffer.len() < 6 {
7675
Err(SerializationError::BufferTooSmall)
77-
}
78-
else {
76+
} else {
7977
Ok((StoredAddr(BdAddr::new(buffer[0..6].try_into().unwrap())), 6))
8078
}
8179
}
@@ -102,43 +100,56 @@ impl<'a> Value<'a> for StoredBondInformation {
102100

103101
fn deserialize_from(buffer: &'a [u8]) -> Result<Self, SerializationError>
104102
where
105-
Self: Sized
103+
Self: Sized,
106104
{
107105
if buffer.len() < 17 {
108106
Err(SerializationError::BufferTooSmall)
109-
}
110-
else {
107+
} else {
111108
let ltk = LongTermKey::from_le_bytes(buffer[0..16].try_into().unwrap());
112109
let security_level = match buffer[16] {
113110
0 => SecurityLevel::NoEncryption,
114111
1 => SecurityLevel::Encrypted,
115112
2 => SecurityLevel::EncryptedAuthenticated,
116-
_ => return Err(SerializationError::InvalidData)
113+
_ => return Err(SerializationError::InvalidData),
117114
};
118115
Ok(StoredBondInformation { ltk, security_level })
119116
}
120117
}
121118
}
122119

123120
fn flash_range<S: NorFlash>() -> Range<u32> {
124-
0..2*S::ERASE_SIZE as u32
121+
0..2 * S::ERASE_SIZE as u32
125122
}
126123

127-
async fn store_bonding_info<S: NorFlash>(storage: &mut S, info: &BondInformation) -> Result<(), sequential_storage::Error<S::Error>> {
128-
// Assumes that S::ERASE_SIZE is large enough
129-
sequential_storage::erase_all(storage, 0..S::ERASE_SIZE as u32).await?;
130-
let mut buffer = [0;32];
124+
async fn store_bonding_info<S: NorFlash>(
125+
storage: &mut S,
126+
info: &BondInformation,
127+
) -> Result<(), sequential_storage::Error<S::Error>> {
128+
// Use flash range from 640KB, should be good for both ESP32 & nRF52840 examples
129+
let start_addr = 0xA0000 as u32;
130+
let storage_range = start_addr..(start_addr + 8 * S::ERASE_SIZE as u32);
131+
sequential_storage::erase_all(storage, storage_range.clone()).await?;
132+
let mut buffer = [0; 32];
131133
let key = StoredAddr(info.identity.bd_addr);
132-
let value = StoredBondInformation { ltk: info.ltk, security_level: info.security_level };
133-
sequential_storage::map::store_item(storage, flash_range::<S>(), &mut NoCache::new(), &mut buffer, &key, &value).await?;
134+
let value = StoredBondInformation {
135+
ltk: info.ltk,
136+
security_level: info.security_level,
137+
};
138+
sequential_storage::map::store_item(storage, storage_range, &mut NoCache::new(), &mut buffer, &key, &value).await?;
134139
Ok(())
135140
}
136141

137-
async fn load_bonding_info<S: NorFlash>(storage: &mut S) -> Option<BondInformation>
138-
{
139-
let mut buffer = [0;32];
142+
async fn load_bonding_info<S: NorFlash>(storage: &mut S) -> Option<BondInformation> {
143+
let mut buffer = [0; 32];
140144
let mut cache = NoCache::new();
141-
let mut iter = sequential_storage::map::fetch_all_items::<StoredAddr, _, _>(storage, flash_range::<S>(), &mut cache, &mut buffer).await.ok()?;
145+
let mut iter = sequential_storage::map::fetch_all_items::<StoredAddr, _, _>(
146+
storage,
147+
flash_range::<S>(),
148+
&mut cache,
149+
&mut buffer,
150+
)
151+
.await
152+
.ok()?;
142153
while let Some((key, value)) = iter.next::<StoredBondInformation>(&mut buffer).await.ok()? {
143154
return Some(BondInformation {
144155
identity: Identity {
@@ -147,7 +158,7 @@ async fn load_bonding_info<S: NorFlash>(storage: &mut S) -> Option<BondInformati
147158
},
148159
security_level: value.security_level,
149160
is_bonded: true,
150-
ltk: value.ltk
161+
ltk: value.ltk,
151162
});
152163
}
153164
None
@@ -174,8 +185,7 @@ where
174185
info!("Loaded bond information");
175186
stack.add_bond_information(bond_info).unwrap();
176187
true
177-
}
178-
else {
188+
} else {
179189
info!("No bond information found");
180190
false
181191
};
@@ -189,7 +199,7 @@ where
189199
name: "TrouBLE",
190200
appearance: &appearance::human_interface_device::GENERIC_HUMAN_INTERFACE_DEVICE,
191201
}))
192-
.unwrap();
202+
.unwrap();
193203

194204
let _ = join(ble_task(runner), async {
195205
loop {
@@ -203,6 +213,7 @@ where
203213
// run until any task ends (usually because the connection has been closed),
204214
// then return to advertising state.
205215
select(a, b).await;
216+
info!("Connection dropped");
206217
}
207218
Err(e) => {
208219
#[cfg(feature = "defmt")]
@@ -212,7 +223,7 @@ where
212223
}
213224
}
214225
})
215-
.await;
226+
.await;
216227
}
217228

218229
/// This is a background task that is required to run forever alongside any other BLE tasks.
@@ -244,13 +255,18 @@ async fn ble_task<C: Controller, P: PacketPool>(mut runner: Runner<'_, C, P>) {
244255
///
245256
/// This function will handle the GATT events and process them.
246257
/// This is how we interact with read and write requests.
247-
async fn gatt_events_task<S: NorFlash>(storage: &mut S, server: &Server<'_>, conn: &GattConnection<'_, '_, DefaultPacketPool>, bond_stored: &mut bool) -> Result<(), Error> {
258+
async fn gatt_events_task<S: NorFlash>(
259+
storage: &mut S,
260+
server: &Server<'_>,
261+
conn: &GattConnection<'_, '_, DefaultPacketPool>,
262+
bond_stored: &mut bool,
263+
) -> Result<(), Error> {
248264
let level = server.battery_service.level;
249265
let reason = loop {
250266
match conn.next().await {
251267
GattConnectionEvent::Disconnected { reason } => break reason,
252268
#[cfg(feature = "security")]
253-
GattConnectionEvent::PairingComplete { security_level, bond} => {
269+
GattConnectionEvent::PairingComplete { security_level, bond } => {
254270
info!("[gatt] pairing complete: {:?}", security_level);
255271
if let Some(bond) = bond {
256272
store_bonding_info(storage, &bond).await.unwrap();
@@ -321,7 +337,10 @@ async fn advertise<'values, 'server, C: Controller>(
321337
let len = AdStructure::encode_slice(
322338
&[
323339
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
324-
AdStructure::ServiceUuids16(&[service::BATTERY.to_le_bytes(), service::HUMAN_INTERFACE_DEVICE.to_le_bytes()]),
340+
AdStructure::ServiceUuids16(&[
341+
service::BATTERY.to_le_bytes(),
342+
service::HUMAN_INTERFACE_DEVICE.to_le_bytes(),
343+
]),
325344
AdStructure::CompleteLocalName(name.as_bytes()),
326345
],
327346
&mut advertiser_data[..],

examples/nrf-sdc/Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/nrf-sdc/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ resolver = "2"
77
[dependencies]
88
embassy-executor = { version = "0.9", default-features = false, features = ["arch-cortex-m", "executor-thread", "defmt", "executor-interrupt"] }
99
embassy-time = { version = "0.5", default-features = false, features = ["defmt", "defmt-timestamp-uptime"] }
10-
embassy-nrf = { version = "0.7", default-features = false, features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac", "rt"] }
10+
embassy-nrf = { version = "0.8", default-features = false, features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac", "rt"] }
1111
embassy-futures = "0.1.1"
1212
embassy-sync = { version = "0.7", features = ["defmt"] }
1313

1414
futures = { version = "0.3", default-features = false, features = ["async-await"]}
1515
nrf-sdc = { version = "0.4", default-features = false, features = ["defmt", "peripheral", "central"] }
1616
nrf-mpsl = { version = "0.3", default-features = false, features = ["defmt", "critical-section-impl"] }
1717
bt-hci = { version = "0.6", default-features = false, features = ["defmt"] }
18-
trouble-host = { path = "../../host", features = ["derive", "scan"] }
18+
trouble-host = { path = "../../host", features = ["derive", "scan", "gatt"] }
1919
trouble-example-apps = { version = "0.1.0", path = "../apps", features = ["defmt"] }
2020

2121
defmt = "1.0"
@@ -41,8 +41,8 @@ debug = 2
4141
#embassy-time-driver = {path = "../../../embassy/embassy-time-driver"}
4242
#embassy-embedded-hal = {path = "../../../embassy/embassy-embedded-hal"}
4343
#embassy-hal-internal = {path = "../../../embassy/embassy-hal-internal"}
44-
nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", rev = "1bc7380cd5d7a031f37511b69da13fc6caded816"}
45-
nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", rev = "1bc7380cd5d7a031f37511b69da13fc6caded816"}
44+
nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", rev = "11d5c3c"}
45+
nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", rev = "11d5c3c"}
4646
#bt-hci = { git = "https://github.com/embassy-rs/bt-hci.git", rev = "83a9e179ff019ed60abb73705f54383f89fc60fc" }
4747

4848
[features]

examples/nrf-sdc/src/bin/ble_bas_peripheral_bonding.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use embassy_executor::Spawner;
66
use embassy_nrf::mode::Async;
77
use embassy_nrf::peripherals::RNG;
88
use embassy_nrf::{bind_interrupts, qspi, rng};
9+
use nrf_sdc::mpsl::Flash;
910
use nrf_sdc::mpsl::MultiprotocolServiceLayer;
1011
use nrf_sdc::{self as sdc, mpsl};
1112
use rand_chacha::ChaCha12Rng;
@@ -40,7 +41,7 @@ const L2CAP_MTU: usize = 72;
4041

4142
fn build_sdc<'d, const N: usize>(
4243
p: nrf_sdc::Peripherals<'d>,
43-
rng: &'d mut rng::Rng<RNG, Async>,
44+
rng: &'d mut rng::Rng<Async>,
4445
mpsl: &'d MultiprotocolServiceLayer,
4546
mem: &'d mut sdc::Mem<N>,
4647
) -> Result<nrf_sdc::SoftdeviceController<'d>, nrf_sdc::Error> {
@@ -64,7 +65,13 @@ async fn main(spawner: Spawner) {
6465
skip_wait_lfclk_started: mpsl::raw::MPSL_DEFAULT_SKIP_WAIT_LFCLK_STARTED != 0,
6566
};
6667
static MPSL: StaticCell<MultiprotocolServiceLayer> = StaticCell::new();
67-
let mpsl = MPSL.init(unwrap!(mpsl::MultiprotocolServiceLayer::new(mpsl_p, Irqs, lfclk_cfg)));
68+
static SESSION_MEM: StaticCell<mpsl::SessionMem<1>> = StaticCell::new();
69+
let mpsl = MPSL.init(unwrap!(mpsl::MultiprotocolServiceLayer::with_timeslots(
70+
mpsl_p,
71+
Irqs,
72+
lfclk_cfg,
73+
SESSION_MEM.init(mpsl::SessionMem::new())
74+
)));
6875
spawner.must_spawn(mpsl_task(&*mpsl));
6976

7077
let sdc_p = sdc::Peripherals::new(
@@ -75,27 +82,11 @@ async fn main(spawner: Spawner) {
7582
let mut rng = rng::Rng::new(p.RNG, Irqs);
7683
let mut rng_2 = ChaCha12Rng::from_rng(&mut rng).unwrap();
7784

78-
let mut sdc_mem = sdc::Mem::<3312>::new();
85+
let mut sdc_mem = sdc::Mem::<5000>::new();
7986
let sdc = unwrap!(build_sdc(sdc_p, &mut rng, mpsl, &mut sdc_mem));
8087

81-
// Config for the MX25R64 present in the nRF52840 DK
82-
let mut config = qspi::Config::default();
83-
config.read_opcode = qspi::ReadOpcode::READ4IO;
84-
config.write_opcode = qspi::WriteOpcode::PP4IO;
85-
config.write_page_size = qspi::WritePageSize::_256BYTES;
86-
config.frequency = qspi::Frequency::M32;
87-
config.capacity = 8*1024*1024;
88+
// Use internal Flash as the storage
89+
let mut flash = Flash::take(mpsl, p.NVMC);
8890

89-
let mut qspi: qspi::Qspi<_> = qspi::Qspi::new(
90-
p.QSPI, Irqs, p.P0_19, p.P0_17, p.P0_20, p.P0_21, p.P0_22, p.P0_23, config,
91-
);
92-
let input = embassy_nrf::gpio::Input::new(p.P0_11, embassy_nrf::gpio::Pull::Up);
93-
// Allow time for button to settle
94-
embassy_time::Timer::after(embassy_time::Duration::from_millis(100)).await;
95-
if input.is_low() {
96-
defmt::info!("Erasing flash");
97-
qspi.erase(0).await.unwrap();
98-
}
99-
100-
ble_bas_peripheral_bonding::run(sdc, &mut rng_2, &mut qspi).await;
91+
ble_bas_peripheral_bonding::run(sdc, &mut rng_2, &mut flash).await;
10192
}

0 commit comments

Comments
 (0)