add half transfer interrupt and circular dma

This commit is contained in:
JuliDi 2023-06-18 18:51:36 +02:00
parent 78a2ca8a0e
commit f8ee33abb9
No known key found for this signature in database
GPG Key ID: E1E90AE563D09D63
2 changed files with 36 additions and 7 deletions

View File

@ -2,7 +2,7 @@
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use crate::dma::Transfer; use crate::dma::{Transfer, TransferOptions};
use crate::pac::dac; use crate::pac::dac;
use crate::rcc::RccPeripheral; use crate::rcc::RccPeripheral;
use crate::{peripherals, Peripheral}; use crate::{peripherals, Peripheral};
@ -237,7 +237,7 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> {
} }
/// TODO: Allow an array of Value instead of only u16, right-aligned /// TODO: Allow an array of Value instead of only u16, right-aligned
pub async fn write(&mut self, data: &[u16]) -> Result<(), Error> pub async fn write(&mut self, data: &[u16], circular: bool) -> Result<(), Error>
where where
Tx: Dma<T>, Tx: Dma<T>,
{ {
@ -257,7 +257,18 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> {
// Use the 12 bit right-aligned register for now. TODO: distinguish values // Use the 12 bit right-aligned register for now. TODO: distinguish values
let tx_dst = T::regs().dhr12r(CHANNEL).ptr() as *mut u16; let tx_dst = T::regs().dhr12r(CHANNEL).ptr() as *mut u16;
let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) }; let tx_f = unsafe {
Transfer::new_write(
&mut self.txdma,
tx_request,
data,
tx_dst,
TransferOptions {
circular,
halt_transfer_ir: false,
},
)
};
//debug!("Awaiting tx_f"); //debug!("Awaiting tx_f");

View File

@ -1,6 +1,7 @@
#![macro_use] #![macro_use]
use core::future::Future; use core::future::Future;
use core::option;
use core::pin::Pin; use core::pin::Pin;
use core::sync::atomic::{fence, Ordering}; use core::sync::atomic::{fence, Ordering};
use core::task::{Context, Poll, Waker}; use core::task::{Context, Poll, Waker};
@ -21,11 +22,17 @@ use crate::pac::bdma::{regs, vals};
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive] #[non_exhaustive]
pub struct TransferOptions {} pub struct TransferOptions {
pub circular: bool,
pub halt_transfer_ir: bool,
}
impl Default for TransferOptions { impl Default for TransferOptions {
fn default() -> Self { fn default() -> Self {
Self {} Self {
circular: false,
halt_transfer_ir: false,
}
} }
} }
@ -253,7 +260,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
mem_len: usize, mem_len: usize,
incr_mem: bool, incr_mem: bool,
data_size: WordSize, data_size: WordSize,
_options: TransferOptions, options: TransferOptions,
) -> Self { ) -> Self {
let ch = channel.regs().ch(channel.num()); let ch = channel.regs().ch(channel.num());
@ -284,6 +291,14 @@ impl<'a, C: Channel> Transfer<'a, C> {
w.set_dir(dir.into()); w.set_dir(dir.into());
w.set_teie(true); w.set_teie(true);
w.set_tcie(true); w.set_tcie(true);
w.set_htie(options.halt_transfer_ir);
if options.circular {
w.set_circ(vals::Circ::ENABLED);
debug!("Setting circular mode");
} else {
w.set_circ(vals::Circ::DISABLED);
}
w.set_pl(vals::Pl::VERYHIGH);
w.set_en(true); w.set_en(true);
}); });
@ -314,8 +329,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
pub fn is_running(&mut self) -> bool { pub fn is_running(&mut self) -> bool {
let ch = self.channel.regs().ch(self.channel.num()); let ch = self.channel.regs().ch(self.channel.num());
let en = unsafe { ch.cr().read() }.en(); let en = unsafe { ch.cr().read() }.en();
let circular = unsafe { ch.cr().read() }.circ() == vals::Circ::ENABLED;
let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0;
en && !tcif en && (circular || !tcif)
} }
/// Gets the total remaining transfers for the channel /// Gets the total remaining transfers for the channel
@ -482,6 +498,8 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
let ch = self.channel.regs().ch(self.channel.num()); let ch = self.channel.regs().ch(self.channel.num());
// Disable the channel. Keep the IEs enabled so the irqs still fire. // Disable the channel. Keep the IEs enabled so the irqs still fire.
// If the channel is enabled and transfer is not completed, we need to perform
// two separate write access to the CR register to disable the channel.
unsafe { unsafe {
ch.cr().write(|w| { ch.cr().write(|w| {
w.set_teie(true); w.set_teie(true);