Skip to content

Commit

Permalink
Merge pull request #4 from embassy-rs/serial-example
Browse files Browse the repository at this point in the history
Update serial example to work
  • Loading branch information
lulf authored Mar 21, 2024
2 parents 191299d + b72fdc2 commit d0593e7
Show file tree
Hide file tree
Showing 20 changed files with 463 additions and 339 deletions.
6 changes: 3 additions & 3 deletions examples/nrf-sdc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", branch =
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
embassy-embedded-hal = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "main" }
nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "main" }
bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "main" }
nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "update-api" }
nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "update-api" }
bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "serial-controller" }

#embassy-executor = {path = "../../../embassy/embassy-executor"}
#embassy-nrf = {path = "../../../embassy/embassy-nrf"}
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf-sdc/src/bin/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]

use bt_hci::cmd::SyncCmd;
use bt_hci::param::BdAddr;
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf-sdc/src/bin/ble_l2cap_central.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]

use bt_hci::cmd::SyncCmd;
use bt_hci::param::BdAddr;
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]

use bt_hci::cmd::SyncCmd;
use bt_hci::param::BdAddr;
Expand Down
8 changes: 8 additions & 0 deletions examples/rp-pico-w/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip RP2040"

[build]
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+

[env]
DEFMT_LOG = "debug"
59 changes: 59 additions & 0 deletions examples/rp-pico-w/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "rp-pico-w"
version = "0.1.0"
edition = "2021"

[dependencies]
bt-hci = { version = "0.1.0", default-features = false, features = ["defmt"] }
trouble-host = { version = "0.1.0", path = "../../host", features = ["defmt"] }

embassy-embedded-hal = { version = "0.1.0", features = ["defmt"] }
embassy-sync = { version = "0.5.0", features = ["defmt"] }
embassy-executor = { version = "0.5.0", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.0", features = ["defmt-timestamp-uptime"] }
embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] }
embassy-futures = { version = "0.1.0" }
cyw43 = { version = "0.1.0", features = ["firmware-logs"] }
cyw43-pio = { version = "0.1.0", features = ["overclock"] }

defmt = "0.3"
defmt-rtt = "0.4"
fixed = "1.23.1"
fixed-macro = "1.2"

#cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m = { version = "0.7.6", features = ["inline-asm"] }
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] }
byte-slice-cast = { version = "1.2.0", default-features = false }
heapless = "0.8"
usbd-hid = "0.7.0"

embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = "1.0"
embedded-hal-bus = { version = "0.1", features = ["async"] }
embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
embedded-io = { version = "0.6.1", features = ["defmt-03"] }
embedded-storage = { version = "0.3" }
static_cell = "2"
portable-atomic = { version = "1.5", features = ["critical-section"] }
pio-proc = "0.2"
pio = "0.2.1"
rand = { version = "0.8.5", default-features = false }

[profile.release]
debug = 2

[patch.crates-io]
#bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "serial-controller" }
embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
embassy-embedded-hal = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
embassy-rp = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
cyw43 = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
cyw43-pio = { git = "https://github.com/embassy-rs/embassy.git", branch = "pico-bluetooth" }
#embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
bt-hci = { path = "../../../bt-hci" }
36 changes: 36 additions & 0 deletions examples/rp-pico-w/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());

// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");

println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tlink-rp.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}
17 changes: 17 additions & 0 deletions examples/rp-pico-w/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100

/* Pick one of the two options for RAM layout */

/* OPTION A: Use all RAM banks as one big block */
/* Reasonable, unless you are doing something */
/* really particular with DMA or other concurrent */
/* access that would benefit from striping */
RAM : ORIGIN = 0x20000000, LENGTH = 264K

/* OPTION B: Keep the unstriped sections separate */
/* RAM: ORIGIN = 0x20000000, LENGTH = 256K */
/* SCRATCH_A: ORIGIN = 0x20040000, LENGTH = 4K */
/* SCRATCH_B: ORIGIN = 0x20041000, LENGTH = 4K */
}
167 changes: 167 additions & 0 deletions examples/rp-pico-w/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#![no_std]
#![no_main]
use bt_hci::driver::{HciController, HciDriver};
use bt_hci::{
data, param, Controller, ControllerCmdAsync, ControllerCmdSync, ControllerToHostPacket, FromHciBytes, PacketKind,
ReadHci, WithIndicator, WriteHci,
};
use core::cell::RefCell;
use core::future::{pending, Future};
use core::ops::DerefMut;
use cyw43_pio::PioSpi;
use defmt::{assert_eq, todo, *};
use embassy_executor::{Executor, Spawner};
use embassy_futures::join::join3;
use embassy_futures::yield_now;
use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::mutex::Mutex;
use embassy_time::{Duration, Timer};
use embedded_io_async::Read;
use static_cell::StaticCell;
use trouble_host::adapter::{Adapter, HostResources};
use trouble_host::advertise::{AdStructure, AdvertiseConfig, BR_EDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE};
use trouble_host::attribute::{AttributeTable, CharacteristicProp, Service, Uuid};
use trouble_host::PacketQos;
use {defmt_rtt as _, embassy_time as _, panic_probe as _};

bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
});

