Skip to content

Commit

Permalink
Merge pull request #47 from embassy-rs/l2cap-features
Browse files Browse the repository at this point in the history
add features for l2cap pool size and queue len
  • Loading branch information
lulf authored May 23, 2024
2 parents 8908178 + ab50145 commit a2687b0
Show file tree
Hide file tree
Showing 15 changed files with 326 additions and 83 deletions.
2 changes: 1 addition & 1 deletion examples/apache-nimble/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async fn main(spawner: embassy_executor::Spawner) {
embassy_nrf::init(conf);
apache_nimble::initialize_nimble();

static HOST_RESOURCE: StaticCell<BleHostResources<2, 2, 2, 27>> = StaticCell::new();
static HOST_RESOURCE: StaticCell<BleHostResources<2, 2, 27>> = StaticCell::new();
let host_resources = HOST_RESOURCE.init(BleHostResources::new(PacketQos::None));

let controller = apache_nimble::controller::NimbleController::new();
Expand Down
8 changes: 2 additions & 6 deletions examples/nrf-sdc/src/bin/ble_advertise_multiple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ const CONNECTIONS_MAX: usize = 1;
/// Max number of L2CAP channels.
const L2CAP_CHANNELS_MAX: usize = 2; // Signal + att

/// Number of packets available in the pool
const PACKET_POOL_SIZE: usize = 10;

fn build_sdc<'d, const N: usize>(
p: nrf_sdc::Peripherals<'d>,
rng: &'d RngPool,
Expand Down Expand Up @@ -107,9 +104,8 @@ async fn main(spawner: Spawner) {
info!("Our address = {:02x}", my_addr());
Timer::after(Duration::from_millis(200)).await;

static HOST_RESOURCES: StaticCell<
BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, PACKET_POOL_SIZE, L2CAP_MTU>,
> = StaticCell::new();
static HOST_RESOURCES: StaticCell<BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU>> =
StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::None));

let mut ble: BleHost<'_, _> = BleHost::new(sdc, host_resources);
Expand Down
8 changes: 2 additions & 6 deletions examples/nrf-sdc/src/bin/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ const CONNECTIONS_MAX: usize = 1;
/// Max number of L2CAP channels.
const L2CAP_CHANNELS_MAX: usize = 2; // Signal + att

/// Number of packets available in the pool
const PACKET_POOL_SIZE: usize = 10;

fn build_sdc<'d, const N: usize>(
p: nrf_sdc::Peripherals<'d>,
rng: &'d RngPool,
Expand Down Expand Up @@ -105,9 +102,8 @@ async fn main(spawner: Spawner) {
info!("Our address = {:02x}", my_addr());
Timer::after(Duration::from_millis(200)).await;

static HOST_RESOURCES: StaticCell<
BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, PACKET_POOL_SIZE, L2CAP_MTU>,
> = StaticCell::new();
static HOST_RESOURCES: StaticCell<BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU>> =
StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::None));

let mut ble: BleHost<'_, _> = BleHost::new(sdc, host_resources);
Expand Down
10 changes: 3 additions & 7 deletions examples/nrf-sdc/src/bin/ble_l2cap_central.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ const CONNECTIONS_MAX: usize = 1;
/// Max number of L2CAP channels.
const L2CAP_CHANNELS_MAX: usize = 3; // Signal + att + CoC

/// Number of packets available in the pool
const PACKET_POOL_SIZE: usize = (L2CAP_TXQ + L2CAP_RXQ) as usize;

fn build_sdc<'d, const N: usize>(
p: nrf_sdc::Peripherals<'d>,
rng: &'d RngPool,
Expand Down Expand Up @@ -112,10 +109,9 @@ async fn main(spawner: Spawner) {
info!("Our address = {:02x}", my_addr());
Timer::after(Duration::from_millis(200)).await;

static HOST_RESOURCES: StaticCell<
BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, PACKET_POOL_SIZE, L2CAP_MTU>,
> = StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::Guaranteed(4)));
static HOST_RESOURCES: StaticCell<BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU>> =
StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::None));

let mut ble: BleHost<'_, _> = BleHost::new(sdc, host_resources);
ble.set_random_address(my_addr());
Expand Down
10 changes: 3 additions & 7 deletions examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ const CONNECTIONS_MAX: usize = 1;
/// Max number of L2CAP channels.
const L2CAP_CHANNELS_MAX: usize = 3; // Signal + att + CoC

/// Number of packets available in the pool
const PACKET_POOL_SIZE: usize = (L2CAP_TXQ + L2CAP_RXQ) as usize;

fn build_sdc<'d, const N: usize>(
p: nrf_sdc::Peripherals<'d>,
rng: &'d RngPool,
Expand Down Expand Up @@ -111,10 +108,9 @@ async fn main(spawner: Spawner) {
info!("Our address = {:02x}", my_addr());
Timer::after(Duration::from_millis(200)).await;

static HOST_RESOURCES: StaticCell<
BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, PACKET_POOL_SIZE, L2CAP_MTU>,
> = StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::Guaranteed(4)));
static HOST_RESOURCES: StaticCell<BleHostResources<CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU>> =
StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::None));

