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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user