Skip to content

Commit 3b4cc4b

Browse files
committed
Use embedded-dma traits for DMA buffers
1 parent e020ccc commit 3b4cc4b

File tree

3 files changed

+39
-202
lines changed

3 files changed

+39
-202
lines changed

examples/i2s-peripheral-demo/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ const RED: [u8; 9] = [0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x10, 0xFF];
2929
const APP: () = {
3030
struct Resources {
3131
rgb: Spim<SPIM0>,
32-
transfer: Option<Transfer<&'static mut [i16]>>,
32+
transfer: Option<Transfer<&'static mut [i16; 128]>>,
3333
}
3434

3535
#[init]
3636
fn init(ctx: init::Context) -> init::LateResources {
37-
static mut RX_BUF: [i16; 128] = [0i16; 128];
37+
static mut RX_BUF: [i16; 128] = [0; 128];
3838

3939
let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc();
4040
rtt_init_print!();
@@ -78,7 +78,7 @@ const APP: () = {
7878
);
7979
init::LateResources {
8080
rgb,
81-
transfer: i2s.rx(&mut RX_BUF[..]).ok(),
81+
transfer: i2s.rx(RX_BUF).ok(),
8282
}
8383
}
8484

@@ -87,7 +87,7 @@ const APP: () = {
8787
let (rx_buf, i2s) = ctx.resources.transfer.take().unwrap().wait();
8888
if i2s.is_event_triggered(I2SEvent::RxPtrUpdated) {
8989
i2s.reset_event(I2SEvent::RxPtrUpdated);
90-
// Calculate mono summed average of received buffer
90+
//Calculate mono summed average of received buffer
9191
let avg = (rx_buf.iter().map(|x| (*x).abs() as u32).sum::<u32>() / rx_buf.len() as u32)
9292
as u16;
9393
let color = match avg {

nrf-hal-common/Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ nb = "1.0.0"
2424
fixed = "1.0.0"
2525
rand_core = "0.5.1"
2626
cfg-if = "0.1.10"
27-
28-
[dependencies.stable_deref_trait]
29-
version = "1.2.0"
30-
default-features = false
27+
embedded-dma = "0.1.1"
3128

3229
[dependencies.void]
3330
default-features = false

nrf-hal-common/src/i2s.rs

Lines changed: 34 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ use crate::{
1010
pac::generic::Reg,
1111
target_constants::{SRAM_LOWER, SRAM_UPPER},
1212
};
13-
use core::{
14-
ops::{Deref, DerefMut},
15-
sync::atomic::{compiler_fence, Ordering},
16-
};
17-
pub use stable_deref_trait::StableDeref;
13+
use core::sync::atomic::{compiler_fence, Ordering};
14+
use embedded_dma::*;
1815

1916
use i2s::{_EVENTS_RXPTRUPD, _EVENTS_STOPPED, _EVENTS_TXPTRUPD, _TASKS_START, _TASKS_STOP};
2017

@@ -23,7 +20,7 @@ pub struct I2S {
2320
}
2421

2522
// I2S EasyDMA MAXCNT bit length = 14
26-
const MAX_DMA_MAXCNT: u32 = 16_384;
23+
const MAX_DMA_MAXCNT: u32 = 1 << 14;
2724

2825
impl I2S {
2926
/// Takes ownership of the raw I2S peripheral, returning a safe wrapper in controller mode.
@@ -265,23 +262,20 @@ impl I2S {
265262
/// Receives data into the given `buffer` until it's filled.
266263
/// Returns a value that represents the in-progress DMA transfer.
267264
#[allow(unused_mut)]
268-
pub fn rx<Word, B>(mut self, mut buffer: B) -> Result<Transfer<B>, Error>
265+
pub fn rx<W, B>(mut self, mut buffer: B) -> Result<Transfer<B>, Error>
269266
where
270-
Word: SupportedWordSize,
271-
B: DerefMut + StableDeref + 'static + I2SBuffer,
272-
B::Target: AsMut<[Word]>,
267+
B: WriteBuffer<Word = W>,
273268
{
274-
if buffer.maxcnt() > MAX_DMA_MAXCNT {
269+
let (ptr, len) = unsafe { buffer.write_buffer() };
270+
let maxcnt = (len / (core::mem::size_of::<u32>() / core::mem::size_of::<W>())) as u32;
271+
if maxcnt > MAX_DMA_MAXCNT {
275272
return Err(Error::BufferTooLong);
276273
}
277274
self.i2s
278275
.rxd
279276
.ptr
280-
.write(|w| unsafe { w.ptr().bits(buffer.ptr()) });
281-
self.i2s
282-
.rxtxd
283-
.maxcnt
284-
.write(|w| unsafe { w.bits(buffer.maxcnt()) });
277+
.write(|w| unsafe { w.ptr().bits(ptr as u32) });
278+
self.i2s.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
285279
Ok(Transfer {
286280
inner: Some(Inner { buffer, i2s: self }),
287281
})
@@ -292,42 +286,37 @@ impl I2S {
292286
/// into the given `rx_buffer` until it is filled. The buffers must be of equal size.
293287
/// Returns a value that represents the in-progress DMA transfer.
294288
#[allow(unused_mut)]
295-
pub fn transfer<Word, TxB, RxB>(
289+
pub fn transfer<W, TxB, RxB>(
296290
mut self,
297291
tx_buffer: TxB,
298292
mut rx_buffer: RxB,
299293
) -> Result<TransferFullDuplex<TxB, RxB>, Error>
300294
where
301-
Word: SupportedWordSize,
302-
TxB: Deref + StableDeref + 'static + I2SBuffer,
303-
TxB::Target: AsRef<[Word]>,
304-
RxB: DerefMut + StableDeref + 'static + I2SBuffer,
305-
RxB::Target: AsMut<[Word]>,
295+
TxB: ReadBuffer<Word = W>,
296+
RxB: WriteBuffer<Word = W>,
306297
{
307-
if (tx_buffer.ptr() as usize) < SRAM_LOWER || (tx_buffer.ptr() as usize) > SRAM_UPPER {
308-
return Err(Error::DMABufferNotInDataMemory);
309-
}
310-
if tx_buffer.maxcnt() != rx_buffer.maxcnt() {
298+
let (rx_ptr, rx_len) = unsafe { rx_buffer.write_buffer() };
299+
let (tx_ptr, tx_len) = unsafe { tx_buffer.read_buffer() };
300+
let maxcnt = (tx_len / (core::mem::size_of::<u32>() / core::mem::size_of::<W>())) as u32;
301+
if tx_len != rx_len {
311302
return Err(Error::BuffersDontMatch);
312303
}
313-
if tx_buffer.maxcnt() > MAX_DMA_MAXCNT {
304+
if maxcnt > MAX_DMA_MAXCNT {
314305
return Err(Error::BufferTooLong);
315306
}
307+
if (tx_ptr as usize) < SRAM_LOWER || (tx_ptr as usize) > SRAM_UPPER {
308+
return Err(Error::DMABufferNotInDataMemory);
309+
}
316310

317311
self.i2s
318312
.txd
319313
.ptr
320-
.write(|w| unsafe { w.ptr().bits(tx_buffer.ptr()) });
314+
.write(|w| unsafe { w.ptr().bits(tx_ptr as u32) });
321315
self.i2s
322316
.rxd
323317
.ptr
324-
.write(|w| unsafe { w.ptr().bits(rx_buffer.ptr()) });
325-
self.i2s
326-
.rxtxd
327-
.maxcnt
328-
.write(|w| unsafe { w.bits(rx_buffer.maxcnt()) });
329-
330-
self.start();
318+
.write(|w| unsafe { w.ptr().bits(rx_ptr as u32) });
319+
self.i2s.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
331320

332321
Ok(TransferFullDuplex {
333322
inner: Some(InnerFullDuplex {
@@ -341,28 +330,24 @@ impl I2S {
341330
/// Transmits the given `tx_buffer`.
342331
/// Returns a value that represents the in-progress DMA transfer.
343332
#[allow(unused_mut)]
344-
pub fn tx<Word, B>(mut self, buffer: B) -> Result<Transfer<B>, Error>
333+
pub fn tx<W, B>(mut self, buffer: B) -> Result<Transfer<B>, Error>
345334
where
346-
Word: SupportedWordSize,
347-
B: Deref + StableDeref + 'static + I2SBuffer,
348-
B::Target: AsRef<[Word]>,
335+
B: ReadBuffer<Word = W>,
349336
{
350-
if (buffer.ptr() as usize) < SRAM_LOWER || (buffer.ptr() as usize) > SRAM_UPPER {
351-
return Err(Error::DMABufferNotInDataMemory);
352-
}
353-
354-
if buffer.maxcnt() > MAX_DMA_MAXCNT {
337+
let (ptr, len) = unsafe { buffer.read_buffer() };
338+
let maxcnt = (len / (core::mem::size_of::<u32>() / core::mem::size_of::<W>())) as u32;
339+
if maxcnt > MAX_DMA_MAXCNT {
355340
return Err(Error::BufferTooLong);
356341
}
342+
if (ptr as usize) < SRAM_LOWER || (ptr as usize) > SRAM_UPPER {
343+
return Err(Error::DMABufferNotInDataMemory);
344+
}
357345

358346
self.i2s
359347
.txd
360348
.ptr
361-
.write(|w| unsafe { w.ptr().bits(buffer.ptr()) });
362-
self.i2s
363-
.rxtxd
364-
.maxcnt
365-
.write(|w| unsafe { w.bits(buffer.maxcnt()) });
349+
.write(|w| unsafe { w.ptr().bits(ptr as u32) });
350+
self.i2s.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
366351

367352
Ok(Transfer {
368353
inner: Some(Inner { buffer, i2s: self }),
@@ -598,132 +583,6 @@ pub enum I2SEvent {
598583
Stopped,
599584
}
600585

601-
/// Trait to represent valid sample buffers.
602-
pub trait I2SBuffer: private::Sealed {
603-
fn ptr(&self) -> u32;
604-
fn maxcnt(&self) -> u32;
605-
}
606-
607-
impl private::Sealed for &[i8] {}
608-
impl I2SBuffer for &[i8] {
609-
fn ptr(&self) -> u32 {
610-
self.as_ptr() as u32
611-
}
612-
fn maxcnt(&self) -> u32 {
613-
self.len() as u32 / 4
614-
}
615-
}
616-
617-
impl private::Sealed for &[i16] {}
618-
impl I2SBuffer for &[i16] {
619-
fn ptr(&self) -> u32 {
620-
self.as_ptr() as u32
621-
}
622-
fn maxcnt(&self) -> u32 {
623-
self.len() as u32 / 2
624-
}
625-
}
626-
627-
impl private::Sealed for &[i32] {}
628-
impl I2SBuffer for &[i32] {
629-
fn ptr(&self) -> u32 {
630-
self.as_ptr() as u32
631-
}
632-
fn maxcnt(&self) -> u32 {
633-
self.len() as u32
634-
}
635-
}
636-
637-
impl private::Sealed for &[u8] {}
638-
impl I2SBuffer for &[u8] {
639-
fn ptr(&self) -> u32 {
640-
self.as_ptr() as u32
641-
}
642-
fn maxcnt(&self) -> u32 {
643-
self.len() as u32 / 8
644-
}
645-
}
646-
647-
impl private::Sealed for &[u16] {}
648-
impl I2SBuffer for &[u16] {
649-
fn ptr(&self) -> u32 {
650-
self.as_ptr() as u32
651-
}
652-
fn maxcnt(&self) -> u32 {
653-
self.len() as u32 / 4
654-
}
655-
}
656-
657-
impl private::Sealed for &[u32] {}
658-
impl I2SBuffer for &[u32] {
659-
fn ptr(&self) -> u32 {
660-
self.as_ptr() as u32
661-
}
662-
fn maxcnt(&self) -> u32 {
663-
self.len() as u32 / 2
664-
}
665-
}
666-
667-
impl private::Sealed for &mut [i8] {}
668-
impl I2SBuffer for &mut [i8] {
669-
fn ptr(&self) -> u32 {
670-
self.as_ptr() as u32
671-
}
672-
fn maxcnt(&self) -> u32 {
673-
self.len() as u32 / 4
674-
}
675-
}
676-
677-
impl private::Sealed for &mut [i16] {}
678-
impl I2SBuffer for &mut [i16] {
679-
fn ptr(&self) -> u32 {
680-
self.as_ptr() as u32
681-
}
682-
fn maxcnt(&self) -> u32 {
683-
self.len() as u32 / 2
684-
}
685-
}
686-
687-
impl private::Sealed for &mut [i32] {}
688-
impl I2SBuffer for &mut [i32] {
689-
fn ptr(&self) -> u32 {
690-
self.as_ptr() as u32
691-
}
692-
fn maxcnt(&self) -> u32 {
693-
self.len() as u32
694-
}
695-
}
696-
697-
impl private::Sealed for &mut [u8] {}
698-
impl I2SBuffer for &mut [u8] {
699-
fn ptr(&self) -> u32 {
700-
self.as_ptr() as u32
701-
}
702-
fn maxcnt(&self) -> u32 {
703-
self.len() as u32 / 8
704-
}
705-
}
706-
707-
impl private::Sealed for &mut [u16] {}
708-
impl I2SBuffer for &mut [u16] {
709-
fn ptr(&self) -> u32 {
710-
self.as_ptr() as u32
711-
}
712-
fn maxcnt(&self) -> u32 {
713-
self.len() as u32 / 4
714-
}
715-
}
716-
717-
impl private::Sealed for &mut [u32] {}
718-
impl I2SBuffer for &mut [u32] {
719-
fn ptr(&self) -> u32 {
720-
self.as_ptr() as u32
721-
}
722-
fn maxcnt(&self) -> u32 {
723-
self.len() as u32 / 2
724-
}
725-
}
726-
727586
/// A DMA transfer
728587
pub struct Transfer<B> {
729588
inner: Option<Inner<B>>,
@@ -791,22 +650,3 @@ impl<TxB, RxB> Drop for TransferFullDuplex<TxB, RxB> {
791650
}
792651
}
793652
}
794-
795-
pub trait SupportedWordSize: private::Sealed {}
796-
impl private::Sealed for i8 {}
797-
impl SupportedWordSize for i8 {}
798-
impl private::Sealed for i16 {}
799-
impl SupportedWordSize for i16 {}
800-
impl private::Sealed for i32 {}
801-
impl SupportedWordSize for i32 {}
802-
impl private::Sealed for u8 {}
803-
impl SupportedWordSize for u8 {}
804-
impl private::Sealed for u16 {}
805-
impl SupportedWordSize for u16 {}
806-
impl private::Sealed for u32 {}
807-
impl SupportedWordSize for u32 {}
808-
809-
mod private {
810-
/// Prevents code outside of the parent module from implementing traits.
811-
pub trait Sealed {}
812-
}

0 commit comments

Comments
 (0)