Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async ble #161

Merged
merged 3 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ jobs:

- name: build (ble)
run: cd examples-esp32 && cargo build --release --example=ble --features=ble
- name: build (async-ble)
run: cd examples-esp32 && cargo build --release --example=async_ble --features=async,ble
- name: build (dhcp)
run: cd examples-esp32 && cargo build --release --example=dhcp --features=embedded-svc,wifi
- name: build (static_ip)
Expand All @@ -53,70 +55,77 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/rust-toolchain@v1
with:
targets: riscv32imc-unknown-none-elf
target: riscv32imc-unknown-none-elf
toolchain: nightly-2023-03-09
components: rust-src
- uses: Swatinem/rust-cache@v1

- name: build (ble)
run: cd examples-esp32c2 && cargo build --release --example=ble --features=ble
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=ble --features=ble
- name: build (async-ble)
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=async_ble --features=async,ble
- name: build (dhcp)
run: cd examples-esp32c2 && cargo build --release --example=dhcp --features=embedded-svc,wifi
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=dhcp --features=embedded-svc,wifi
- name: build (static_ip)
run: cd examples-esp32c2 && cargo build --release --example=static_ip --features=embedded-svc,wifi
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=static_ip --features=embedded-svc,wifi
- name: build (esp_now)
run: cd examples-esp32c2 && cargo build --release --example=esp_now --features=esp-now
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=esp_now --features=esp-now
- name: build (embassy_esp_now)
run: cd examples-esp32c2 && cargo build --release --example=embassy_esp_now --features=async,esp-now
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=embassy_esp_now --features=async,esp-now
- name: build (embassy_dhcp)
run: cd examples-esp32c2 && cargo build --release --example=embassy_dhcp --features=async,embedded-svc,wifi,embassy-net
run: cd examples-esp32c2 && cargo +nightly-2023-03-09 build --release --example=embassy_dhcp --features=async,embedded-svc,wifi,embassy-net

esp32c3:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/rust-toolchain@v1
with:
targets: riscv32imc-unknown-none-elf
target: riscv32imc-unknown-none-elf
toolchain: nightly-2023-03-09
components: rust-src
- uses: Swatinem/rust-cache@v1

- name: build (ble)
run: cd examples-esp32c3 && cargo build --release --example=ble --features=ble
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=ble --features=ble
- name: build (async-ble)
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=async_ble --features=async,ble
- name: build (coex)
run: cd examples-esp32c3 && cargo build --release --example=coex --features=embedded-svc,wifi,ble
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=coex --features=embedded-svc,wifi,ble
- name: build (dhcp)
run: cd examples-esp32c3 && cargo build --release --example=dhcp --features=embedded-svc,wifi
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=dhcp --features=embedded-svc,wifi
- name: build (static_ip)
run: cd examples-esp32c3 && cargo build --release --example=static_ip --features=embedded-svc,wifi
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=static_ip --features=embedded-svc,wifi
- name: build (esp_now)
run: cd examples-esp32c3 && cargo build --release --example=esp_now --features=esp-now
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=esp_now --features=esp-now
- name: build (embassy_esp_now)
run: cd examples-esp32c3 && cargo build --release --example=embassy_esp_now --features=async,esp-now
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=embassy_esp_now --features=async,esp-now
- name: build (embassy_dhcp)
run: cd examples-esp32c3 && cargo build --release --example=embassy_dhcp --features=async,embedded-svc,wifi,embassy-net
run: cd examples-esp32c3 && cargo +nightly-2023-03-09 build --release --example=embassy_dhcp --features=async,embedded-svc,wifi,embassy-net

esp32c6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/rust-toolchain@v1
with:
targets: riscv32imac-unknown-none-elf
target: riscv32imac-unknown-none-elf
toolchain: nightly-2023-03-09
components: rust-src
- uses: Swatinem/rust-cache@v1

- name: build (dhcp)
run: cd examples-esp32c6 && cargo build --release --example=dhcp --features=embedded-svc,wifi
run: cd examples-esp32c6 && cargo +nightly-2023-03-09 build --release --example=dhcp --features=embedded-svc,wifi
- name: build (static_ip)
run: cd examples-esp32c6 && cargo build --release --example=static_ip --features=embedded-svc,wifi
run: cd examples-esp32c6 && cargo +nightly-2023-03-09 build --release --example=static_ip --features=embedded-svc,wifi
- name: build (esp_now)
run: cd examples-esp32c6 && cargo build --release --example=esp_now --features=esp-now
run: cd examples-esp32c6 && cargo +nightly-2023-03-09 build --release --example=esp_now --features=esp-now
- name: build (embassy_esp_now)
run: cd examples-esp32c6 && cargo build --release --example=embassy_esp_now --features=async,esp-now
run: cd examples-esp32c6 && cargo +nightly-2023-03-09 build --release --example=embassy_esp_now --features=async,esp-now
- name: build (embassy_dhcp)
run: cd examples-esp32c6 && cargo build --release --example=embassy_dhcp --features=async,embedded-svc,wifi,embassy-net
run: cd examples-esp32c6 && cargo +nightly-2023-03-09 build --release --example=embassy_dhcp --features=async,embedded-svc,wifi,embassy-net

