From 84c348a286f0124bfc2f23c370b99040c75c03e0 Mon Sep 17 00:00:00 2001 From: jerrysxie Date: Tue, 5 Nov 2024 18:14:55 -0600 Subject: [PATCH] dma: expose more functionalities - Expose both dma busy and active bits - Expose getting dma transfer count - Allow dma aborts - Allow dma channel to be disabled --- src/dma/channel.rs | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/dma/channel.rs b/src/dma/channel.rs index c7342e64..a2f84041 100644 --- a/src/dma/channel.rs +++ b/src/dma/channel.rs @@ -54,12 +54,42 @@ impl<'d> ChannelAndRequest<'d> { &DMA_WAKERS[self.channel.info.ch_num] } - /// Check whether DMA is busy + /// Check whether DMA is active pub fn is_active(&self) -> bool { let channel = self.channel.info.ch_num; self.channel.info.regs.active0().read().act().bits() & (1 << channel) != 0 } + /// Check whether DMA is busy + pub fn is_busy(&self) -> bool { + let channel = self.channel.info.ch_num; + self.channel.info.regs.busy0().read().bsy().bits() & (1 << channel) != 0 + } + + /// Return DMA remaining transfer count + /// To get number of bytes, do `(XFERCOUNT + 1) x data width` + pub fn get_xfer_count(&self) -> u16 { + let channel = self.channel.info.ch_num; + self.channel + .info + .regs + .channel(channel) + .xfercfg() + .read() + .xfercount() + .bits() + } + + /// Abort DMA operation + pub fn abort(&self) { + let channel = self.channel.info.ch_num; + self.channel.disable_channel(); + while self.is_busy() {} + self.channel.info.regs.abort0().write(|w| + // SAFETY: unsafe due to .bits usage + unsafe { w.abortctrl().bits(1 << channel) }); + } + async fn poll_transfer_complete(&'d self) { poll_fn(|cx| { // TODO - handle transfer failure @@ -174,6 +204,14 @@ impl Channel<'_> { .modify(|_, w| unsafe { w.ena().bits(1 << channel) }); } + /// Disable the DMA channel + pub fn disable_channel(&self) { + let channel = self.info.ch_num; + self.info.regs.enableclr0().write(|w| + // SAFETY: unsafe due to .bits usage + unsafe { w.clr().bits(1 << channel) }); + } + /// Trigger the DMA channel pub fn trigger_channel(&self) { let channel = self.info.ch_num;