add half transfer interrupt and circular dma
This commit is contained in:
parent
78a2ca8a0e
commit
f8ee33abb9
@ -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");
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user