issue 2059 fix build errors in ci

This commit is contained in:
Tyler Gilbert 2023-12-17 20:47:58 -06:00
parent 6c2ad332e8
commit 3c58465e30
6 changed files with 149 additions and 81 deletions

View File

@ -1,6 +1,6 @@
//! Basic Direct Memory Acccess (BDMA) //! Basic Direct Memory Acccess (BDMA)
use core::future::Future; use core::future::{poll_fn, Future};
use core::pin::Pin; use core::pin::Pin;
use core::sync::atomic::{fence, AtomicUsize, Ordering}; use core::sync::atomic::{fence, AtomicUsize, Ordering};
use core::task::{Context, Poll, Waker}; use core::task::{Context, Poll, Waker};
@ -431,6 +431,45 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
} }
} }
struct RingBuffer {}
impl RingBuffer {
fn is_running(ch: &pac::bdma::Ch) -> bool {
ch.cr().read().en()
}
fn request_stop(ch: &pac::bdma::Ch) {
// 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.
ch.cr().write(|w| {
w.set_teie(true);
w.set_htie(true);
w.set_tcie(true);
});
}
async fn stop(ch: &pac::bdma::Ch, set_waker: &mut dyn FnMut(&Waker)) {
use core::sync::atomic::compiler_fence;
Self::request_stop(ch);
//wait until cr.susp reads as true
poll_fn(|cx| {
set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
if !Self::is_running(ch) {
Poll::Ready(())
} else {
Poll::Pending
}
})
.await
}
}
/// Ringbuffer for reading data using DMA circular mode. /// Ringbuffer for reading data using DMA circular mode.
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
cr: regs::Cr, cr: regs::Cr,
@ -508,6 +547,13 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
} }
pub async fn stop(&mut self) {
RingBuffer::stop(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
self.set_waker(waker)
})
.await
}
/// Read elements from the ring buffer /// Read elements from the ring buffer
/// Return a tuple of the length read and the length remaining in the buffer /// Return a tuple of the length read and the length remaining in the buffer
/// If not all of the elements were read, then there will be some elements in the buffer remaining /// If not all of the elements were read, then there will be some elements in the buffer remaining
@ -557,16 +603,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
/// ///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_stop(&mut self) { pub fn request_stop(&mut self) {
let ch = self.channel.regs().ch(self.channel.num()); RingBuffer::request_stop(&self.channel.regs().ch(self.channel.num()));
// 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.
ch.cr().write(|w| {
w.set_teie(true);
w.set_htie(true);
w.set_tcie(true);
});
} }
/// Return whether DMA is still running. /// Return whether DMA is still running.
@ -574,8 +611,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
/// If this returns `false`, it can be because either the transfer finished, or /// If this returns `false`, it can be because either the transfer finished, or
/// it was requested to stop early with [`request_stop`](Self::request_stop). /// it was requested to stop early with [`request_stop`](Self::request_stop).
pub fn is_running(&mut self) -> bool { pub fn is_running(&mut self) -> bool {
let ch = self.channel.regs().ch(self.channel.num()); RingBuffer::is_running(&self.channel.regs().ch(self.channel.num()))
ch.cr().read().en()
} }
} }
@ -666,6 +702,20 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 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.
#[allow(dead_code)]
pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.write_immediate(buf)
}
pub async fn stop(&mut self) {
RingBuffer::stop(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
self.set_waker(waker)
})
.await
}
/// Write elements to the ring buffer /// Write elements to the ring buffer
/// Return a tuple of the length written and the length remaining in the 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> { pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
@ -702,16 +752,7 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
/// ///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_stop(&mut self) { pub fn request_stop(&mut self) {
let ch = self.channel.regs().ch(self.channel.num()); RingBuffer::request_stop(&self.channel.regs().ch(self.channel.num()));
// 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.
ch.cr().write(|w| {
w.set_teie(true);
w.set_htie(true);
w.set_tcie(true);
});
} }
/// Return whether DMA is still running. /// Return whether DMA is still running.
@ -719,8 +760,7 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
/// If this returns `false`, it can be because either the transfer finished, or /// If this returns `false`, it can be because either the transfer finished, or
/// it was requested to stop early with [`request_stop`](Self::request_stop). /// it was requested to stop early with [`request_stop`](Self::request_stop).
pub fn is_running(&mut self) -> bool { pub fn is_running(&mut self) -> bool {
let ch = self.channel.regs().ch(self.channel.num()); RingBuffer::is_running(&self.channel.regs().ch(self.channel.num()))
ch.cr().read().en()
} }
} }

View File