let mut ble: BleHost<'_, _> = BleHost::new(sdc, host_resources);
ble.set_random_address(my_addr());
Expand Down
2 changes: 1 addition & 1 deletion examples/serial-hci/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async fn main() {

let driver: SerialTransport<NoopRawMutex, _, _> = SerialTransport::new(reader, writer);
let controller: ExternalController<_, 10> = ExternalController::new(driver);
static HOST_RESOURCES: StaticCell<BleHostResources<2, 4, 32, 27>> = StaticCell::new();
static HOST_RESOURCES: StaticCell<BleHostResources<2, 4, 27>> = StaticCell::new();
let host_resources = HOST_RESOURCES.init(BleHostResources::new(PacketQos::None));

let mut ble: BleHost<'_, _> = BleHost::new(controller, host_resources);
Expand Down
31 changes: 28 additions & 3 deletions host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,35 @@ env_logger = "0.11"
critical-section = { version = "1", features = ["std"] }
static_cell = "2.1.0"

[features]
defmt = [ "dep:defmt" ]
gatt = []

[patch.crates-io]
bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "main" }
embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }


[features]
defmt = [ "dep:defmt" ]
gatt = []

# BEGIN AUTOGENERATED CONFIG FEATURES
# Generated by gen_config.py. DO NOT EDIT.
l2cap-rx-queue-size-1 = [] # Default
l2cap-rx-queue-size-2 = []
l2cap-rx-queue-size-4 = []
l2cap-rx-queue-size-8 = []
l2cap-rx-queue-size-16 = []
l2cap-rx-queue-size-32 = []
l2cap-rx-queue-size-64 = []

l2cap-rx-packet-pool-size-1 = []
l2cap-rx-packet-pool-size-2 = [] # Default
l2cap-rx-packet-pool-size-4 = []
l2cap-rx-packet-pool-size-8 = []
l2cap-rx-packet-pool-size-16 = []
l2cap-rx-packet-pool-size-32 = []
l2cap-rx-packet-pool-size-64 = []
l2cap-rx-packet-pool-size-128 = []
l2cap-rx-packet-pool-size-256 = []
l2cap-rx-packet-pool-size-512 = []

# END AUTOGENERATED CONFIG FEATURES
94 changes: 94 additions & 0 deletions host/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::collections::HashMap;
use std::fmt::Write;
use std::path::PathBuf;
use std::{env, fs};

static CONFIGS: &[(&str, usize)] = &[
// BEGIN AUTOGENERATED CONFIG FEATURES
// Generated by gen_config.py. DO NOT EDIT.
("L2CAP_RX_QUEUE_SIZE", 1),
("L2CAP_RX_PACKET_POOL_SIZE", 2),
// END AUTOGENERATED CONFIG FEATURES
];

struct ConfigState {
value: usize,
seen_feature: bool,
seen_env: bool,
}

fn main() {
let crate_name = env::var("CARGO_PKG_NAME")
.unwrap()
.to_ascii_uppercase()
.replace('-', "_");

// only rebuild if build.rs changed. Otherwise Cargo will rebuild if any
// other file changed.
println!("cargo:rerun-if-changed=build.rs");

// Rebuild if config envvar changed.
for (name, _) in CONFIGS {
println!("cargo:rerun-if-env-changed={crate_name}_{name}");
}

let mut configs = HashMap::new();
for (name, default) in CONFIGS {
configs.insert(
*name,
ConfigState {
value: *default,
seen_env: false,
seen_feature: false,
},
);
}

let prefix = format!("{crate_name}_");
for (var, value) in env::vars() {
if let Some(name) = var.strip_prefix(&prefix) {
let Some(cfg) = configs.get_mut(name) else {
panic!("Unknown env var {name}")
};

let Ok(value) = value.parse::<usize>() else {
panic!("Invalid value for env var {name}: {value}")
};

cfg.value = value;
cfg.seen_env = true;
}

if let Some(feature) = var.strip_prefix("CARGO_FEATURE_") {
if let Some(i) = feature.rfind('_') {
let name = &feature[..i];
let value = &feature[i + 1..];
if let Some(cfg) = configs.get_mut(name) {
let Ok(value) = value.parse::<usize>() else {
panic!("Invalid value for feature {name}: {value}")
};

// envvars take priority.
if !cfg.seen_env {
if cfg.seen_feature {
panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value);
}

cfg.value = value;
cfg.seen_feature = true;
}
}
}
}
}

let mut data = String::new();

for (name, cfg) in &configs {
writeln!(&mut data, "pub const {}: usize = {};", name, cfg.value).unwrap();
}

