use crate::ral;
use crate::common::dma::channel::Channel;
pub const CHANNEL_COUNT: usize = crate::chip::config::DMA_CHANNEL_COUNT;
pub static DMA: crate::common::dma::Dma<{ CHANNEL_COUNT }> = unsafe {
crate::common::dma::Dma::new(
crate::ral::dma::DMA.cast(),
crate::ral::dmamux::DMAMUX.cast(),
)
};
pub fn channels(_: ral::dma::DMA, _: ral::dmamux::DMAMUX) -> [Option<Channel>; CHANNEL_COUNT] {
const NO_CHANNEL: Option<Channel> = None;
let mut channels: [Option<Channel>; CHANNEL_COUNT] = [NO_CHANNEL; CHANNEL_COUNT];
for (idx, channel) in channels.iter_mut().enumerate() {
let mut chan = unsafe { DMA.channel(idx) };
chan.reset();
*channel = Some(chan);
}
channels
}
use crate::dma::peripheral;
#[cfg(family = "imxrt10xx")]
mod mappings {
pub(super) const LPUART_DMA_RX_MAPPING: [u32; 8] = [3, 67, 5, 69, 7, 71, 9, 73];
pub(super) const LPUART_DMA_TX_MAPPING: [u32; 8] = [2, 66, 4, 68, 6, 70, 8, 72];
pub(super) const LPSPI_DMA_RX_MAPPING: [u32; 4] = [13, 77, 15, 79];
pub(super) const LPSPI_DMA_TX_MAPPING: [u32; 4] = [14, 78, 16, 80];
pub(super) const ADC_DMA_RX_MAPPING: [u32; 2] = [24, 88];
}
#[cfg(family = "imxrt11xx")]
mod mappings {
pub(super) const LPUART_DMA_RX_MAPPING: [u32; 12] =
[9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31];
pub(super) const LPUART_DMA_TX_MAPPING: [u32; 12] =
[8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30];
pub(super) const LPSPI_DMA_RX_MAPPING: [u32; 6] = [36, 38, 40, 42, 44, 46];
pub(super) const LPSPI_DMA_TX_MAPPING: [u32; 6] = [37, 39, 41, 43, 45, 47];
}
use mappings::*;
use crate::lpuart;
unsafe impl<P, const N: u8> peripheral::Destination<u8> for lpuart::Lpuart<P, N> {
fn destination_signal(&self) -> u32 {
LPUART_DMA_TX_MAPPING[N as usize - 1]
}
fn destination_address(&self) -> *const u8 {
self.data().cast()
}
fn enable_destination(&mut self) {
self.enable_dma_transmit();
}
fn disable_destination(&mut self) {
self.disable_dma_transmit();
}
}
unsafe impl<P, const N: u8> peripheral::Source<u8> for lpuart::Lpuart<P, N> {
fn source_signal(&self) -> u32 {
LPUART_DMA_RX_MAPPING[N as usize - 1]
}
fn source_address(&self) -> *const u8 {
self.data().cast()
}
fn enable_source(&mut self) {
self.enable_dma_receive();
}
fn disable_source(&mut self) {
self.disable_dma_receive();
}
}
impl<P, const N: u8> lpuart::Lpuart<P, N> {
pub fn dma_write<'a>(
&'a mut self,
channel: &'a mut Channel,
buffer: &'a [u8],
) -> peripheral::Write<'a, Self, u8> {
peripheral::write(channel, buffer, self)
}
pub fn dma_read<'a>(
&'a mut self,
channel: &'a mut Channel,
buffer: &'a mut [u8],
) -> peripheral::Read<'a, Self, u8> {
peripheral::read(channel, self, buffer)
}
}
use crate::lpspi;
unsafe impl<P, const N: u8> peripheral::Source<u32> for lpspi::Lpspi<P, N> {
fn source_signal(&self) -> u32 {
LPSPI_DMA_RX_MAPPING[N as usize - 1]
}
fn source_address(&self) -> *const u32 {
self.rdr().cast()
}
fn enable_source(&mut self) {
self.enable_dma_receive()
}
fn disable_source(&mut self) {
self.disable_dma_receive();
}
}
unsafe impl<P, const N: u8> peripheral::Destination<u32> for lpspi::Lpspi<P, N> {
fn destination_signal(&self) -> u32 {
LPSPI_DMA_TX_MAPPING[N as usize - 1]
}
fn destination_address(&self) -> *const u32 {
self.tdr().cast()
}
fn enable_destination(&mut self) {
self.enable_dma_transmit();
}
fn disable_destination(&mut self) {
self.disable_dma_transmit();
}
}
unsafe impl<P, const N: u8> peripheral::Bidirectional<u32> for lpspi::Lpspi<P, N> {}
impl<P, const N: u8> lpspi::Lpspi<P, N> {
pub fn dma_write<'a>(
&'a mut self,
channel: &'a mut Channel,
buffer: &'a [u32],
) -> Result<peripheral::Write<'a, Self, u32>, lpspi::LpspiError> {
let mut transaction = lpspi::Transaction::new_u32s(buffer)?;
transaction.bit_order = self.bit_order();
transaction.receive_data_mask = true;
self.wait_for_transmit_fifo_space()?;
self.enqueue_transaction(&transaction);
Ok(peripheral::write(channel, buffer, self))
}
pub fn dma_read<'a>(
&'a mut self,
channel: &'a mut Channel,
buffer: &'a mut [u32],
) -> Result<peripheral::Read<'a, Self, u32>, lpspi::LpspiError> {
let mut transaction = lpspi::Transaction::new_u32s(buffer)?;
transaction.bit_order = self.bit_order();
transaction.transmit_data_mask = true;
self.wait_for_transmit_fifo_space()?;
self.enqueue_transaction(&transaction);
Ok(peripheral::read(channel, self, buffer))
}
pub fn dma_full_duplex<'a>(
&'a mut self,
rx: &'a mut Channel,
tx: &'a mut Channel,
buffer: &'a mut [u32],
) -> Result<peripheral::FullDuplex<'a, Self, u32>, lpspi::LpspiError> {
let mut transaction = lpspi::Transaction::new_u32s(buffer)?;
transaction.bit_order = self.bit_order();
self.wait_for_transmit_fifo_space()?;
self.enqueue_transaction(&transaction);
Ok(peripheral::full_duplex(rx, tx, self, buffer))
}
}
#[cfg(family = "imxrt10xx")]
use crate::adc;
#[cfg(family = "imxrt10xx")]
unsafe impl<P, const N: u8> peripheral::Source<u16> for adc::DmaSource<P, N> {
fn source_signal(&self) -> u32 {
ADC_DMA_RX_MAPPING[if N == ral::SOLE_INSTANCE {
N as usize
} else {
N as usize - 1
}]
}
fn source_address(&self) -> *const u16 {
self.r0().cast()
}
fn enable_source(&mut self) {
self.enable_dma();
}
fn disable_source(&mut self) {
self.disable_dma();
}
}