Skip to content

Commit 589f5c8

Browse files
authored
Merge pull request #242 from DrTobe/circbuffer-rewrite
Redesigning dma::CircBuffer as suggested in issue #205
2 parents 8b7f4ee + 84b6e6a commit 589f5c8

File tree

5 files changed

+188
-239
lines changed

5 files changed

+188
-239
lines changed

examples/serial_dma.rs

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extern crate stm32l4xx_hal as hal;
1818
// #[macro_use(block)]
1919
// extern crate nb;
2020

21-
use crate::hal::dma::{CircReadDma, Half};
21+
use crate::hal::dma::CircReadDma;
2222
use crate::hal::prelude::*;
2323
use crate::hal::serial::{Config, Serial};
2424
use crate::rt::ExceptionFrame;
@@ -59,34 +59,66 @@ fn main() -> ! {
5959
);
6060
let (mut tx, rx) = serial.split();
6161

62-
let sent = b'X';
63-
64-
// The `block!` macro makes an operation block until it finishes
65-
// NOTE the error type is `!`
66-
67-
block!(tx.write(sent)).ok();
68-
69-
let buf = singleton!(: [[u8; 8]; 2] = [[0; 8]; 2]).unwrap();
70-
62+
let buf = singleton!(: [u8; 9] = [0; 9]).unwrap();
7163
let mut circ_buffer = rx.with_dma(channels.5).circ_read(buf);
64+
let mut rx_buf = [0; 9];
65+
66+
// single byte send/receive
67+
send(&mut tx, b"x");
68+
let rx_len = circ_buffer.read(&mut rx_buf).unwrap();
69+
assert_eq!(rx_len, 1);
70+
assert_eq!(&rx_buf[..1], b"x");
71+
72+
// multi byte send/receive
73+
send(&mut tx, b"12345678");
74+
let rx_len = circ_buffer.read(&mut rx_buf).unwrap();
75+
assert_eq!(rx_len, 8);
76+
assert_eq!(&rx_buf[..8], b"12345678");
77+
78+
// Checking three types of overflow detection
79+
// 1. write pointer passes read pointer
80+
send(&mut tx, b"12345678"); // write-pointer -> 8
81+
let rx_len = circ_buffer.read(&mut rx_buf[..1]).unwrap(); // read-pointer -> 1
82+
assert_eq!(rx_len, 1);
83+
send(&mut tx, b"12"); // write-pointer -> 1 (catches up with read-pointer)
84+
let rx_res = circ_buffer.read(&mut rx_buf[..1]);
85+
if let Err(hal::dma::Error::Overrun) = rx_res {
86+
} else {
87+
panic!("An overrun should have been detected");
88+
}
7289

73-
for _ in 0..2 {
74-
while circ_buffer.readable_half().unwrap() != Half::First {}
75-
76-
let _first_half = circ_buffer.peek(|_buf, half| half).unwrap();
77-
78-
// asm::bkpt();
79-
80-
while circ_buffer.readable_half().unwrap() != Half::Second {}
81-
82-
// asm::bkpt();
83-
84-
let _second_half = circ_buffer.peek(|_buf, half| half).unwrap();
90+
// 2. transfer complete flag set but it looks like the write-pointer did not pass 0
91+
send(&mut tx, b"123456789"); // write-pointer stays 1, transfer complete flag set
92+
send(&mut tx, b"1234"); // write-pointer -> 5
93+
let rx_res = circ_buffer.read(&mut rx_buf[..]);
94+
if let Err(hal::dma::Error::Overrun) = rx_res {
95+
} else {
96+
panic!("An overrun should have been detected");
8597
}
8698

87-
// let received = block!(rx.read()).unwrap();
99+
// 3a. half complete flag set but it looks like the write-ptr did not pass ceil(capacity/2) = 5
100+
send(&mut tx, b"123456789"); // write-pointer stays 5, all flags set
101+
send(&mut tx, b"12345678"); // write-pointer -> 4
102+
let rx_res = circ_buffer.read(&mut rx_buf[..]);
103+
if let Err(hal::dma::Error::Overrun) = rx_res {
104+
} else {
105+
panic!("An overrun should have been detected");
106+
}
88107

89-
// assert_eq!(received, sent);
108+
// 3b. check that the half complete flag is not yet set at write-pointer = floor(capacity/2) = 4
109+
send(&mut tx, b"1234"); // write-pointer -> 0
110+
circ_buffer.read(&mut rx_buf[..]).unwrap(); // read something to prevent overrun
111+
send(&mut tx, b"12345"); // write-pointer -> 4
112+
circ_buffer
113+
.read(&mut rx_buf[..])
114+
.expect("No overrun should be detected here");
115+
116+
// Undetectable overrun
117+
send(&mut tx, b"123456789");
118+
send(&mut tx, b"abcdefgh"); // overrun but it looks like only 8 bytes have been written
119+
let rx_len = circ_buffer.read(&mut rx_buf[..]).unwrap();
120+
assert_eq!(rx_len, 8);
121+
assert_eq!(&rx_buf[..8], b"abcdefgh");
90122

91123
// if all goes well you should reach this breakpoint
92124
asm::bkpt();
@@ -96,6 +128,19 @@ fn main() -> ! {
96128
}
97129
}
98130

131+
fn send(tx: &mut impl embedded_hal::serial::Write<u8>, data: &[u8]) {
132+
for byte in data {
133+
if let Err(_) = block!(tx.write(*byte)) {
134+
panic!("serial tx failed");
135+
}
136+
}
137+
138+
// waste some time so that the data will be received completely
139+
for i in 0..10000 {
140+
cortex_m::asm::nop();
141+
}
142+
}
143+
99144
#[exception]
100145
fn HardFault(ef: &ExceptionFrame) -> ! {
101146
panic!("{:#?}", ef);

examples/serial_dma_partial_peek.rs

Lines changed: 0 additions & 100 deletions
This file was deleted.

examples/serial_dma_us2.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extern crate stm32l4xx_hal as hal;
1818
// #[macro_use(block)]
1919
// extern crate nb;
2020

21-
use crate::hal::dma::{CircReadDma, Half};
21+
use crate::hal::dma::CircReadDma;
2222
use crate::hal::prelude::*;
2323
use crate::hal::serial::{Config, Serial};
2424
use crate::rt::ExceptionFrame;
@@ -65,23 +65,14 @@ fn main() -> ! {
6565

6666
block!(tx.write(sent)).ok();
6767

68-
let buf = singleton!(: [[u8; 8]; 2] = [[0; 8]; 2]).unwrap();
68+
let buf = singleton!(: [u8; 8] = [0; 8]).unwrap();
6969

7070
let mut circ_buffer = rx.with_dma(channels.6).circ_read(buf);
7171

72-
for _ in 0..2 {
73-
while circ_buffer.readable_half().unwrap() != Half::First {}
72+
let mut rx_buf = [0; 8];
73+
let rx_len = circ_buffer.read(&mut rx_buf).unwrap();
7474

75-
let _first_half = circ_buffer.peek(|_buf, half| half).unwrap();
76-
77-
// asm::bkpt();
78-
79-
while circ_buffer.readable_half().unwrap() != Half::Second {}
80-
81-
// asm::bkpt();
82-
83-
let _second_half = circ_buffer.peek(|_buf, half| half).unwrap();
84-
}
75+
let _received = &rx_buf[..rx_len];
8576

8677
// let received = block!(rx.read()).unwrap();
8778

0 commit comments

Comments
 (0)