let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir.join("config.rs").to_string_lossy().to_string();
fs::write(out_file, data).unwrap();
}
82 changes: 82 additions & 0 deletions host/gen_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os

abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)

features = []


def feature(name, default, min=None, max=None, pow2=None, vals=None, factors=[]):
if vals is None:
assert min is not None
assert max is not None

vals = set()
val = min
while val <= max:
vals.add(val)
for f in factors:
if val*f <= max:
vals.add(val*f)
if (pow2 == True or (isinstance(pow2, int) and val >= pow2)) and val > 0:
val *= 2
else:
val += 1
vals.add(default)
vals = sorted(list(vals))

features.append(
{
"name": name,
"default": default,
"vals": vals,
}
)


feature("l2cap_rx_queue_size", default=1, min=1, max=64, pow2=True)
feature("l2cap_rx_packet_pool_size", default=2, min=1, max=512, pow2=True)

# ========= Update Cargo.toml

things = ""
for f in features:
name = f["name"].replace("_", "-")
for val in f["vals"]:
things += f"{name}-{val} = []"
if val == f["default"]:
things += " # Default"
things += "\n"
things += "\n"

SEPARATOR_START = "# BEGIN AUTOGENERATED CONFIG FEATURES\n"
SEPARATOR_END = "# END AUTOGENERATED CONFIG FEATURES\n"
HELP = "# Generated by gen_config.py. DO NOT EDIT.\n"
with open("Cargo.toml", "r") as f:
data = f.read()
before, data = data.split(SEPARATOR_START, maxsplit=1)
_, after = data.split(SEPARATOR_END, maxsplit=1)
data = before + SEPARATOR_START + HELP + things + SEPARATOR_END + after
with open("Cargo.toml", "w") as f:
f.write(data)


# ========= Update build.rs

things = ""
for f in features:
name = f["name"].upper()
things += f' ("{name}", {f["default"]}),\n'

SEPARATOR_START = "// BEGIN AUTOGENERATED CONFIG FEATURES\n"
SEPARATOR_END = "// END AUTOGENERATED CONFIG FEATURES\n"
HELP = " // Generated by gen_config.py. DO NOT EDIT.\n"
with open("build.rs", "r") as f:
data = f.read()
before, data = data.split(SEPARATOR_START, maxsplit=1)
_, after = data.split(SEPARATOR_END, maxsplit=1)
data = before + SEPARATOR_START + HELP + \
things + " " + SEPARATOR_END + after
with open("build.rs", "w") as f:
f.write(data)
57 changes: 57 additions & 0 deletions host/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! Compile-time configuration.
//!
//! `trouble` has some configuration settings that are set at compile time.
//!
//! They can be set in two ways:
//!
//! - Via Cargo features: enable a feature like `<name>-<value>`. `name` must be in lowercase and
//! use dashes instead of underscores. For example. `max-page-count-1024`. Only a selection of values
//! is available, check `Cargo.toml` for the list.
//! - Via environment variables at build time: set the variable named `TROUBLE_HOST_<value>`. For example
//! `TROUBLE_HOST_L2CAP_RX_QUEUE_SIZE=1 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`.
//! Any value can be set, unlike with Cargo features.
//!
//! Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting
//! with different values, compilation fails.
//!
//! ## Compatibility warning
//!
//! Changing ANY of these configuration settings changes the on-disk format of the database. If you change
//! them, you won't be able to read databases written with a different configuration.
//!
//! Currently, mounting doesn't check the on-disk database uses the same configuration. Mounting a database
//! with a different configuration might succeed and then cause fun errors later, perhaps very rarely.
//! Always remember to format your flash device every time you change them.
mod raw {
#![allow(unused)]
include!(concat!(env!("OUT_DIR"), "/config.rs"));
}

// ======== L2CAP parameters

/// L2CAP RX queue size
///
/// This is the rx queue size of every l2cap channel. Every channel have to be able
/// to buffer at least 1 packet, but if the controller already does buffering this
/// may be sufficient.
///
/// If the controller does not support rx buffering, increasing this value will allow
/// a higher throughput between the controller and host.
///
/// Default: 1.
pub const L2CAP_RX_QUEUE_SIZE: usize = raw::L2CAP_RX_QUEUE_SIZE;

/// L2CAP RX packet pool size
///
/// This is the rx packet pool size of every l2cap channel. There has to be at least
/// 1 packet that can be allocated, but the pool is shared among different channels.
///
/// If the rx queue size is adjusted, consider adjusting the rx packet pool size as well,
/// taking the number of channels and per-channel queue size into account.
///
/// Ensuring fair access to the pool is done configuring the QoS policy when creating
/// the host resources.
///
/// Default: 1.
pub const L2CAP_RX_PACKET_POOL_SIZE: usize = raw::L2CAP_RX_PACKET_POOL_SIZE;
Loading

0 comments on commit a2687b0

Please sign in to comment.