summaryrefslogtreecommitdiff
path: root/examples/src
diff options
context:
space:
mode:
Diffstat (limited to 'examples/src')
-rw-r--r--examples/src/bin/ble_bas_central.rs1
-rw-r--r--examples/src/bin/ble_bas_peripheral.rs1
-rw-r--r--examples/src/bin/ble_l2cap_central.rs176
-rw-r--r--examples/src/bin/ble_l2cap_peripheral.rs163
-rw-r--r--examples/src/bin/ble_peripheral_onoff.rs1
-rw-r--r--examples/src/bin/ble_scan.rs1
-rw-r--r--examples/src/bin/flash.rs1
-rw-r--r--examples/src/bin/interrupts.rs1
-rw-r--r--examples/src/bin/rtic.rs1
-rw-r--r--examples/src/example_common.rs18
10 files changed, 364 insertions, 0 deletions
diff --git a/examples/src/bin/ble_bas_central.rs b/examples/src/bin/ble_bas_central.rs
index 0bef2f4..5216aea 100644
--- a/examples/src/bin/ble_bas_central.rs
+++ b/examples/src/bin/ble_bas_central.rs
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/bin/ble_bas_peripheral.rs b/examples/src/bin/ble_bas_peripheral.rs
index 24c59a7..08e74fa 100644
--- a/examples/src/bin/ble_bas_peripheral.rs
+++ b/examples/src/bin/ble_bas_peripheral.rs
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/bin/ble_l2cap_central.rs b/examples/src/bin/ble_l2cap_central.rs
new file mode 100644
index 0000000..c1675b5
--- /dev/null
+++ b/examples/src/bin/ble_l2cap_central.rs
@@ -0,0 +1,176 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
+extern crate alloc;
+
+#[path = "../example_common.rs"]
+mod example_common;
+use example_common::*;
+
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
+use cortex_m_rt::entry;
+use defmt::info;
+use defmt::{panic, *};
+use embassy::executor::{task, Executor};
+use embassy::util::Forever;
+use heapless::consts::*;
+
+use nrf_softdevice::ble::l2cap::Packet as _;
+use nrf_softdevice::ble::{central, l2cap, Address, Connection, Uuid};
+use nrf_softdevice::raw;
+use nrf_softdevice::Softdevice;
+
+static EXECUTOR: Forever<Executor> = Forever::new();
+
+const PSM: u16 = 0x2349;
+
+#[task]
+async fn softdevice_task(sd: &'static Softdevice) {
+ sd.run().await;
+}
+
+#[task]
+async fn ble_central_task(sd: &'static Softdevice) {
+ info!("Scanning for peer...");
+
+ let config = central::ScanConfig { whitelist: None };
+ let res = central::scan(sd, config, |params| unsafe {
+ let mut data = slice::from_raw_parts(params.data.p_data, params.data.len as usize);
+ while data.len() != 0 {
+ let len = data[0] as usize;
+ if data.len() < len + 1 {
+ break;
+ }
+ if len < 1 {
+ break;
+ }
+ let key = data[1];
+ let value = &data[2..len + 1];
+
+ if key == 0x06
+ && value
+ == &[
+ 0xeb, 0x04, 0x8b, 0xfd, 0x5b, 0x03, 0x21, 0xb5, 0xeb, 0x11, 0x65, 0x2f,
+ 0x18, 0xce, 0x9c, 0x82,
+ ]
+ {
+ return Some(Address::new_random_static(params.peer_addr.addr));
+ }
+ data = &data[len + 1..];
+ }
+ None
+ })
+ .await;
+ let address = unwrap!(res);
+ info!("Scan found address {:?}", address);
+
+ let addrs = &[address];
+
+ let config = central::Config::default();
+ let conn = unwrap!(central::connect(sd, addrs, config).await);
+ info!("connected");
+
+ let l = l2cap::L2cap::<Packet>::init(sd);
+ let ch = unwrap!(l.setup(&conn, PSM).await);
+ info!("l2cap connected");
+
+ for i in 0..10 {
+ let mut v = Vec::with_capacity(Packet::MTU);
+ v.extend(&[i; Packet::MTU]);
+ unwrap!(ch.tx(Packet(v)));
+ info!("l2cap tx done");
+ }
+ futures::future::pending::<()>().await;
+}
+
+use alloc::vec::Vec;
+
+struct Packet(Vec<u8>);
+impl l2cap::Packet for Packet {
+ const MTU: usize = 512;
+ fn allocate() -> Option<NonNull<u8>> {
+ let mut v = Vec::with_capacity(Self::MTU);
+ let ptr = v.as_mut_ptr();
+ mem::forget(v);
+ info!("allocate {:u32}", ptr as u32);
+ NonNull::new(ptr)
+ }
+
+ fn into_raw_parts(mut self) -> (NonNull<u8>, usize) {
+ let ptr = self.0.as_mut_ptr();
+ let len = self.0.len();
+ mem::forget(self);
+ info!("into_raw_parts {:u32}", ptr as u32);
+ (unwrap!(NonNull::new(ptr)), len)
+ }
+
+ unsafe fn from_raw_parts(ptr: NonNull<u8>, len: usize) -> Self {
+ info!("from_raw_parts {:u32}", ptr.as_ptr() as u32);
+ Self(Vec::from_raw_parts(ptr.as_ptr(), len, Self::MTU))
+ }
+}
+
+#[entry]
+fn main() -> ! {
+ info!("Hello World!");
+
+ let 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: 7,
+ }),
+ conn_gap: Some(raw::ble_gap_conn_cfg_t {
+ conn_count: 20,
+ event_length: 180,
+ }),
+ conn_gatt: Some(raw::ble_gatt_conn_cfg_t { att_mtu: 114 }),
+ conn_gattc: Some(raw::ble_gattc_conn_cfg_t {
+ write_cmd_tx_queue_size: 0,
+ }),
+ conn_gatts: Some(raw::ble_gatts_conn_cfg_t {
+ hvn_tx_queue_size: 0,
+ }),
+ gatts_attr_tab_size: Some(raw::ble_gatts_cfg_attr_tab_size_t { attr_tab_size: 512 }),
+ gap_role_count: Some(raw::ble_gap_cfg_role_count_t {
+ adv_set_count: 1,
+ periph_role_count: 5,
+ central_role_count: 15,
+ 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,
+ ),
+ }),
+ conn_l2cap: Some(raw::ble_l2cap_conn_cfg_t {
+ ch_count: 1,
+ rx_mps: 247,
+ tx_mps: 247,
+ rx_queue_size: 10,
+ tx_queue_size: 10,
+ }),
+ ..Default::default()
+ };
+
+ let (sdp, p) = take_peripherals();
+ let sd = Softdevice::enable(sdp, &config);
+
+ let executor = EXECUTOR.put(Executor::new(cortex_m::asm::sev));
+ unwrap!(executor.spawn(softdevice_task(sd)));
+ unwrap!(executor.spawn(ble_central_task(sd)));
+
+ loop {
+ executor.run();
+ cortex_m::asm::wfe();
+ }
+}
diff --git a/examples/src/bin/ble_l2cap_peripheral.rs b/examples/src/bin/ble_l2cap_peripheral.rs
new file mode 100644
index 0000000..312a794
--- /dev/null
+++ b/examples/src/bin/ble_l2cap_peripheral.rs
@@ -0,0 +1,163 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
+extern crate alloc;
+
+#[path = "../example_common.rs"]
+mod example_common;
+use example_common::*;
+
+use core::mem;
+use core::ptr::NonNull;
+use cortex_m_rt::entry;
+use defmt::{panic, *};
+use heapless::consts::*;
+
+use nrf_softdevice::ble;
+use nrf_softdevice::ble::{l2cap, peripheral, Connection};
+use nrf_softdevice::{raw, RawError, Softdevice};
+
+use embassy::executor::{task, Executor};
+use embassy::util::Forever;
+static EXECUTOR: Forever<Executor> = Forever::new();
+
+const PSM: u16 = 0x2349;
+
+#[task]
+async fn softdevice_task(sd: &'static Softdevice) {
+ sd.run().await;
+}
+
+#[task]
+async fn bluetooth_task(sd: &'static Softdevice, config: peripheral::Config) {
+ info!("My address: {:?}", ble::get_address(sd));
+
+ #[rustfmt::skip]
+ let adv_data = &[
+ 0x02, 0x01, raw::BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE as u8,
+ 0x11, 0x06, 0xeb, 0x04, 0x8b, 0xfd, 0x5b, 0x03, 0x21, 0xb5, 0xeb, 0x11, 0x65, 0x2f, 0x18, 0xce, 0x9c, 0x82,
+ 0x02, 0x09, b'H',
+ ];
+ #[rustfmt::skip]
+ let scan_data = &[ ];
+
+ let l = l2cap::L2cap::<Packet>::init(sd);
+
+ loop {
+ let conn = unwrap!(
+ peripheral::advertise(
+ sd,
+ peripheral::ConnectableAdvertisement::ScannableUndirected {
+ adv_data,
+ scan_data,
+ },
+ config,
+ )
+ .await
+ );
+
+ info!("advertising done!");
+
+ let ch = unwrap!(l.listen(&conn, PSM).await);
+ info!("l2cap connected");
+
+ loop {
+ let pkt = unwrap!(ch.rx().await);
+ info!("rx: {:[u8]}", pkt.0);
+ }
+
+ futures::future::pending::<()>().await;
+ }
+}
+
+use alloc::vec::Vec;
+
+struct Packet(Vec<u8>);
+impl l2cap::Packet for Packet {
+ const MTU: usize = 512;
+ fn allocate() -> Option<NonNull<u8>> {
+ let mut v = Vec::with_capacity(Self::MTU);
+ let ptr = v.as_mut_ptr();
+ mem::forget(v);
+ info!("allocate {:u32}", ptr as u32);
+ NonNull::new(ptr)
+ }
+
+ fn into_raw_parts(mut self) -> (NonNull<u8>, usize) {
+ let ptr = self.0.as_mut_ptr();
+ let len = self.0.len();
+ mem::forget(self);
+ info!("into_raw_parts {:u32}", ptr as u32);
+ (unwrap!(NonNull::new(ptr)), len)
+ }
+
+ unsafe fn from_raw_parts(ptr: NonNull<u8>, len: usize) -> Self {
+ info!("from_raw_parts {:u32}", ptr.as_ptr() as u32);
+ Self(Vec::from_raw_parts(ptr.as_ptr(), len, Self::MTU))
+ }
+}
+
+#[entry]
+fn main() -> ! {
+ info!("Hello World!");
+
+ let 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: 7,
+ }),
+ conn_gap: Some(raw::ble_gap_conn_cfg_t {
+ conn_count: 20,
+ event_length: 180,
+ }),
+ conn_gatt: Some(raw::ble_gatt_conn_cfg_t { att_mtu: 114 }),
+ conn_gattc: Some(raw::ble_gattc_conn_cfg_t {
+ write_cmd_tx_queue_size: 0,
+ }),
+ conn_gatts: Some(raw::ble_gatts_conn_cfg_t {
+ hvn_tx_queue_size: 0,
+ }),
+ gatts_attr_tab_size: Some(raw::ble_gatts_cfg_attr_tab_size_t {
+ attr_tab_size: 1024,
+ }),
+ gap_role_count: Some(raw::ble_gap_cfg_role_count_t {
+ adv_set_count: 1,
+ periph_role_count: 5,
+ central_role_count: 15,
+ 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,
+ ),
+ }),
+ conn_l2cap: Some(raw::ble_l2cap_conn_cfg_t {
+ ch_count: 1,
+ rx_mps: 256,
+ tx_mps: 256,
+ rx_queue_size: 10,
+ tx_queue_size: 10,
+ }),
+ ..Default::default()
+ };
+
+ let (sdp, p) = take_peripherals();
+ let sd = Softdevice::enable(sdp, &config);
+
+ let executor = EXECUTOR.put(Executor::new(cortex_m::asm::sev));
+ unwrap!(executor.spawn(softdevice_task(sd)));
+ unwrap!(executor.spawn(bluetooth_task(sd, peripheral::Config::default())));
+
+ loop {
+ executor.run();
+ cortex_m::asm::wfe();
+ }
+}
diff --git a/examples/src/bin/ble_peripheral_onoff.rs b/examples/src/bin/ble_peripheral_onoff.rs
index 8476bca..625b895 100644
--- a/examples/src/bin/ble_peripheral_onoff.rs
+++ b/examples/src/bin/ble_peripheral_onoff.rs
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/bin/ble_scan.rs b/examples/src/bin/ble_scan.rs
index 021c5e0..4e54978 100644
--- a/examples/src/bin/ble_scan.rs
+++ b/examples/src/bin/ble_scan.rs
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/bin/flash.rs b/examples/src/bin/flash.rs
index c673d21..825a62b 100644
--- a/examples/src/bin/flash.rs
+++ b/examples/src/bin/flash.rs
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/bin/interrupts.rs b/examples/src/bin/interrupts.rs
index 5ec8f2e..1c777b5 100644
--- a/examples/src/bin/interrupts.rs
+++ b/examples/src/bin/interrupts.rs
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/bin/rtic.rs b/examples/src/bin/rtic.rs
index 08071e8..bc46c0e 100644
--- a/examples/src/bin/rtic.rs
+++ b/examples/src/bin/rtic.rs
@@ -12,6 +12,7 @@
#![no_main]
#![no_std]
#![feature(type_alias_impl_trait)]
+#![feature(alloc_error_handler)]
#[path = "../example_common.rs"]
mod example_common;
diff --git a/examples/src/example_common.rs b/examples/src/example_common.rs
index 8f4c2f2..7c8cdb1 100644
--- a/examples/src/example_common.rs
+++ b/examples/src/example_common.rs
@@ -5,9 +5,24 @@ use nrf_softdevice::pac;
use nrf_softdevice_defmt_rtt as _; // global logger
use panic_probe as _;
+use alloc_cortex_m::CortexMHeap;
+use core::alloc::Layout;
use core::sync::atomic::{AtomicUsize, Ordering};
use defmt::{panic, *};
+// this is the allocator the application will use
+#[global_allocator]
+static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
+
+// define what happens in an Out Of Memory (OOM) condition
+#[alloc_error_handler]
+fn alloc_error(_layout: Layout) -> ! {
+ panic!("Alloc error");
+ loop {}
+}
+
+const HEAP_SIZE: usize = 32 * 1024; // in bytes
+
#[defmt::timestamp]
fn timestamp() -> u64 {
static COUNT: AtomicUsize = AtomicUsize::new(0);
@@ -19,6 +34,9 @@ fn timestamp() -> u64 {
// Take peripherals, split by softdevice and application
pub fn take_peripherals() -> (nrf_softdevice::Peripherals, Peripherals) {
+ // Initialize the allocator BEFORE you use it
+ unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) }
+
let p = unwrap!(pac::Peripherals::take());
(