Skip to content

Commit 6f612f1

Browse files
authored
Merge pull request #10 from MabezDev/dma-circ-fixes
Dma circ fixes & idle line detection interrupt
2 parents 6dd7607 + ca09776 commit 6f612f1

File tree

3 files changed

+50
-41
lines changed

3 files changed

+50
-41
lines changed

examples/serial_dma.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ fn main() -> ! {
6767
for _ in 0..2 {
6868
while circ_buffer.readable_half().unwrap() != Half::First {}
6969

70-
let _first_half = circ_buffer.peek(|half, _| {
71-
*half
70+
let _first_half = circ_buffer.peek(|_buf, half| {
71+
half
7272
}).unwrap();
7373

7474
// asm::bkpt();
@@ -77,7 +77,7 @@ fn main() -> ! {
7777

7878
// asm::bkpt();
7979

80-
let _second_half = circ_buffer.peek(|half, _| *half).unwrap();
80+
let _second_half = circ_buffer.peek(|_buf, half| half).unwrap();
8181
}
8282

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

src/dma.rs

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -201,37 +201,8 @@ macro_rules! dma {
201201
}
202202

203203
impl<B> CircBuffer<B, $CX> {
204-
/// Peeks into the readable half of the buffer
205-
/// Returns the result of the closure
206-
pub fn peek<R, F>(&mut self, f: F) -> Result<R, Error>
207-
where
208-
F: FnOnce(&B, Half) -> R,
209-
{
210-
let half_being_read = self.readable_half()?;
211-
212-
let buf = match half_being_read {
213-
Half::First => &self.buffer[0],
214-
Half::Second => &self.buffer[1],
215-
};
216-
217-
// XXX does this need a compiler barrier?
218-
let ret = f(buf, half_being_read);
219-
220-
221-
let isr = self.channel.isr();
222-
let first_half_is_done = isr.$htifX().bit_is_set();
223-
let second_half_is_done = isr.$tcifX().bit_is_set();
224-
225-
if (half_being_read == Half::First && second_half_is_done) ||
226-
(half_being_read == Half::Second && first_half_is_done) {
227-
Err(Error::Overrun)
228-
} else {
229-
Ok(ret)
230-
}
231-
}
232-
233-
/// Partial Peek of the current state of the DMA buffer -> https://github.com/japaric/stm32f103xx-hal/issues/48#issuecomment-386683962
234-
/// Return type of closure is a tuple (bytes 'used', the partial_peek with return)
204+
205+
/// Return the partial contents of the buffer half being written
235206
pub fn partial_peek<R, F, T>(&mut self, f: F) -> Result<R, Error>
236207
where
237208
F: FnOnce(&[T], Half) -> Result<(usize, R), ()>,
@@ -242,40 +213,52 @@ macro_rules! dma {
242213
Half::First => &self.buffer[1],
243214
Half::Second => &self.buffer[0],
244215
};
245-
246216
// ,- half-buffer
247217
// [ x x x x y y y y y z | z z z z z z z z z z ]
248218
// ^- pending=11
249219
let pending = self.channel.get_cndtr() as usize; // available bytes in _whole_ buffer
250-
251220
let slice: &[T] = buf;
252221
let capacity = slice.len(); // capacity of _half_ a buffer
253222
// <--- capacity=10 --->
254223
// [ x x x x y y y y y z | z z z z z z z z z z ]
255-
256224
let pending = if pending > capacity {
257225
pending - capacity
258226
} else {
259227
pending
260228
};
261-
262229
// ,- half-buffer
263230
// [ x x x x y y y y y z | z z z z z z z z z z ]
264231
// ^- pending=1
265-
266232
let end = capacity - pending;
267233
// [ x x x x y y y y y z | z z z z z z z z z z ]
268234
// ^- end=9
269235
// ^- consumed_offset=4
270236
// [y y y y y] <-- slice
271237
let slice = &slice[self.consumed_offset..end];
272-
273238
match f(slice, self.readable_half) {
274239
Ok((l, r)) => { self.consumed_offset += l; Ok(r) },
275240
Err(_) => Err(Error::BufferError),
276241
}
277242
}
278243

244+
/// Peeks into the readable half of the buffer
245+
/// Returns the result of the closure
246+
pub fn peek<R, F, T>(&mut self, f: F) -> Result<R, Error>
247+
where
248+
F: FnOnce(&[T], Half) -> R,
249+
B: Unsize<[T]>,
250+
{
251+
let half_being_read = self.readable_half()?;
252+
let buf = match half_being_read {
253+
Half::First => &self.buffer[0],
254+
Half::Second => &self.buffer[1],
255+
};
256+
let slice: &[T] = buf;
257+
let slice = &slice[self.consumed_offset..];
258+
self.consumed_offset = 0;
259+
Ok(f(slice, half_being_read))
260+
}
261+
279262
/// Returns the `Half` of the buffer that can be read
280263
pub fn readable_half(&mut self) -> Result<Half, Error> {
281264
let isr = self.channel.isr();

src/serial.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ pub enum Event {
2222
Rxne,
2323
/// New data can be sent
2424
Txe,
25+
/// The line has gone idle
26+
Idle
2527
}
2628

2729
/// Serial error
@@ -128,6 +130,9 @@ macro_rules! hal {
128130
Event::Txe => {
129131
self.usart.cr1.modify(|_, w| w.txeie().set_bit())
130132
},
133+
Event::Idle => {
134+
self.usart.cr1.modify(|_, w| w.idleie().set_bit())
135+
},
131136
}
132137
}
133138

@@ -140,6 +145,9 @@ macro_rules! hal {
140145
Event::Txe => {
141146
self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
142147
},
148+
Event::Idle => {
149+
self.usart.cr1.modify(|_, w| w.idleie().clear_bit())
150+
},
143151
}
144152
}
145153

@@ -224,7 +232,7 @@ macro_rules! hal {
224232

225233
impl Rx<$USARTX> {
226234
pub fn circ_read<B>(
227-
self,
235+
&self,
228236
mut chan: $rx_chan,
229237
buffer: &'static mut [B; 2],
230238
) -> CircBuffer<B, $rx_chan>
@@ -281,6 +289,24 @@ macro_rules! hal {
281289

282290
CircBuffer::new(buffer, chan)
283291
}
292+
293+
/// Checks to see if the usart peripheral has detected an idle line and clears the flag
294+
pub fn is_idle(&mut self, clear: bool) -> bool {
295+
let isr = unsafe { &(*$USARTX::ptr()).isr.read() };
296+
let icr = unsafe { &(*$USARTX::ptr()).icr };
297+
298+
if isr.idle().bit_is_set() {
299+
if clear {
300+
icr.write(|w| {
301+
w.idlecf()
302+
.set_bit()
303+
});
304+
}
305+
true
306+
} else {
307+
false
308+
}
309+
}
284310
}
285311
)+
286312
}

0 commit comments

Comments
 (0)