esp32s2:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -153,6 +162,8 @@ jobs:

- name: build (ble)
run: cd examples-esp32s3 && cargo build --release --example=ble --features=ble
- name: build (async-ble)
run: cd examples-esp32s3 && cargo build --release --example=async_ble --features=async,ble
- name: build (coex)
run: cd examples-esp32s3 && cargo build --release --example=coex --features=embedded-svc,wifi,ble
- name: build (dhcp)
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ embassy-futures = { version = "0.1.0" }
embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a", features = ["nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a" }

bleps = { git = "https://github.com/bjoernQ/bleps", package = "bleps", rev = "33fde67257bfbc6c0aebf7649fd302c82ed94c64" }
bleps = { git = "https://github.com/bjoernQ/bleps", package = "bleps", rev = "daa341f4e5f40db8348886ab245f51902fccaa17" }
bleps-macros = { git = "https://github.com/bjoernQ/bleps", package = "bleps-macros", rev = "33fde67257bfbc6c0aebf7649fd302c82ed94c64" }
embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] }
embassy-time = { version = "0.1.0", features = ["nightly"] }
futures-util = { version = "0.3.17", default-features = false }
esp-println = { version = "0.4.0", features = ["log"] }
esp-backtrace = { version = "0.6.0", features = ["panic-handler", "exception-handler", "print-uart"] }
embedded-hal-async = { version = "0.2.0-alpha.0" }
19 changes: 14 additions & 5 deletions esp-wifi/src/ble/btdm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ extern "C" fn notify_host_recv(data: *mut u8, len: u16) -> i32 {
let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
queue.enqueue(packet).unwrap();
});

#[cfg(feature = "async")]
crate::ble::controller::asynch::hci_read_data_available();
}

0
Expand Down Expand Up @@ -522,18 +525,24 @@ static mut BLE_HCI_READ_DATA: [u8; 256] = [0u8; 256];
static mut BLE_HCI_READ_DATA_INDEX: usize = 0;
static mut BLE_HCI_READ_DATA_LEN: usize = 0;

#[cfg(feature = "async")]
pub fn have_hci_read_data() -> bool {
critical_section::with(|cs| {
let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
!queue.is_empty() || unsafe { BLE_HCI_READ_DATA_LEN > 0 && (BLE_HCI_READ_DATA_LEN >= BLE_HCI_READ_DATA_INDEX) }
})
}

pub fn read_hci(data: &mut [u8]) -> usize {
unsafe {
if BLE_HCI_READ_DATA_LEN == 0 {
critical_section::with(|cs| {
let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);

if let Some(packet) = queue.dequeue() {
for i in 0..(packet.len as usize + 0/*1*/) {
BLE_HCI_READ_DATA[i] = packet.data[i];
}

BLE_HCI_READ_DATA_LEN = packet.len as usize + 0 /*1*/;
BLE_HCI_READ_DATA[..packet.len as usize]
.copy_from_slice(&packet.data[..packet.len as usize]);
BLE_HCI_READ_DATA_LEN = packet.len as usize;
BLE_HCI_READ_DATA_INDEX = 0;
}
});
Expand Down
92 changes: 92 additions & 0 deletions esp-wifi/src/ble/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,95 @@ impl Write for BleConnector<'_> {
Ok(())
}
}

#[cfg(feature = "async")]
pub mod asynch {
use core::task::Poll;

use crate::ble::ble::have_hci_read_data;

use super::BleConnectorError;
use super::{read_hci, send_hci};
use embassy_sync::waitqueue::AtomicWaker;
use embedded_io::asynch;
use embedded_io::Io;
use esp_hal_common::peripheral::{Peripheral, PeripheralRef};

static HCI_WAKER: AtomicWaker = AtomicWaker::new();

pub(crate) fn hci_read_data_available() {
HCI_WAKER.wake();
}

pub struct BleConnector<'d> {
_device: PeripheralRef<'d, esp_hal_common::radio::Bluetooth>,
}

impl<'d> BleConnector<'d> {
pub fn new(
device: impl Peripheral<P = esp_hal_common::radio::Bluetooth> + 'd,
) -> BleConnector<'d> {
Self {
_device: device.into_ref(),
}
}
}

impl Io for BleConnector<'_> {
type Error = BleConnectorError;
}

impl asynch::Read for BleConnector<'_> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, BleConnectorError> {
if !have_hci_read_data() {
HciReadyEventFuture.await;
}

let mut total = 0;
for b in buf {
let mut buffer = [0u8];
let len = read_hci(&mut buffer);

if len == 1 {
*b = buffer[0];
total += 1;
} else {
return Ok(total);
}
}

