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)
use core::future::Future;
use core::future::{poll_fn, Future};
use core::pin::Pin;
use core::sync::atomic::{fence, AtomicUsize, Ordering};
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.
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
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()));
}
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
/// 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
@ -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.
pub fn request_stop(&mut self) {
let ch = 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);
});
RingBuffer::request_stop(&self.channel.regs().ch(self.channel.num()));
}
/// 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
/// it was requested to stop early with [`request_stop`](Self::request_stop).
pub fn is_running(&mut self) -> bool {
let ch = self.channel.regs().ch(self.channel.num());
ch.cr().read().en()
RingBuffer::is_running(&self.channel.regs().ch(self.channel.num()))
}
}
@ -666,6 +702,20 @@ 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.
#[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
/// 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> {
@ -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.
pub fn request_stop(&mut self) {
let ch = 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);
});
RingBuffer::request_stop(&self.channel.regs().ch(self.channel.num()));
}
/// 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
/// it was requested to stop early with [`request_stop`](Self::request_stop).
pub fn is_running(&mut self) -> bool {
let ch = self.channel.regs().ch(self.channel.num());
ch.cr().read().en()
RingBuffer::is_running(&self.channel.regs().ch(self.channel.num()))
}
}

View File

@ -1,4 +1,4 @@
use core::future::Future;
use core::future::{poll_fn, Future};
use core::marker::PhantomData;
use core::pin::Pin;
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.
pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
cr: regs::Cr,
@ -755,6 +791,17 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
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.
pub fn clear(&mut self) {
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);
}
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.
pub fn clear(&mut self) {
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.
/// 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(
&mut DmaCtrlImpl {
channel: self.channel.reborrow(),
word_size: W::size(),
},
buf,
)
self.ringbuf.write_immediate(buf)
}
/// 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;
Self::request_suspend(ch);
@ -504,17 +504,15 @@ impl RingBuffer {
let cr = ch.cr().read();
if cr.susp() {
defmt::info!("Ready {}", cr.susp());
Poll::Ready(())
} else {
defmt::info!("still pending {}", cr.susp());
Poll::Pending
}
})
.await
}
fn resume(ch: &pac::gpdma::Channel) {
fn start(ch: &pac::gpdma::Channel) {
Self::clear_irqs(ch);
ch.cr().modify(|w| {
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> {
pub unsafe fn new_read(
pub unsafe fn new(
channel: impl Peripheral<P = C> + 'a,
request: Request,
peri_addr: *mut W,
@ -564,25 +562,21 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
pub fn start(&mut self) {
let ch = &self.channel.regs().ch(self.channel.num());
RingBuffer::clear_irqs(ch);
ch.cr().modify(|w| w.set_en(true));
RingBuffer::start(ch);
//ch.cr().modify(|w| w.set_en(true));
}
pub fn request_stop(&mut self, ch: &pac::gpdma::Channel) {
ch.cr().modify(|w| w.set_en(false));
pub fn request_stop(&mut self) {
RingBuffer::request_suspend(&self.channel.regs().ch(self.channel.num()));
}
pub async fn suspend(&mut self) {
RingBuffer::suspend(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
pub async fn stop(&mut self) {
RingBuffer::stop(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
self.set_waker(waker)
})
.await
}
pub fn resume(&mut self) {
RingBuffer::resume(&self.channel.regs().ch(self.channel.num()));
}
pub fn clear(&mut self) {
self.ringbuf.clear(&mut DmaCtrlImpl {
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> {
fn drop(&mut self) {
RingBuffer::request_suspend(&self.channel.regs().ch(self.channel.num()));
self.request_stop();
while self.is_running() {}
// "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> {
pub unsafe fn new_write(
pub unsafe fn new(
channel: impl Peripheral<P = C> + 'a,
request: Request,
peri_addr: *mut W,
@ -692,26 +686,28 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
}
pub fn start(&mut self) {
self.resume();
RingBuffer::start(&self.channel.regs().ch(self.channel.num()));
}
pub async fn suspend(&mut self) {
RingBuffer::suspend(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
pub async fn stop(&mut self) {
RingBuffer::stop(&self.channel.regs().ch(self.channel.num()), &mut |waker| {
self.set_waker(waker)
})
.await
}
pub fn resume(&mut self) {
RingBuffer::resume(&self.channel.regs().ch(self.channel.num()));
}
pub fn request_stop(&mut self) {
// reads can be stopped by disabling the enable flag
let ch = &self.channel.regs().ch(self.channel.num());
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) {
self.ringbuf.clear(&mut DmaCtrlImpl {
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.
pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> {
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> {
fn drop(&mut self) {
RingBuffer::request_suspend(&self.channel.regs().ch(self.channel.num()));
self.request_stop();
while self.is_running() {}
// "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.
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 {
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 {
RingBuffer::Writable(buffer) => buffer.suspend().await,
RingBuffer::Readable(buffer) => buffer.suspend().await,
}
}
pub fn resume(&mut self) {
match &mut self.ring_buffer {
RingBuffer::Writable(buffer) => buffer.resume(),
RingBuffer::Readable(buffer) => buffer.resume(),
RingBuffer::Writable(buffer) => buffer.stop().await,
RingBuffer::Readable(buffer) => buffer.stop().await,
}
}

View File

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