#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let fw = include_bytes!("../../../../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../../../../embassy/cyw43-firmware/43439A0_clm.bin");
let btfw = include_bytes!("../../../../embassy/cyw43-firmware/43439A0_btfw.bin");

// To make flashing faster for development, you may want to flash the firmwares independently
// at hardcoded addresses, instead of baking them into the program with `include_bytes!`:
// probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
// probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000
//let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) };
//let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) };

let pwr = Output::new(p.PIN_23, Level::Low);
let cs = Output::new(p.PIN_25, Level::High);
let mut pio = Pio::new(p.PIO0, Irqs);
let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);

static STATE: StaticCell<cyw43::State> = StaticCell::new();
let state = STATE.init(cyw43::State::new());
let (_net_device, mut control, runner) = cyw43::new_with_bluetooth(state, pwr, spi, fw, btfw).await;

let driver = PicoWController::new(runner);
let controller: HciController<_, 10> = HciController::new(driver);
static HOST_RESOURCES: StaticCell<HostResources<NoopRawMutex, 4, 32, 27>> = StaticCell::new();
let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::None));

let adapter: Adapter<'_, NoopRawMutex, _, 2, 4, 1, 1> = Adapter::new(controller, host_resources);
let config = AdvertiseConfig {
params: None,
data: &[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[Uuid::Uuid16([0x0f, 0x18])]),
AdStructure::CompleteLocalName("Trouble PicoW"),
],
};

let mut table: AttributeTable<'_, NoopRawMutex, 10> = AttributeTable::new();

// Generic Access Service (mandatory)
let id = b"Trouble PicoW";
let appearance = [0x80, 0x07];
let mut bat_level = [0; 1];
let handle = {
let mut svc = table.add_service(Service::new(0x1800));
let _ = svc.add_characteristic_ro(0x2a00, id);
let _ = svc.add_characteristic_ro(0x2a01, &appearance[..]);
drop(svc);

// Generic attribute service (mandatory)
table.add_service(Service::new(0x1801));

// Battery service
let mut svc = table.add_service(Service::new(0x180f));

svc.add_characteristic(
0x2a19,
&[CharacteristicProp::Read, CharacteristicProp::Notify],
&mut bat_level,
)
};

let server = adapter.gatt_server(&table);

info!("Starting advertising and GATT service");
let _ = join3(
adapter.run(),
async {
loop {
match server.next().await {
Ok(event) => {
info!("Gatt event: {:?}", event);
}
Err(e) => {
error!("Error processing GATT events: {:?}", e);
}
}
}
},
async {
let conn = adapter.advertise(&config).await.unwrap();
// Keep connection alive
let mut tick: u8 = 0;
loop {
Timer::after(Duration::from_secs(10)).await;
tick += 1;
server.notify(handle, &conn, &[tick]).await.unwrap();
}
},
)
.await;
}

struct PicoWController {
runner: Mutex<NoopRawMutex, cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>>,
}

impl PicoWController {
pub fn new(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> Self {
Self {
runner: Mutex::new(runner),
}
}
}

#[derive(Debug, defmt::Format)]
pub struct Error;

impl embedded_io::Error for Error {
fn kind(&self) -> embedded_io::ErrorKind {
embedded_io::ErrorKind::Other
}
}

impl HciDriver for PicoWController {
type Error = Error;
fn read(&self, rx: &mut [u8]) -> impl Future<Output = Result<usize, Self::Error>> {
async {
let mut runner = self.runner.lock().await;
let n = runner.hci_read(rx).await as usize;
Ok(n)
}
}

fn write(&self, tx: &[u8]) -> impl Future<Output = Result<(), Self::Error>> {
async {
let mut runner = self.runner.lock().await;
runner.hci_write(tx).await;
Ok(())
}
}
}
19 changes: 9 additions & 10 deletions examples/serial-hci/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ env_logger = "0.10.0"
log = "0.4"
crossterm = "0.27.0"
rand_core = { version = "0.6.4", features = ["std"] }
embassy-executor = { version = "0.5.0", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] }
embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] }
# embassy-executor = { version = "0.5.0", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] }
embedded-io-adapters = { version = "0.6.1", features = ["tokio-1"] }
embedded-io-async = { version = "0.6.1" }
embassy-time = { version = "0.3.0", features = ["log", "std", ] }
embassy-sync = { version = "0.5.0", features = ["log"] }
critical-section = { version = "1.1", features = ["std"] }
embassy-futures = { version = "0.1" }
nix = "0.26.2"
async-io = "1.6.0"
static_cell = "2"
futures = { version = "0.3.17" }
tokio = { version = "1", features = ["full"] }
tokio-serial = "5.4"

bt-hci = { version = "0.1.0", default-features = false } #features = ["log"] }
trouble-host = { version = "0.1.0", path = "../../host" } #, features = ["log"] }
bt-hci = { version = "0.1.0", default-features = false, features = ["log"] }
trouble-host = { version = "0.1.0", path = "../../host", features = ["log"] }

[patch.crates-io]
bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "main" }
bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "serial-controller" }
embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
#embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
#bt-hci = { path = "../../../bt-hci" }
Loading

0 comments on commit d0593e7

Please sign in to comment.