Ok(total)
}
}

impl asynch::Write for BleConnector<'_> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, BleConnectorError> {
send_hci(buf);
Ok(buf.len())
}

async fn flush(&mut self) -> Result<(), BleConnectorError> {
// nothing to do
Ok(())
}
}

pub(crate) struct HciReadyEventFuture;

impl core::future::Future for HciReadyEventFuture {
type Output = ();

fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> {
HCI_WAKER.register(cx.waker());

if have_hci_read_data() {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
}
15 changes: 14 additions & 1 deletion esp-wifi/src/ble/npl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,9 @@ unsafe extern "C" fn ble_hs_hci_rx_evt(cmd: *const u8, arg: *const c_void) {
})
.unwrap();
});

#[cfg(feature = "async")]
crate::ble::controller::asynch::hci_read_data_available();
}

unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) {
Expand All @@ -1255,12 +1258,23 @@ unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) {
})
.unwrap();
});

#[cfg(feature = "async")]
crate::ble::controller::asynch::hci_read_data_available();
}

static mut BLE_HCI_READ_DATA: [u8; 256] = [0u8; 256];
static mut BLE_HCI_READ_DATA_INDEX: usize = 0;
static mut BLE_HCI_READ_DATA_LEN: usize = 0;

#[cfg(feature = "async")]
pub fn have_hci_read_data() -> bool {
critical_section::with(|cs| {
let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
!queue.is_empty() || unsafe { BLE_HCI_READ_DATA_LEN > 0 && (BLE_HCI_READ_DATA_LEN >= BLE_HCI_READ_DATA_INDEX) }
})
}

pub fn read_hci(data: &mut [u8]) -> usize {
unsafe {
if BLE_HCI_READ_DATA_LEN == 0 {
Expand All @@ -1274,7 +1288,6 @@ pub fn read_hci(data: &mut [u8]) -> usize {
BLE_HCI_READ_DATA_INDEX = 0;
}
});
return 0;
}

if BLE_HCI_READ_DATA_LEN > 0 {
Expand Down
13 changes: 4 additions & 9 deletions esp-wifi/src/ble/os_adapter_esp32c3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub(crate) fn create_ble_config() -> esp_bt_controller_config_t {
hci_tl_funcs: core::ptr::null_mut(),
txant_dft: 0,
rxant_dft: 0,
txpwr_dft: 7,
txpwr_dft: 9,
cfg_mask: 1,
scan_duplicate_mode: 0,
scan_duplicate_type: 0,
Expand All @@ -179,9 +179,7 @@ pub(crate) fn create_ble_config() -> esp_bt_controller_config_t {
pub(crate) unsafe extern "C" fn interrupt_on(intr_num: i32) {
trace!("interrupt_on {}", intr_num);

(*esp32c3::INTERRUPT_CORE0::PTR)
.cpu_int_enable
.modify(|r, w| w.bits(r.bits() | 1 << intr_num));
// NO-OP
}

pub(crate) unsafe extern "C" fn interrupt_off(_intr_num: i32) {
Expand Down Expand Up @@ -218,13 +216,10 @@ pub(crate) unsafe extern "C" fn interrupt_set(
interrupt_prio
);

((0x600c2000 + 0x114 + interrupt_no * 4) as *mut u32).write_volatile(interrupt_prio as u32);

/* Set the interrupt type (Edge or Level). */
// ----

/* Map the CPU interrupt ID to the peripheral. */
((0x600c2000 + intr_source * 4) as *mut u32).write_volatile(interrupt_no as u32);

// NO-OP
}

pub(crate) unsafe extern "C" fn interrupt_clear(_interrupt_source: i32, _interrupt_no: i32) {
Expand Down
2 changes: 2 additions & 0 deletions esp-wifi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![no_std]
#![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))]
#![feature(c_variadic)]
#![cfg_attr(feature = "async", feature(async_fn_in_trait))]
#![cfg_attr(feature = "async", allow(incomplete_features))]

use core::cell::RefCell;
use core::mem::MaybeUninit;
Expand Down
3 changes: 2 additions & 1 deletion examples-esp32/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ examples-util = { path = "../examples-util", features = ["esp32"] }
esp-println = { workspace = true, features = [ "esp32" ] }
esp-backtrace = { workspace = true, features = ["esp32"] }
esp-wifi = { path = "../esp-wifi", features = ["esp32"] }
embedded-hal-async = { workspace = true, optional = true }

[features]
default = ["esp32"]
esp32 = []
async = ["esp-wifi/esp32-async"]
async = ["esp-wifi/esp32-async", "bleps/async", "dep:embedded-hal-async", "esp32-hal/async"]
embassy-net = ["esp-wifi/embassy-net","dep:embassy-net"]
wifi-logs = ["esp-wifi/wifi-logs"]
dump-packets = ["esp-wifi/dump-packets"]
Expand Down
Loading