Skip to content

Commit

Permalink
Moved DMA setup to when the DMA object is made
Browse files Browse the repository at this point in the history
As it is a one-time setup, it does not make sense to re-setup the entire
DMA engine, when it's enough to setup the buffer's address and length.
  • Loading branch information
korken89 committed May 31, 2021
1 parent b209de8 commit efe86ca
Showing 1 changed file with 135 additions and 124 deletions.
259 changes: 135 additions & 124 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,11 +393,71 @@ macro_rules! spi_dma {
impl<PINS> Spi<$SPIX, PINS> {
pub fn with_rx_dma(self, channel: $RX_CH) -> SpiRxDma<$SPIX, PINS, $RX_CH> {
let payload = SpiPayload { spi: self };

// Perform one-time setup actions to keep the work minimal when using the driver.

self.channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);
self.channel.cselr().modify(|_, w| w.$RX_CHX().$RX_MAPX());
self.channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to memory
.dir()
.clear_bit()
});

SpiRxDma { payload, channel }
}

pub fn with_tx_dma(self, channel: $TX_CH) -> SpiTxDma<$SPIX, PINS, $TX_CH> {
let payload = SpiPayload { spi: self };

// Perform one-time setup actions to keep the work minimal when using the driver.

self.channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);
self.channel.cselr().modify(|_, w| w.$TX_CHX().$TX_MAPX());
self.channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to peripheral
.dir()
.set_bit()
});

SpiTxDma { payload, channel }
}

Expand All @@ -407,6 +467,75 @@ macro_rules! spi_dma {
tx_channel: $TX_CH,
) -> SpiRxTxDma<$SPIX, PINS, $RX_CH, $TX_CH> {
let payload = SpiPayload { spi: self };

// Perform one-time setup actions to keep the work minimal when using the driver.

//
// Setup RX channel
//
self.rx_channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);
self.rx_channel
.cselr()
.modify(|_, w| w.$RX_CHX().$RX_MAPX());

self.rx_channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to memory
.dir()
.clear_bit()
});

//
// Setup TX channel
//
self.tx_channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);
self.tx_channel
.cselr()
.modify(|_, w| w.$TX_CHX().$TX_MAPX());

self.tx_channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to peripheral
.dir()
.set_bit()
});

SpiRxTxDma {
payload,
rx_channel,
Expand Down Expand Up @@ -506,37 +635,12 @@ macro_rules! spi_dma {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.static_write_buffer() };
self.channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);

// Setup RX channel
self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len as u16);

self.channel.cselr().modify(|_, w| w.$RX_CHX().$RX_MAPX());

atomic::compiler_fence(Ordering::Release);
self.channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to memory
.dir()
.clear_bit()
});
// Fences and start
atomic::compiler_fence(Ordering::Release);
self.start();

Expand All @@ -552,37 +656,12 @@ macro_rules! spi_dma {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.static_read_buffer() };
self.channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);

// Setup TX channel
self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len as u16);

self.channel.cselr().modify(|_, w| w.$TX_CHX().$TX_MAPX());

atomic::compiler_fence(Ordering::Release);
self.channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to peripheral
.dir()
.set_bit()
});
// Fences and start
atomic::compiler_fence(Ordering::Release);
self.start();

Expand All @@ -601,83 +680,15 @@ macro_rules! spi_dma {
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.static_write_buffer() };

//
// Setup RX channel
//
self.rx_channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);
self.rx_channel.set_memory_address(ptr as u32, true);
self.rx_channel.set_transfer_length(len as u16);

self.rx_channel
.cselr()
.modify(|_, w| w.$RX_CHX().$RX_MAPX());

atomic::compiler_fence(Ordering::Release);
self.rx_channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to memory
.dir()
.clear_bit()
});

//
// Setup TX channel
//
self.tx_channel.set_peripheral_address(
unsafe { &(*$SPIX::ptr()).dr as *const _ as u32 },
false,
);
self.tx_channel.set_memory_address(ptr as u32, true);
self.tx_channel.set_transfer_length(len as u16);

self.tx_channel
.cselr()
.modify(|_, w| w.$TX_CHX().$TX_MAPX());

atomic::compiler_fence(Ordering::Release);
self.tx_channel.ccr().modify(|_, w| {
w
// memory to memory mode disabled
.mem2mem()
.clear_bit()
// medium channel priority level
.pl()
.medium()
// 8-bit memory size
.msize()
.bits8()
// 8-bit peripheral size
.psize()
.bits8()
// circular mode disabled
.circ()
.clear_bit()
// write to peripheral
.dir()
.set_bit()
});

//
// Fences and start
//
atomic::compiler_fence(Ordering::Release);
self.start();

Expand Down

0 comments on commit efe86ca

Please sign in to comment.