summaryrefslogtreecommitdiffstats
path: root/ble/src
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-08-19 21:06:42 -0400
committerBrian Cully <bjc@kublai.com>2019-08-19 21:06:42 -0400
commit784db2bc6ca1dac88a60fcf5919ae5f7fa98f688 (patch)
treeaa8a5e5ca7ae0af26d03f4bc98c2fa4905d56a80 /ble/src
parenta3b976df4b1214c6f4e2a053724398b1a5e1767b (diff)
downloadbleusb-784db2bc6ca1dac88a60fcf5919ae5f7fa98f688.tar.gz
bleusb-784db2bc6ca1dac88a60fcf5919ae5f7fa98f688.zip
Clumsy, but BLE advertising is up.
Diffstat (limited to 'ble/src')
-rw-r--r--ble/src/ble.rs122
-rw-r--r--ble/src/main.rs9
2 files changed, 120 insertions, 11 deletions
diff --git a/ble/src/ble.rs b/ble/src/ble.rs
index e5f16cb..ac3542f 100644
--- a/ble/src/ble.rs
+++ b/ble/src/ble.rs
@@ -1,6 +1,22 @@
-use nrf52840_hal::target::{FICR, RADIO, TIMER0};
-use rubble::link::{AddressKind, DeviceAddress, HardwareInterface, LinkLayer, MIN_PDU_BUF};
-use rubble_nrf52::{radio::BleRadio, timer::BleTimer};
+use bbqueue::{bbq, BBQueue};
+use core::{cell::RefCell, ops::DerefMut};
+use cortex_m::{self, interrupt::Mutex};
+use log::info;
+use nrf52840_hal::target::{interrupt, FICR, RADIO, TIMER0};
+use rubble::{
+ gatt::BatteryServiceAttrs,
+ l2cap::{BleChannelMap, L2CAPState},
+ link::{
+ ad_structure::AdStructure, queue, AddressKind, DeviceAddress, HardwareInterface, LinkLayer,
+ Responder, MIN_PDU_BUF,
+ },
+ security_manager::NoSecurity,
+ time::{Duration, Timer},
+};
+use rubble_nrf52::{
+ radio::{BleRadio, PacketBuffer},
+ timer::BleTimer,
+};
struct NRF52840 {}
impl HardwareInterface for NRF52840 {
@@ -8,15 +24,31 @@ impl HardwareInterface for NRF52840 {
type Tx = BleRadio;
}
-pub fn setup(radio: RADIO, timer: TIMER0, ficr: FICR) {
+type Global<T> = Mutex<RefCell<Option<T>>>;
+
+static BLE_LL: Global<LinkLayer<NRF52840>> = Mutex::new(RefCell::new(None));
+static BLE_RADIO: Global<BleRadio> = Mutex::new(RefCell::new(None));
+
+pub fn setup(
+ radio: RADIO,
+ timer: TIMER0,
+ ficr: FICR,
+) -> Responder<BleChannelMap<BatteryServiceAttrs, NoSecurity>> {
// make sure hfclock is started for timer0 to work at the right
// resolution.
let ble_timer = BleTimer::init(timer);
- let mut devaddr = [0u8; 6];
- let devaddr_lo = ficr.deviceaddr[0].read().bits();
- let devaddr_hi = ficr.deviceaddr[1].read().bits();
- devaddr[..4].clone_from_slice(&devaddr_lo.to_le_bytes());
- devaddr[4..].clone_from_slice(&devaddr_hi.to_le_bytes());
+ let devaddr_lo: &[u8] = &ficr.deviceaddr[0].read().bits().to_le_bytes();
+ let devaddr_hi: &[u8] = &(ficr.deviceaddr[1].read().bits() as u16).to_le_bytes();
+
+ let mut devaddr: [u8; 6] = [0; 6];
+ for (i, a) in [devaddr_lo, devaddr_hi]
+ .iter()
+ .copied()
+ .flatten()
+ .enumerate()
+ {
+ devaddr[i] = *a;
+ }
let addrkind = if ficr.deviceaddrtype.read().deviceaddrtype().is_public() {
AddressKind::Public
@@ -24,5 +56,75 @@ pub fn setup(radio: RADIO, timer: TIMER0, ficr: FICR) {
AddressKind::Random
};
let addr = DeviceAddress::new(devaddr, addrkind);
- let mut _ll = LinkLayer::<NRF52840>::new(addr, ble_timer);
+ info!("my address: {:?}", addr);
+
+ static mut TX_BUF: PacketBuffer = [0; MIN_PDU_BUF];
+ static mut RX_BUF: PacketBuffer = [0; MIN_PDU_BUF];
+
+ let (tx_prod, tx_cons) = queue::create(bbq![MIN_PDU_BUF * 2].expect("creating tx queue"));
+ let (rx_prod, rx_cons) = queue::create(bbq![MIN_PDU_BUF * 2].expect("creating rx queue"));
+
+ // `responder` used on main loop.
+ let resp = Responder::new(
+ tx_prod,
+ rx_cons,
+ L2CAPState::new(BleChannelMap::with_attributes(BatteryServiceAttrs::new())),
+ );
+
+ // `ble_radio` and `ll` used on both `timer` and `radio`
+ // interrupts.
+ // may be able to use ring buffer to avoid sharing?
+ let mut ble_radio = unsafe { BleRadio::new(radio, &mut TX_BUF, &mut RX_BUF) };
+
+ let mut ble_ll = LinkLayer::<NRF52840>::new(addr, ble_timer);
+ let next_update = ble_ll
+ .start_advertise(
+ Duration::from_millis(200),
+ &[AdStructure::CompleteLocalName("bleusb")],
+ &mut ble_radio,
+ tx_cons,
+ rx_prod,
+ )
+ .expect("scheduling link layer update");
+ ble_ll.timer().configure_interrupt(next_update);
+
+ cortex_m::interrupt::free(|cs| {
+ BLE_LL.borrow(cs).replace(Some(ble_ll));
+ BLE_RADIO.borrow(cs).replace(Some(ble_radio));
+ });
+
+ resp
+}
+
+#[interrupt]
+fn TIMER0() {
+ cortex_m::interrupt::free(|cs| {
+ if let (Some(ref mut ble_ll), Some(ref mut ble_radio)) = (
+ BLE_LL.borrow(cs).borrow_mut().deref_mut(),
+ BLE_RADIO.borrow(cs).borrow_mut().deref_mut(),
+ ) {
+ if !ble_ll.timer().is_interrupt_pending() {
+ return;
+ }
+ ble_ll.timer().clear_interrupt();
+
+ let cmd = ble_ll.update(ble_radio);
+ ble_radio.configure_receiver(cmd.radio);
+
+ ble_ll.timer().configure_interrupt(cmd.next_update);
+ }
+ })
+}
+
+#[interrupt]
+fn RADIO() {
+ cortex_m::interrupt::free(|cs| {
+ if let (Some(ref mut ble_ll), Some(ref mut ble_radio)) = (
+ BLE_LL.borrow(cs).borrow_mut().deref_mut(),
+ BLE_RADIO.borrow(cs).borrow_mut().deref_mut(),
+ ) {
+ let next_update = ble_radio.recv_interrupt(ble_ll.timer().now(), ble_ll);
+ ble_ll.timer().configure_interrupt(next_update);
+ }
+ })
}
diff --git a/ble/src/main.rs b/ble/src/main.rs
index 36c3228..137c8a7 100644
--- a/ble/src/main.rs
+++ b/ble/src/main.rs
@@ -83,7 +83,7 @@ fn main() -> ! {
let uarte1 = uarte1(nrf52.UARTE1, txp, rxp);
let (mut uarte1_reader, mut uarte1_handler) = uarte1::setup(uarte1);
- //ble::setup(nrf52.RADIO, nrf52.TIMER0, nrf52.FICR);
+ let mut resp = ble::setup(nrf52.RADIO, nrf52.TIMER0, nrf52.FICR);
HANDLERS.with_overrides(|hs| {
hs.register(0, &mut rtc_handler);
@@ -93,6 +93,9 @@ fn main() -> ! {
hs.register(2, &mut uarte1_handler);
nvic.enable(Interrupt::UARTE1);
+ nvic.enable(Interrupt::TIMER0);
+ nvic.enable(Interrupt::RADIO);
+
info!("Bootstrap complete.");
// Buffer is just scratch space that always gets written to
@@ -122,6 +125,10 @@ fn main() -> ! {
);
len = uarte1_reader.shift_into(&mut buf);
}
+
+ if resp.has_work() {
+ resp.process_one().expect("ble response processing");
+ }
wfi();
}
});