diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index cce0407c..bb140716 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -876,6 +876,18 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); } + /// Write elements directly to the raw buffer. + /// This can be used to fill the buffer before starting the DMA transfer. + pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { + self.ringbuf.write_immediate( + &mut DmaCtrlImpl { + channel: self.channel.reborrow(), + word_size: W::size(), + }, + buf, + ) + } + /// Write elements from the ring buffer /// Return a tuple of the length written and the length remaining in the buffer pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index e53183f8..fac9f9ab 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -731,8 +731,10 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { ) } - pub fn prime(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { - self.ringbuf.prime( + /// Write elements directly to the raw buffer. + /// This can be used to fill the buffer before starting the DMA transfer. + pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { + self.ringbuf.write_immediate( &mut DmaCtrlImpl { channel: self.channel.reborrow(), word_size: W::size(), diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs index c4a76580..498ea709 100644 --- a/embassy-stm32/src/dma/ringbuffer.rs +++ b/embassy-stm32/src/dma/ringbuffer.rs @@ -260,15 +260,11 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { /// The current position of the ringbuffer fn pos(&self, dma: &mut impl DmaCtrl) -> usize { - let result = self.cap() - dma.get_remaining_transfers(); - if result >= self.cap() / 2 { - self.cap() / 2 - } else { - 0 - } + self.cap() - dma.get_remaining_transfers() } - pub fn prime(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<(usize, usize), OverrunError> { + /// Write elements directl to the buffer. This should be done before the DMA is started. + pub fn write_immediate(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<(usize, usize), OverrunError> { if self.end != 0 { return Err(OverrunError); } diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index b5f99084..feb90bef 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -435,6 +435,8 @@ impl MasterClockDivider { } } +pub const MAX_FRAME_LENGTH: u8 = 0; + /// [`SAI`] configuration. #[non_exhaustive] #[derive(Copy, Clone)] @@ -853,13 +855,6 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { } } - pub fn prime(self: &mut Self, prime_buffer: &[W]) -> Result<(usize, usize), Error> { - match self.ring_buffer { - RingBuffer::Writable(ref mut rb) => Ok(rb.prime(prime_buffer)?), - RingBuffer::Readable(_) => Err(Error::NotATransmitter), - } - } - fn is_transmitter(ring_buffer: &RingBuffer) -> bool { match ring_buffer { RingBuffer::Writable(_) => true, @@ -943,7 +938,11 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { w.set_fspol(config.frame_sync_polarity.fspol()); w.set_fsdef(config.frame_sync_definition.fsdef()); w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1); - w.set_frl(config.frame_length - 1); + if config.frame_length == MAX_FRAME_LENGTH { + w.set_frl(255); + } else { + w.set_frl(config.frame_length - 1); + } }); ch.slotr().modify(|w| { @@ -1030,6 +1029,16 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { } } + /// Write elements directly to the raw buffer. + /// This should be used before starting the audio stream. This will give the CPU time to + /// prepare the next audio frame while the initial audio frame is playing. + pub fn write_immediate(self: &mut Self, source_buffer: &[W]) -> Result<(usize, usize), Error> { + match self.ring_buffer { + RingBuffer::Writable(ref mut rb) => Ok(rb.write_immediate(source_buffer)?), + RingBuffer::Readable(_) => Err(Error::NotATransmitter), + } + } + pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { match &mut self.ring_buffer { RingBuffer::Writable(buffer) => {