@ -1,4 +1,4 @@
use core::future::Future; use core::future::{poll_fn, Future};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::pin::Pin; use core::pin::Pin;
use core::sync::atomic::{fence, AtomicUsize, Ordering}; use core::sync::atomic::{fence, AtomicUsize, Ordering};
@ -668,6 +668,42 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
} }
} }
struct RingBuffer {}
impl RingBuffer {
fn is_running(ch: &pac::dma::St) -> bool {
ch.cr().read().en()
}
fn request_stop(ch: &pac::dma::St) {
ch.cr().write(|w| {
w.set_teie(true);
w.set_htie(true);
w.set_tcie(true);
});
}
async fn stop(ch: &pac::dma::St, set_waker: &mut dyn FnMut(&Waker)) {
use core::sync::atomic::compiler_fence;
Self::request_stop(ch);
//wait until cr.susp reads as true
poll_fn(|cx| {
set_waker(cx.waker());
compiler_fence(Ordering::SeqCst);
if !Self::is_running(ch) {
Poll::Ready(())
} else {
Poll::Pending
}
})
.await
}
}
/// Ringbuffer for receiving data using DMA circular mode. /// Ringbuffer for receiving data using DMA circular mode.
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
cr: regs::Cr, cr: regs::Cr,
@ -755,6 +791,17 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
ch.cr().write_value(self.cr); ch.cr().write_value(self.cr);
} }
pub async fn stop(&mut self) {
RingBuffer::stop(&self.channel.regs().st(self.channel.num()), &mut |waker| {
self.set_waker(waker)
})
.await
}
pub fn resume(&mut self) {
self.start();
}
/// Clear all data in the ring buffer. /// Clear all data in the ring buffer.
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
@ -930,6 +977,13 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
ch.cr().write_value(self.cr); ch.cr().write_value(self.cr);
} }
pub async fn stop(&mut self) {
RingBuffer::stop(&self.channel.regs().st(self.channel.num()), &mut |waker| {
self.set_waker(waker)
})
.await
}
/// Clear all data in the ring buffer. /// Clear all data in the ring buffer.
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
@ -937,14 +991,9 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
/// Write elements directly to the raw buffer. /// Write elements directly to the raw buffer.
/// This can be used to fill the buffer before starting the DMA transfer. /// This can be used to fill the buffer before starting the DMA transfer.
#[allow(dead_code)]
pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
self.ringbuf.write_immediate( self.ringbuf.write_immediate(buf)
&mut DmaCtrlImpl {
channel: self.channel.reborrow(),
word_size: W::size(),
},
buf,
)
} }
/// Write elements from the ring buffer /// Write elements from the ring buffer

View File

