mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-28 21:00:59 +00:00
Remove Rx and Tx traits from the dma module (#3338)
* Remove Rx and Tx traits from the dma module * merge impl blocks
This commit is contained in:
parent
e1e04451ca
commit
17c09ccaec
@ -243,8 +243,6 @@ pub mod dma {
|
||||
DmaRxBuffer,
|
||||
DmaTxBuffer,
|
||||
PeripheralDmaChannel,
|
||||
Rx,
|
||||
Tx,
|
||||
},
|
||||
peripherals::AES,
|
||||
Blocking,
|
||||
|
@ -23,8 +23,6 @@ use crate::{
|
||||
DmaTxBuf,
|
||||
DmaTxBuffer,
|
||||
DmaTxInterrupt,
|
||||
Rx,
|
||||
Tx,
|
||||
},
|
||||
Async,
|
||||
Blocking,
|
||||
|
@ -1324,9 +1324,10 @@ impl TxCircularState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update<T>(&mut self, channel: &T) -> Result<(), DmaError>
|
||||
pub(crate) fn update<Dm, CH>(&mut self, channel: &ChannelTx<Dm, CH>) -> Result<(), DmaError>
|
||||
where
|
||||
T: Tx,
|
||||
Dm: DriverMode,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
if channel
|
||||
.pending_out_interrupts()
|
||||
@ -1735,60 +1736,6 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
/// The functions here are not meant to be used outside the HAL
|
||||
#[doc(hidden)]
|
||||
pub trait Rx: crate::private::Sealed {
|
||||
unsafe fn prepare_transfer_without_start(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
chain: &DescriptorChain,
|
||||
) -> Result<(), DmaError>;
|
||||
|
||||
unsafe fn prepare_transfer<BUF: DmaRxBuffer>(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
buffer: &mut BUF,
|
||||
) -> Result<(), DmaError>;
|
||||
|
||||
fn start_transfer(&mut self) -> Result<(), DmaError>;
|
||||
|
||||
fn stop_transfer(&mut self);
|
||||
|
||||
#[cfg(gdma)]
|
||||
fn set_mem2mem_mode(&mut self, value: bool);
|
||||
|
||||
fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
|
||||
|
||||
fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
|
||||
|
||||
fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt>;
|
||||
|
||||
fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>);
|
||||
|
||||
fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt>;
|
||||
|
||||
fn is_done(&self) -> bool;
|
||||
|
||||
fn has_error(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::DescriptorError)
|
||||
}
|
||||
|
||||
fn has_dscr_empty_error(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::DescriptorEmpty)
|
||||
}
|
||||
|
||||
fn has_eof_error(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::ErrorEof)
|
||||
}
|
||||
|
||||
fn clear_interrupts(&self);
|
||||
|
||||
fn waker(&self) -> &'static crate::asynch::AtomicWaker;
|
||||
}
|
||||
|
||||
// NOTE(p4): because the P4 has two different GDMAs, we won't be able to use
|
||||
// `GenericPeripheralGuard`.
|
||||
cfg_if::cfg_if! {
|
||||
@ -1940,14 +1887,15 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
impl<Dm, CH> Rx for ChannelRx<Dm, CH>
|
||||
#[allow(unused)]
|
||||
impl<Dm, CH> ChannelRx<Dm, CH>
|
||||
where
|
||||
Dm: DriverMode,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
// TODO: used by I2S, which should be rewritten to use the Preparation-based
|
||||
// API.
|
||||
unsafe fn prepare_transfer_without_start(
|
||||
pub(crate) unsafe fn prepare_transfer_without_start(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
chain: &DescriptorChain,
|
||||
@ -1992,7 +1940,7 @@ where
|
||||
self.do_prepare(preparation, peri)
|
||||
}
|
||||
|
||||
unsafe fn prepare_transfer<BUF: DmaRxBuffer>(
|
||||
pub(crate) unsafe fn prepare_transfer<BUF: DmaRxBuffer>(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
buffer: &mut BUF,
|
||||
@ -2002,7 +1950,7 @@ where
|
||||
self.do_prepare(preparation, peri)
|
||||
}
|
||||
|
||||
fn start_transfer(&mut self) -> Result<(), DmaError> {
|
||||
pub(crate) fn start_transfer(&mut self) -> Result<(), DmaError> {
|
||||
self.rx_impl.start();
|
||||
|
||||
if self
|
||||
@ -2015,93 +1963,62 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn stop_transfer(&mut self) {
|
||||
pub(crate) fn stop_transfer(&mut self) {
|
||||
self.rx_impl.stop()
|
||||
}
|
||||
|
||||
#[cfg(gdma)]
|
||||
fn set_mem2mem_mode(&mut self, value: bool) {
|
||||
pub(crate) fn set_mem2mem_mode(&mut self, value: bool) {
|
||||
self.rx_impl.set_mem2mem_mode(value);
|
||||
}
|
||||
|
||||
fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
pub(crate) fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
self.rx_impl.listen(interrupts);
|
||||
}
|
||||
|
||||
fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
pub(crate) fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
self.rx_impl.unlisten(interrupts);
|
||||
}
|
||||
|
||||
fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt> {
|
||||
pub(crate) fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt> {
|
||||
self.rx_impl.is_listening()
|
||||
}
|
||||
|
||||
fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
pub(crate) fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
|
||||
self.rx_impl.clear(interrupts);
|
||||
}
|
||||
|
||||
fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
|
||||
pub(crate) fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
|
||||
self.rx_impl.pending_interrupts()
|
||||
}
|
||||
|
||||
fn is_done(&self) -> bool {
|
||||
pub(crate) fn is_done(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::SuccessfulEof)
|
||||
}
|
||||
|
||||
fn clear_interrupts(&self) {
|
||||
pub(crate) fn clear_interrupts(&self) {
|
||||
self.rx_impl.clear_all();
|
||||
}
|
||||
|
||||
fn waker(&self) -> &'static crate::asynch::AtomicWaker {
|
||||
pub(crate) fn waker(&self) -> &'static crate::asynch::AtomicWaker {
|
||||
self.rx_impl.waker()
|
||||
}
|
||||
}
|
||||
|
||||
/// The functions here are not meant to be used outside the HAL
|
||||
#[doc(hidden)]
|
||||
pub trait Tx: crate::private::Sealed {
|
||||
unsafe fn prepare_transfer_without_start(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
chain: &DescriptorChain,
|
||||
) -> Result<(), DmaError>;
|
||||
|
||||
unsafe fn prepare_transfer<BUF: DmaTxBuffer>(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
buffer: &mut BUF,
|
||||
) -> Result<(), DmaError>;
|
||||
|
||||
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
|
||||
|
||||
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
|
||||
|
||||
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt>;
|
||||
|
||||
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>);
|
||||
|
||||
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt>;
|
||||
|
||||
fn start_transfer(&mut self) -> Result<(), DmaError>;
|
||||
|
||||
fn stop_transfer(&mut self);
|
||||
|
||||
fn is_done(&self) -> bool {
|
||||
self.pending_out_interrupts()
|
||||
.contains(DmaTxInterrupt::TotalEof)
|
||||
pub(crate) fn has_error(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::DescriptorError)
|
||||
}
|
||||
|
||||
fn has_error(&self) -> bool {
|
||||
self.pending_out_interrupts()
|
||||
.contains(DmaTxInterrupt::DescriptorError)
|
||||
pub(crate) fn has_dscr_empty_error(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::DescriptorEmpty)
|
||||
}
|
||||
|
||||
fn clear_interrupts(&self);
|
||||
|
||||
fn waker(&self) -> &'static crate::asynch::AtomicWaker;
|
||||
|
||||
fn last_out_dscr_address(&self) -> usize;
|
||||
pub(crate) fn has_eof_error(&self) -> bool {
|
||||
self.pending_in_interrupts()
|
||||
.contains(DmaRxInterrupt::ErrorEof)
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA transmit channel
|
||||
@ -2235,14 +2152,15 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
impl<Dm, CH> Tx for ChannelTx<Dm, CH>
|
||||
#[allow(unused)]
|
||||
impl<Dm, CH> ChannelTx<Dm, CH>
|
||||
where
|
||||
Dm: DriverMode,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
// TODO: used by I2S, which should be rewritten to use the Preparation-based
|
||||
// API.
|
||||
unsafe fn prepare_transfer_without_start(
|
||||
pub(crate) unsafe fn prepare_transfer_without_start(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
chain: &DescriptorChain,
|
||||
@ -2291,7 +2209,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn prepare_transfer<BUF: DmaTxBuffer>(
|
||||
pub(crate) unsafe fn prepare_transfer<BUF: DmaTxBuffer>(
|
||||
&mut self,
|
||||
peri: DmaPeripheral,
|
||||
buffer: &mut BUF,
|
||||
@ -2301,7 +2219,7 @@ where
|
||||
self.do_prepare(preparation, peri)
|
||||
}
|
||||
|
||||
fn start_transfer(&mut self) -> Result<(), DmaError> {
|
||||
pub(crate) fn start_transfer(&mut self) -> Result<(), DmaError> {
|
||||
self.tx_impl.start();
|
||||
while self.tx_impl.is_fifo_empty() && self.pending_out_interrupts().is_empty() {}
|
||||
|
||||
@ -2315,41 +2233,51 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn stop_transfer(&mut self) {
|
||||
pub(crate) fn stop_transfer(&mut self) {
|
||||
self.tx_impl.stop()
|
||||
}
|
||||
|
||||
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
|
||||
pub(crate) fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
|
||||
self.tx_impl.listen(interrupts);
|
||||
}
|
||||
|
||||
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
|
||||
pub(crate) fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
|
||||
self.tx_impl.unlisten(interrupts);
|
||||
}
|
||||
|
||||
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> {
|
||||
pub(crate) fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> {
|
||||
self.tx_impl.is_listening()
|
||||
}
|
||||
|
||||
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
|
||||
pub(crate) fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
|
||||
self.tx_impl.clear(interrupts);
|
||||
}
|
||||
|
||||
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
|
||||
pub(crate) fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
|
||||
self.tx_impl.pending_interrupts()
|
||||
}
|
||||
|
||||
fn waker(&self) -> &'static crate::asynch::AtomicWaker {
|
||||
pub(crate) fn waker(&self) -> &'static crate::asynch::AtomicWaker {
|
||||
self.tx_impl.waker()
|
||||
}
|
||||
|
||||
fn clear_interrupts(&self) {
|
||||
pub(crate) fn clear_interrupts(&self) {
|
||||
self.tx_impl.clear_all();
|
||||
}
|
||||
|
||||
fn last_out_dscr_address(&self) -> usize {
|
||||
pub(crate) fn last_out_dscr_address(&self) -> usize {
|
||||
self.tx_impl.last_dscr_address()
|
||||
}
|
||||
|
||||
pub(crate) fn is_done(&self) -> bool {
|
||||
self.pending_out_interrupts()
|
||||
.contains(DmaTxInterrupt::TotalEof)
|
||||
}
|
||||
|
||||
pub(crate) fn has_error(&self) -> bool {
|
||||
self.pending_out_interrupts()
|
||||
.contains(DmaTxInterrupt::DescriptorError)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -2569,6 +2497,8 @@ pub(crate) mod dma_private {
|
||||
use super::*;
|
||||
|
||||
pub trait DmaSupport {
|
||||
type DriverMode: DriverMode;
|
||||
|
||||
/// Wait until the transfer is done.
|
||||
///
|
||||
/// Depending on the peripheral this might include checking the DMA
|
||||
@ -2587,17 +2517,17 @@ pub(crate) mod dma_private {
|
||||
}
|
||||
|
||||
pub trait DmaSupportTx: DmaSupport {
|
||||
type TX: Tx;
|
||||
type Channel: DmaTxChannel;
|
||||
|
||||
fn tx(&mut self) -> &mut Self::TX;
|
||||
fn tx(&mut self) -> &mut ChannelTx<Self::DriverMode, Self::Channel>;
|
||||
|
||||
fn chain(&mut self) -> &mut DescriptorChain;
|
||||
}
|
||||
|
||||
pub trait DmaSupportRx: DmaSupport {
|
||||
type RX: Rx;
|
||||
type Channel: DmaRxChannel;
|
||||
|
||||
fn rx(&mut self) -> &mut Self::RX;
|
||||
fn rx(&mut self) -> &mut ChannelRx<Self::DriverMode, Self::Channel>;
|
||||
|
||||
fn chain(&mut self) -> &mut DescriptorChain;
|
||||
}
|
||||
@ -2906,26 +2836,26 @@ pub(crate) mod asynch {
|
||||
use super::*;
|
||||
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct DmaTxFuture<'a, TX>
|
||||
pub struct DmaTxFuture<'a, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
pub(crate) tx: &'a mut TX,
|
||||
pub(crate) tx: &'a mut ChannelTx<Async, CH>,
|
||||
}
|
||||
|
||||
impl<'a, TX> DmaTxFuture<'a, TX>
|
||||
impl<'a, CH> DmaTxFuture<'a, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
#[cfg_attr(esp32c2, allow(dead_code))]
|
||||
pub fn new(tx: &'a mut TX) -> Self {
|
||||
pub fn new(tx: &'a mut ChannelTx<Async, CH>) -> Self {
|
||||
Self { tx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<TX> core::future::Future for DmaTxFuture<'_, TX>
|
||||
impl<CH> core::future::Future for DmaTxFuture<'_, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
type Output = Result<(), DmaError>;
|
||||
|
||||
@ -2952,9 +2882,9 @@ pub(crate) mod asynch {
|
||||
}
|
||||
}
|
||||
|
||||
impl<TX> Drop for DmaTxFuture<'_, TX>
|
||||
impl<CH> Drop for DmaTxFuture<'_, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.tx
|
||||
@ -2963,25 +2893,25 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct DmaRxFuture<'a, RX>
|
||||
pub struct DmaRxFuture<'a, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
pub(crate) rx: &'a mut RX,
|
||||
pub(crate) rx: &'a mut ChannelRx<Async, CH>,
|
||||
}
|
||||
|
||||
impl<'a, RX> DmaRxFuture<'a, RX>
|
||||
impl<'a, CH> DmaRxFuture<'a, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
pub fn new(rx: &'a mut RX) -> Self {
|
||||
pub fn new(rx: &'a mut ChannelRx<Async, CH>) -> Self {
|
||||
Self { rx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<RX> core::future::Future for DmaRxFuture<'_, RX>
|
||||
impl<CH> core::future::Future for DmaRxFuture<'_, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
type Output = Result<(), DmaError>;
|
||||
|
||||
@ -3012,9 +2942,9 @@ pub(crate) mod asynch {
|
||||
}
|
||||
}
|
||||
|
||||
impl<RX> Drop for DmaRxFuture<'_, RX>
|
||||
impl<CH> Drop for DmaRxFuture<'_, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.rx.unlisten_in(
|
||||
@ -3026,28 +2956,28 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
pub struct DmaTxDoneChFuture<'a, TX>
|
||||
pub struct DmaTxDoneChFuture<'a, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
pub(crate) tx: &'a mut TX,
|
||||
pub(crate) tx: &'a mut ChannelTx<Async, CH>,
|
||||
_a: (),
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
impl<'a, TX> DmaTxDoneChFuture<'a, TX>
|
||||
impl<'a, CH> DmaTxDoneChFuture<'a, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
pub fn new(tx: &'a mut TX) -> Self {
|
||||
pub fn new(tx: &'a mut ChannelTx<Async, CH>) -> Self {
|
||||
Self { tx, _a: () }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
impl<TX> core::future::Future for DmaTxDoneChFuture<'_, TX>
|
||||
impl<CH> core::future::Future for DmaTxDoneChFuture<'_, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
type Output = Result<(), DmaError>;
|
||||
|
||||
@ -3079,9 +3009,9 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
impl<TX> Drop for DmaTxDoneChFuture<'_, TX>
|
||||
impl<CH> Drop for DmaTxDoneChFuture<'_, CH>
|
||||
where
|
||||
TX: Tx,
|
||||
CH: DmaTxChannel,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.tx
|
||||
@ -3090,28 +3020,28 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
pub struct DmaRxDoneChFuture<'a, RX>
|
||||
pub struct DmaRxDoneChFuture<'a, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
pub(crate) rx: &'a mut RX,
|
||||
pub(crate) rx: &'a mut ChannelRx<Async, CH>,
|
||||
_a: (),
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
impl<'a, RX> DmaRxDoneChFuture<'a, RX>
|
||||
impl<'a, CH> DmaRxDoneChFuture<'a, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
pub fn new(rx: &'a mut RX) -> Self {
|
||||
pub fn new(rx: &'a mut ChannelRx<Async, CH>) -> Self {
|
||||
Self { rx, _a: () }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
impl<RX> core::future::Future for DmaRxDoneChFuture<'_, RX>
|
||||
impl<CH> core::future::Future for DmaRxDoneChFuture<'_, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
type Output = Result<(), DmaError>;
|
||||
|
||||
@ -3147,9 +3077,9 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
impl<RX> Drop for DmaRxDoneChFuture<'_, RX>
|
||||
impl<CH> Drop for DmaRxDoneChFuture<'_, CH>
|
||||
where
|
||||
RX: Rx,
|
||||
CH: DmaRxChannel,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.rx.unlisten_in(
|
||||
|
@ -89,8 +89,6 @@ use crate::{
|
||||
PeripheralRxChannel,
|
||||
PeripheralTxChannel,
|
||||
ReadBuffer,
|
||||
Rx,
|
||||
Tx,
|
||||
WriteBuffer,
|
||||
},
|
||||
gpio::interconnect::PeripheralOutput,
|
||||
@ -420,6 +418,8 @@ impl<Dm> DmaSupport for I2sTx<'_, Dm>
|
||||
where
|
||||
Dm: DriverMode,
|
||||
{
|
||||
type DriverMode = Dm;
|
||||
|
||||
fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) {
|
||||
self.i2s.wait_for_tx_done();
|
||||
}
|
||||
@ -433,9 +433,9 @@ impl<'d, Dm> DmaSupportTx for I2sTx<'d, Dm>
|
||||
where
|
||||
Dm: DriverMode,
|
||||
{
|
||||
type TX = ChannelTx<Dm, PeripheralTxChannel<AnyI2s<'d>>>;
|
||||
type Channel = PeripheralTxChannel<AnyI2s<'d>>;
|
||||
|
||||
fn tx(&mut self) -> &mut Self::TX {
|
||||
fn tx(&mut self) -> &mut ChannelTx<Dm, PeripheralTxChannel<AnyI2s<'d>>> {
|
||||
&mut self.tx_channel
|
||||
}
|
||||
|
||||
@ -548,6 +548,8 @@ impl<Dm> DmaSupport for I2sRx<'_, Dm>
|
||||
where
|
||||
Dm: DriverMode,
|
||||
{
|
||||
type DriverMode = Dm;
|
||||
|
||||
fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) {
|
||||
self.i2s.wait_for_rx_done();
|
||||
}
|
||||
@ -561,9 +563,9 @@ impl<'d, Dm> DmaSupportRx for I2sRx<'d, Dm>
|
||||
where
|
||||
Dm: DriverMode,
|
||||
{
|
||||
type RX = ChannelRx<Dm, PeripheralRxChannel<AnyI2s<'d>>>;
|
||||
type Channel = PeripheralRxChannel<AnyI2s<'d>>;
|
||||
|
||||
fn rx(&mut self) -> &mut Self::RX {
|
||||
fn rx(&mut self) -> &mut ChannelRx<Dm, PeripheralRxChannel<AnyI2s<'d>>> {
|
||||
&mut self.rx_channel
|
||||
}
|
||||
|
||||
@ -1784,9 +1786,7 @@ pub mod asynch {
|
||||
asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture},
|
||||
DmaEligible,
|
||||
ReadBuffer,
|
||||
Rx,
|
||||
RxCircularState,
|
||||
Tx,
|
||||
TxCircularState,
|
||||
WriteBuffer,
|
||||
},
|
||||
|
@ -112,7 +112,6 @@ use crate::{
|
||||
DmaError,
|
||||
DmaTxBuffer,
|
||||
PeripheralTxChannel,
|
||||
Tx,
|
||||
},
|
||||
gpio::{
|
||||
interconnect::{OutputConnection, PeripheralOutput},
|
||||
|
@ -62,7 +62,7 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
clock::Clocks,
|
||||
dma::{ChannelRx, DmaError, DmaPeripheral, DmaRxBuffer, PeripheralRxChannel, Rx, RxChannelFor},
|
||||
dma::{ChannelRx, DmaError, DmaPeripheral, DmaRxBuffer, PeripheralRxChannel, RxChannelFor},
|
||||
gpio::{
|
||||
interconnect::{PeripheralInput, PeripheralOutput},
|
||||
InputSignal,
|
||||
|
@ -103,7 +103,7 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
clock::Clocks,
|
||||
dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, Tx, TxChannelFor},
|
||||
dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, TxChannelFor},
|
||||
gpio::{interconnect::PeripheralOutput, Level, OutputSignal},
|
||||
lcd_cam::{
|
||||
calculate_clkm,
|
||||
|
@ -59,7 +59,7 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
clock::Clocks,
|
||||
dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, Tx, TxChannelFor},
|
||||
dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, TxChannelFor},
|
||||
gpio::{
|
||||
interconnect::{OutputConnection, PeripheralOutput},
|
||||
OutputSignal,
|
||||
|
@ -139,9 +139,7 @@ use crate::{
|
||||
DmaTxBuffer,
|
||||
PeripheralRxChannel,
|
||||
PeripheralTxChannel,
|
||||
Rx,
|
||||
RxChannelFor,
|
||||
Tx,
|
||||
TxChannelFor,
|
||||
},
|
||||
gpio::{
|
||||
|
@ -48,7 +48,7 @@ use super::{BitOrder, DataMode, DmaError, Error, Mode};
|
||||
use crate::{
|
||||
asynch::AtomicWaker,
|
||||
clock::Clocks,
|
||||
dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx},
|
||||
dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer},
|
||||
gpio::{
|
||||
interconnect::{PeripheralInput, PeripheralOutput},
|
||||
InputSignal,
|
||||
@ -1394,6 +1394,55 @@ mod dma {
|
||||
pins: self.pins,
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_idle_async(&mut self) {
|
||||
if self.rx_transfer_in_progress {
|
||||
_ = DmaRxFuture::new(&mut self.channel.rx).await;
|
||||
self.rx_transfer_in_progress = false;
|
||||
}
|
||||
|
||||
struct Fut(Driver);
|
||||
impl Future for Fut {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.0.interrupts().contains(SpiInterrupt::TransferDone) {
|
||||
#[cfg(esp32)]
|
||||
// Need to poll for done-ness even after interrupt fires.
|
||||
if self.0.busy() {
|
||||
cx.waker().wake_by_ref();
|
||||
return Poll::Pending;
|
||||
}
|
||||
|
||||
self.0.clear_interrupts(SpiInterrupt::TransferDone.into());
|
||||
return Poll::Ready(());
|
||||
}
|
||||
|
||||
self.0.state.waker.register(cx.waker());
|
||||
self.0
|
||||
.enable_listen(SpiInterrupt::TransferDone.into(), true);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
impl Drop for Fut {
|
||||
fn drop(&mut self) {
|
||||
self.0
|
||||
.enable_listen(SpiInterrupt::TransferDone.into(), false);
|
||||
}
|
||||
}
|
||||
|
||||
if !self.is_done() {
|
||||
Fut(self.driver()).await;
|
||||
}
|
||||
|
||||
if self.tx_transfer_in_progress {
|
||||
// In case DMA TX buffer is bigger than what the SPI consumes, stop the DMA.
|
||||
if !self.channel.tx.is_done() {
|
||||
self.channel.tx.stop_transfer();
|
||||
}
|
||||
self.tx_transfer_in_progress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dm> core::fmt::Debug for SpiDma<'_, Dm>
|
||||
@ -1470,55 +1519,6 @@ mod dma {
|
||||
fence(Ordering::Acquire);
|
||||
}
|
||||
|
||||
async fn wait_for_idle_async(&mut self) {
|
||||
if self.rx_transfer_in_progress {
|
||||
_ = DmaRxFuture::new(&mut self.channel.rx).await;
|
||||
self.rx_transfer_in_progress = false;
|
||||
}
|
||||
|
||||
struct Fut(Driver);
|
||||
impl Future for Fut {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.0.interrupts().contains(SpiInterrupt::TransferDone) {
|
||||
#[cfg(esp32)]
|
||||
// Need to poll for done-ness even after interrupt fires.
|
||||
if self.0.busy() {
|
||||
cx.waker().wake_by_ref();
|
||||
return Poll::Pending;
|
||||
}
|
||||
|
||||
self.0.clear_interrupts(SpiInterrupt::TransferDone.into());
|
||||
return Poll::Ready(());
|
||||
}
|
||||
|
||||
self.0.state.waker.register(cx.waker());
|
||||
self.0
|
||||
.enable_listen(SpiInterrupt::TransferDone.into(), true);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
impl Drop for Fut {
|
||||
fn drop(&mut self) {
|
||||
self.0
|
||||
.enable_listen(SpiInterrupt::TransferDone.into(), false);
|
||||
}
|
||||
}
|
||||
|
||||
if !self.is_done() {
|
||||
Fut(self.driver()).await;
|
||||
}
|
||||
|
||||
if self.tx_transfer_in_progress {
|
||||
// In case DMA TX buffer is bigger than what the SPI consumes, stop the DMA.
|
||||
if !self.channel.tx.is_done() {
|
||||
self.channel.tx.stop_transfer();
|
||||
}
|
||||
self.tx_transfer_in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety:
|
||||
///
|
||||
/// The caller must ensure to not access the buffer contents while the
|
||||
@ -1545,8 +1545,7 @@ mod dma {
|
||||
bytes_to_write,
|
||||
rx_buffer,
|
||||
tx_buffer,
|
||||
&mut self.channel.rx,
|
||||
&mut self.channel.tx,
|
||||
&mut self.channel,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1591,8 +1590,7 @@ mod dma {
|
||||
bytes_to_write,
|
||||
&mut EmptyBuf,
|
||||
&mut self.address_buffer,
|
||||
&mut self.channel.rx,
|
||||
&mut self.channel.tx,
|
||||
&mut self.channel,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -2748,15 +2746,14 @@ impl DmaDriver {
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg_attr(place_spi_driver_in_ram, ram)]
|
||||
unsafe fn start_transfer_dma<RX: Rx, TX: Tx>(
|
||||
unsafe fn start_transfer_dma<Dm: DriverMode>(
|
||||
&self,
|
||||
_full_duplex: bool,
|
||||
rx_len: usize,
|
||||
tx_len: usize,
|
||||
rx_buffer: &mut impl DmaRxBuffer,
|
||||
tx_buffer: &mut impl DmaTxBuffer,
|
||||
rx: &mut RX,
|
||||
tx: &mut TX,
|
||||
channel: &mut Channel<Dm, PeripheralDmaChannel<AnySpi<'_>>>,
|
||||
) -> Result<(), Error> {
|
||||
#[cfg(esp32s2)]
|
||||
{
|
||||
@ -2775,8 +2772,10 @@ impl DmaDriver {
|
||||
self.enable_dma();
|
||||
|
||||
if rx_len > 0 {
|
||||
rx.prepare_transfer(self.dma_peripheral, rx_buffer)
|
||||
.and_then(|_| rx.start_transfer())?;
|
||||
channel
|
||||
.rx
|
||||
.prepare_transfer(self.dma_peripheral, rx_buffer)
|
||||
.and_then(|_| channel.rx.start_transfer())?;
|
||||
} else {
|
||||
#[cfg(esp32)]
|
||||
{
|
||||
@ -2793,8 +2792,10 @@ impl DmaDriver {
|
||||
}
|
||||
}
|
||||
if tx_len > 0 {
|
||||
tx.prepare_transfer(self.dma_peripheral, tx_buffer)
|
||||
.and_then(|_| tx.start_transfer())?;
|
||||
channel
|
||||
.tx
|
||||
.prepare_transfer(self.dma_peripheral, tx_buffer)
|
||||
.and_then(|_| channel.tx.start_transfer())?;
|
||||
}
|
||||
|
||||
#[cfg(gdma)]
|
||||
@ -3849,6 +3850,8 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::dma::{Channel, PeripheralDmaChannel};
|
||||
|
||||
impl Future for SpiFuture<'_> {
|
||||
type Output = ();
|
||||
|
||||
|
@ -172,8 +172,6 @@ pub mod dma {
|
||||
DmaTxBuffer,
|
||||
EmptyBuf,
|
||||
PeripheralDmaChannel,
|
||||
Rx,
|
||||
Tx,
|
||||
},
|
||||
DriverMode,
|
||||
};
|
||||
@ -259,8 +257,7 @@ pub mod dma {
|
||||
bytes_to_write,
|
||||
&mut EmptyBuf,
|
||||
&mut buffer,
|
||||
&mut self.channel.rx,
|
||||
&mut self.channel.tx,
|
||||
&mut self.channel,
|
||||
)
|
||||
};
|
||||
if let Err(err) = result {
|
||||
@ -295,8 +292,7 @@ pub mod dma {
|
||||
0,
|
||||
&mut buffer,
|
||||
&mut EmptyBuf,
|
||||
&mut self.channel.rx,
|
||||
&mut self.channel.tx,
|
||||
&mut self.channel,
|
||||
)
|
||||
};
|
||||
if let Err(err) = result {
|
||||
@ -341,8 +337,7 @@ pub mod dma {
|
||||
bytes_to_write,
|
||||
&mut rx_buffer,
|
||||
&mut tx_buffer,
|
||||
&mut self.channel.rx,
|
||||
&mut self.channel.tx,
|
||||
&mut self.channel,
|
||||
)
|
||||
};
|
||||
if let Err(err) = result {
|
||||
@ -462,29 +457,28 @@ pub mod dma {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
unsafe fn start_transfer_dma<RX, TX>(
|
||||
unsafe fn start_transfer_dma<Dm: DriverMode>(
|
||||
&self,
|
||||
read_buffer_len: usize,
|
||||
write_buffer_len: usize,
|
||||
rx_buffer: &mut impl DmaRxBuffer,
|
||||
tx_buffer: &mut impl DmaTxBuffer,
|
||||
rx: &mut RX,
|
||||
tx: &mut TX,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
RX: Rx,
|
||||
TX: Tx,
|
||||
{
|
||||
channel: &mut Channel<Dm, PeripheralDmaChannel<AnySpi<'_>>>,
|
||||
) -> Result<(), Error> {
|
||||
self.enable_dma();
|
||||
|
||||
self.info.reset_spi();
|
||||
|
||||
if read_buffer_len > 0 {
|
||||
rx.prepare_transfer(self.dma_peripheral, rx_buffer)?;
|
||||
channel
|
||||
.rx
|
||||
.prepare_transfer(self.dma_peripheral, rx_buffer)?;
|
||||
}
|
||||
|
||||
if write_buffer_len > 0 {
|
||||
tx.prepare_transfer(self.dma_peripheral, tx_buffer)?;
|
||||
channel
|
||||
.tx
|
||||
.prepare_transfer(self.dma_peripheral, tx_buffer)?;
|
||||
}
|
||||
|
||||
#[cfg(esp32)]
|
||||
@ -503,11 +497,11 @@ pub mod dma {
|
||||
self.regs().cmd().modify(|_, w| w.usr().set_bit());
|
||||
|
||||
if read_buffer_len > 0 {
|
||||
rx.start_transfer()?;
|
||||
channel.rx.start_transfer()?;
|
||||
}
|
||||
|
||||
if write_buffer_len > 0 {
|
||||
tx.start_transfer()?;
|
||||
channel.tx.start_transfer()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user