Skip to content

Commit 3765065

Browse files
authored
Merge pull request #81 from torfmaster/feature/heapless-ble
Remove unnecessary usage of heap in BLE implememtation.
2 parents 301e215 + 2cc6422 commit 3765065

8 files changed

+99
-46
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ This script does the following steps for you:
7676

7777
## Running the Integration Tests
7878
Having an nRF52-DK board at hand, integration tests can be run using `./run_hardware_tests.sh`.
79+
The pins P0.03 and P0.04 need to be connected (on a nRF52-DK).
7980
The expected output on the UART console will be as follows.
8081
```
8182
[test-results]

examples/adc_buffer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() {
1515
let adc_buffer = libtock::adc::Adc::init_buffer(&mut adc_buffer).unwrap();
1616

1717
let mut with_callback = adc::with_callback(|_, _| {
18-
adc_buffer.read_bytes(&mut temp_buffer);
18+
adc_buffer.read_bytes(&mut temp_buffer[..]);
1919
writeln!(console, "First sample in buffer: {}", temp_buffer[0]).unwrap();
2020
});
2121

examples/ble_scanning.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main() {
2222
let shared_memory = BleDriver::share_memory(&mut shared_buffer).unwrap();
2323

2424
let mut callback = BleCallback::new(|_: usize, _: usize| {
25-
shared_memory.read_bytes(&mut my_buffer);
25+
shared_memory.read_bytes(&mut my_buffer[..]);
2626
ble_parser::find(&my_buffer, simple_ble::gap_data::SERVICE_DATA as u8)
2727
.and_then(|service_data| ble_parser::extract_for_service([91, 79], service_data))
2828
.and_then(|payload| corepack::from_bytes::<LedCommand>(&payload).ok())

examples/simple_ble.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,21 @@ fn main() {
2424

2525
let mut buffer = BleAdvertisingDriver::create_advertising_buffer();
2626
let mut gap_payload = BlePayload::new();
27-
gap_payload.add_flag(ble_composer::flags::LE_GENERAL_DISCOVERABLE);
28-
29-
gap_payload.add(ble_composer::gap_types::UUID, &uuid);
30-
31-
gap_payload.add(
32-
ble_composer::gap_types::COMPLETE_LOCAL_NAME,
33-
"Tock!".as_bytes(),
34-
);
35-
gap_payload.add_service_payload([91, 79], &payload);
27+
gap_payload
28+
.add_flag(ble_composer::flags::LE_GENERAL_DISCOVERABLE)
29+
.unwrap();
30+
31+
gap_payload
32+
.add(ble_composer::gap_types::UUID, &uuid)
33+
.unwrap();
34+
35+
gap_payload
36+
.add(
37+
ble_composer::gap_types::COMPLETE_LOCAL_NAME,
38+
"Tock!".as_bytes(),
39+
)
40+
.unwrap();
41+
gap_payload.add_service_payload([91, 79], &payload).unwrap();
3642

3743
let handle = BleAdvertisingDriver::initialize(100, &gap_payload, &mut buffer).unwrap();
3844

src/ble_composer.rs

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use alloc::vec::Vec;
2-
31
pub mod gap_types {
42
pub static COMPLETE_LOCAL_NAME: u8 = 0x09;
53
pub static SERVICE_DATA: u8 = 0x16;
@@ -12,56 +10,104 @@ pub mod flags {
1210
}
1311

1412
pub struct BlePayload {
15-
pub bytes: Vec<u8>,
13+
bytes: [u8; 39],
14+
occupied: usize,
1615
}
1716

1817
impl BlePayload {
19-
pub fn add(&mut self, kind: u8, content: &[u8]) {
20-
self.bytes.push((content.len() + 1) as u8);
21-
self.bytes.push(kind);
22-
for e in content {
23-
self.bytes.push(*e);
24-
}
18+
pub fn add(&mut self, kind: u8, content: &[u8]) -> Result<(), ()> {
19+
self.check_can_write_num_bytes(content.len() + 2)?;
20+
21+
self.bytes[self.occupied] = (content.len() + 1) as u8;
22+
self.bytes[self.occupied + 1] = kind;
23+
let write = &mut self.bytes[self.occupied + 2..(self.occupied + content.len() + 2)];
24+
write.clone_from_slice(content);
25+
self.occupied += 2 + content.len();
26+
Ok(())
2527
}
2628

27-
pub fn add_flag(&mut self, flag: u8) {
28-
self.bytes.push(2);
29-
self.bytes.push(gap_types::FLAGS);
30-
self.bytes.push(flag);
29+
pub fn add_flag(&mut self, flag: u8) -> Result<(), ()> {
30+
self.check_can_write_num_bytes(3)?;
31+
32+
self.bytes[self.occupied] = 2;
33+
self.bytes[self.occupied + 1] = gap_types::FLAGS;
34+
self.bytes[self.occupied + 2] = flag;
35+
self.occupied += 3;
36+
Ok(())
3137
}
3238

3339
pub fn new() -> Self {
34-
BlePayload { bytes: Vec::new() }
40+
BlePayload {
41+
bytes: [0; 39],
42+
occupied: 0,
43+
}
3544
}
3645

37-
pub fn add_service_payload(&mut self, uuid: [u8; 2], content: &[u8]) {
38-
self.bytes.push((content.len() + 3) as u8);
39-
self.bytes.push(gap_types::SERVICE_DATA);
40-
self.bytes.push(uuid[0]);
41-
self.bytes.push(uuid[1]);
42-
for e in content {
43-
self.bytes.push(*e);
46+
pub fn add_service_payload(&mut self, uuid: [u8; 2], content: &[u8]) -> Result<(), ()> {
47+
self.check_can_write_num_bytes(4 + content.len())?;
48+
self.bytes[self.occupied] = (content.len() + 3) as u8;
49+
self.bytes[self.occupied + 1] = gap_types::SERVICE_DATA;
50+
self.bytes[self.occupied + 2] = uuid[0];
51+
self.bytes[self.occupied + 3] = uuid[1];
52+
53+
let write = &mut self.bytes[self.occupied + 4..(self.occupied + content.len() + 4)];
54+
write.clone_from_slice(content);
55+
self.occupied += 4 + content.len();
56+
Ok(())
57+
}
58+
59+
fn check_can_write_num_bytes(&self, number: usize) -> Result<(), ()> {
60+
if self.occupied + number <= self.bytes.len() {
61+
Ok(())
62+
} else {
63+
Err(())
4464
}
4565
}
4666
}
4767

68+
impl AsRef<[u8]> for BlePayload {
69+
fn as_ref(&self) -> &[u8] {
70+
&self.bytes[0..self.occupied]
71+
}
72+
}
73+
4874
#[cfg(test)]
4975
mod test {
5076
use super::*;
5177

52-
use alloc::vec;
53-
5478
#[test]
55-
pub fn test_add() {
79+
fn test_add() {
5680
let mut pld = BlePayload::new();
5781
pld.add(1, &[2]);
58-
assert_eq!(pld.bytes, vec![2, 1, 2])
82+
assert_eq!(pld.as_ref().len(), 3);
83+
assert_eq!(pld.as_ref(), &mut [2, 1, 2])
5984
}
6085

6186
#[test]
62-
pub fn test_add_service_payload() {
87+
fn test_add_service_payload() {
6388
let mut pld = BlePayload::new();
6489
pld.add_service_payload([1, 2], &[2]);
65-
assert_eq!(pld.bytes, &[4, 0x16, 1, 2, 2])
90+
assert_eq!(pld.as_ref(), &[4, 0x16, 1, 2, 2])
91+
}
92+
93+
#[test]
94+
fn test_add_service_payload_two_times() {
95+
let mut pld = BlePayload::new();
96+
pld.add_service_payload([1, 2], &[2]);
97+
pld.add_service_payload([1, 2], &[2, 3]);
98+
99+
assert_eq!(pld.as_ref(), &[4, 0x16, 1, 2, 2, 5, 0x16, 1, 2, 2, 3])
100+
}
101+
102+
#[test]
103+
fn big_data_causes_error() {
104+
let mut pld = BlePayload::new();
105+
assert!(pld.add_service_payload([1, 2], &[0; 36]).is_err());
106+
}
107+
108+
#[test]
109+
fn initial_size_is_zero() {
110+
let pld = BlePayload::new();
111+
assert_eq!(pld.as_ref().len(), 0);
66112
}
67113
}

src/ble_parser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ mod test {
4545
use crate::simple_ble::BUFFER_SIZE_SCAN;
4646

4747
#[test]
48-
pub fn extracts_data_for_ids_correctly() {
48+
fn extracts_data_for_ids_correctly() {
4949
let mut buf = [0; BUFFER_SIZE_SCAN];
5050
{
5151
let slice = &mut buf[8..23];
@@ -62,7 +62,7 @@ mod test {
6262
}
6363

6464
#[test]
65-
pub fn doesnt_panic_for_defect_packets() {
65+
fn doesnt_panic_for_defect_packets() {
6666
let mut buf = [0; BUFFER_SIZE_SCAN];
6767
{
6868
let slice = &mut buf[8..18];
@@ -72,7 +72,7 @@ mod test {
7272
}
7373

7474
#[test]
75-
pub fn ignores_illegal_lengths_in_packets() {
75+
fn ignores_illegal_lengths_in_packets() {
7676
let mut buf = [0; 11];
7777
{
7878
let slice = &mut buf[8..10];

src/shared_memory.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ impl<'a> SharedMemory<'a> {
2020
}
2121
}
2222

23-
pub fn read_bytes(&self, destination: &mut [u8]) {
24-
safe_copy(self.buffer_to_share, destination);
23+
pub fn read_bytes<T: AsMut<[u8]>>(&self, mut destination: T) {
24+
safe_copy(self.buffer_to_share, destination.as_mut());
2525
}
2626

27-
pub fn write_bytes(&mut self, source: &[u8]) {
28-
safe_copy(source, self.buffer_to_share);
27+
pub fn write_bytes<T: AsRef<[u8]>>(&mut self, source: T) {
28+
safe_copy(source.as_ref(), self.buffer_to_share);
2929
}
3030
}
3131

src/simple_ble.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl BleAdvertisingDriver {
4545
ble_commands::ALLOW_ADVERTISMENT_BUFFER,
4646
advertising_buffer,
4747
)?;
48-
shared_memory.write_bytes(&service_payload.bytes);
48+
shared_memory.write_bytes(service_payload);
4949
Self::start_advertising(gap_flags::BLE_DISCOVERABLE, interval)?;
5050
Ok(shared_memory)
5151
}

0 commit comments

Comments
 (0)