@ -491,7 +491,7 @@ impl RingBuffer {
}); });
} }
async fn suspend(ch: &pac::gpdma::Channel, set_waker: &mut dyn FnMut(&Waker)) { async fn stop(ch: &pac::gpdma::Channel, set_waker: &mut dyn FnMut(&Waker)) {
use core::sync::atomic::compiler_fence; use core::sync::atomic::compiler_fence;
Self::request_suspend(ch); Self::request_suspend(ch);
@ -504,17 +504,15 @@ impl RingBuffer {
let cr = ch.cr().read(); let cr = ch.cr().read();
if cr.susp() { if cr.susp() {
defmt::info!("Ready {}", cr.susp());
Poll::Ready(()) Poll::Ready(())
} else { } else {
defmt::info!("still pending {}", cr.susp());
Poll::Pending Poll::Pending
} }
}) })
.await .await
} }
fn resume(ch: &pac::gpdma::Channel) { fn start(ch: &pac::gpdma::Channel) {
Self::clear_irqs(ch); Self::clear_irqs(ch);
ch.cr().modify(|w| { ch.cr().modify(|w| {
w.set_susp(false); w.set_susp(false);
@ -534,7 +532,7 @@ pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
} }
impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
pub unsafe fn new_read( pub unsafe fn new(
channel: impl Peripheral<P = C> + 'a, channel: impl Peripheral<P = C> + 'a,
request: Request, request: Request,
peri_addr: *mut W, peri_addr: *mut W,
@ -564,25 +562,21 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
pub fn start(&mut self) { pub fn start(&mut self) {
let ch = &self.channel.regs().ch(self.channel.num()); let ch = &self.channel.regs().ch(self.channel.num());
RingBuffer::clear_irqs(ch); RingBuffer::start(ch);
ch.cr().modify(|w| w.set_en(true)); //ch.cr().modify(|w| w.set_en(true));
} }
pub fn request_stop(&mut self, ch: &pac::gpdma::Channel) { pub fn request_stop(&mut self) {
ch.cr().modify(|w| w.set_en(false)); RingBuffer::request_suspend(&self.channel.regs().ch(self.channel.num()));
} }
pub async fn suspend(&mut self) { pub async fn stop(&mut self) {
RingBuffer::suspend(&self.channel.regs().ch(self.channel.num()), &mut |waker| { RingBuffer::stop(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
self.set_waker(waker) self.set_waker(waker)
}) })
.await .await
} }
pub fn resume(&mut self) {
RingBuffer::resume(&self.channel.regs().ch(self.channel.num()));
}
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.ringbuf.clear(&mut DmaCtrlImpl { self.ringbuf.clear(&mut DmaCtrlImpl {
channel: self.channel.reborrow(), channel: self.channel.reborrow(),
@ -648,7 +642,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> { impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> {
fn drop(&mut self) { fn drop(&mut self) {
RingBuffer::request_suspend(&self.channel.regs().ch(self.channel.num())); self.request_stop();
while self.is_running() {} while self.is_running() {}
// "Subsequent reads and writes cannot be moved ahead of preceding reads." // "Subsequent reads and writes cannot be moved ahead of preceding reads."
@ -663,7 +657,7 @@ pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
} }
impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
pub unsafe fn new_write( pub unsafe fn new(
channel: impl Peripheral<P = C> + 'a, channel: impl Peripheral<P = C> + 'a,
request: Request, request: Request,
peri_addr: *mut W, peri_addr: *mut W,
@ -692,26 +686,28 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
} }
pub fn start(&mut self) { pub fn start(&mut self) {
self.resume(); RingBuffer::start(&self.channel.regs().ch(self.channel.num()));
} }
pub async fn suspend(&mut self) { pub async fn stop(&mut self) {
RingBuffer::suspend(&self.channel.regs().ch(self.channel.num()), &mut |waker| { RingBuffer::stop(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
self.set_waker(waker) self.set_waker(waker)
}) })
.await .await
} }
pub fn resume(&mut self) {
RingBuffer::resume(&self.channel.regs().ch(self.channel.num()));
}
pub fn request_stop(&mut self) { pub fn request_stop(&mut self) {
// reads can be stopped by disabling the enable flag // reads can be stopped by disabling the enable flag
let ch = &self.channel.regs().ch(self.channel.num()); let ch = &self.channel.regs().ch(self.channel.num());
ch.cr().modify(|w| w.set_en(false)); ch.cr().modify(|w| w.set_en(false));
} }
/// 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(buf)
}
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.ringbuf.clear(&mut DmaCtrlImpl { self.ringbuf.clear(&mut DmaCtrlImpl {
channel: self.channel.reborrow(), channel: self.channel.reborrow(),
@ -731,18 +727,6 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
) )
} }
/// 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 an exact number of elements to the ringbuffer. /// Write an exact number of elements to the ringbuffer.
pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> { pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> {
self.ringbuf self.ringbuf
@ -776,7 +760,7 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
impl<'a, C: Channel, W: Word> Drop for WritableRingBuffer<'a, C, W> { impl<'a, C: Channel, W: Word> Drop for WritableRingBuffer<'a, C, W> {
fn drop(&mut self) { fn drop(&mut self) {
RingBuffer::request_suspend(&self.channel.regs().ch(self.channel.num())); self.request_stop();
while self.is_running() {} while self.is_running() {}
// "Subsequent reads and writes cannot be moved ahead of preceding reads." // "Subsequent reads and writes cannot be moved ahead of preceding reads."

View File

@ -264,7 +264,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
} }
/// Write elements directl to the buffer. This should be done before the DMA is started. /// 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> { pub fn write_immediate(&mut self, buffer: &[W]) -> Result<(usize, usize), OverrunError> {
if self.end != 0 { if self.end != 0 {
return Err(OverrunError); return Err(OverrunError);
} }

View File

@ -1008,17 +1008,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
} }
} }
pub async fn suspend(&mut self) { pub async fn stop(&mut self) {
match &mut self.ring_buffer { match &mut self.ring_buffer {
RingBuffer::Writable(buffer) => buffer.suspend().await, RingBuffer::Writable(buffer) => buffer.stop().await,
RingBuffer::Readable(buffer) => buffer.suspend().await, RingBuffer::Readable(buffer) => buffer.stop().await,
}
}
pub fn resume(&mut self) {
match &mut self.ring_buffer {
RingBuffer::Writable(buffer) => buffer.resume(),
RingBuffer::Readable(buffer) => buffer.resume(),
} }
} }

View File

@ -28,6 +28,8 @@ async fn main(_spawner: Spawner) {
m: Pllm::DIV2, m: Pllm::DIV2,
n: Plln::MUL10, n: Plln::MUL10,
r: Plldiv::DIV1, r: Plldiv::DIV1,
p: Plldiv::DIV1,
q: Plldiv::DIV1,
}); });
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB