Struct mnemos_d1_core::dmac::Channel

source ·
pub struct Channel {
    idx: u8,
    xfer_done: &'static WaitCell,
}
Expand description

A DMA channel.

Channels are used to perform DMA transfers using the Channel::transfer method. Before performing a transfer, a channel must be configured with the desired ChannelModes using Channel::set_channel_modes.

The DMA controller owns a shared pool of 16 DMA channels, which may be used by drivers to initiate DMA transfers. Channels can be acquired from the shared pool using the Dmac::claim_channel and Dmac::try_claim_channel methods. Dropping a Channel releases it back to the shared pool, allowing it to be claimed by other drivers.

Fields§

§idx: u8§xfer_done: &'static WaitCell

Implementations§

source§

impl Channel

source

pub fn channel_index(&self) -> u8

Returns the channel index of this channel, from 0 to 15.

source

pub async unsafe fn transfer(&mut self, desc: NonNull<Descriptor>)

Performs a DMA transfer described by the provided Descriptor on this channel.

§Safety

The caller must ensure that the descriptor pointed to by desc, and the associated memory region used by the transfer, is valid for as long as the DMA transfer is active. When this function returns, the transfer has completed, and it is safe to drop the descriptor. If this future is cancelled, the transfer is cancelled and the descriptor and its associated buffer may be dropped safely. However, it is super ultra not okay to core::mem::forget this future. If you mem::forget a DMA transfer future inside your driver, you deserve whatever happens next.

§Cancel Safety

Dropping this future cancels the DMA transfer. If this future is dropped, the descriptor and its associated memory region may also be dropped safely.

Of course, the transfer may still have completed partially. If we were writing to a device, the device may be unhappy to have only gotten some of the data it wanted. If we were reading from a device, reads may have side effects and incomplete reads may leave the device in a weird state. Cancelling an incomplete transfer may result in, for example, writing out half of a string to the UART, or only part of a structured message over SPI, and so on. But, at least we don’t have abandoned DMA transfers running around in random parts of the heap you probably wanted to use for normal stuff like having strings, or whatever it is that people do on the computer.

source

pub unsafe fn set_channel_modes(&mut self, src: ChannelMode, dst: ChannelMode)

Sets the source and destination ChannelMode for this channel.

This configures the behavior of the two sides of the channel.

§Safety

This method should only be used when a DMA transfer is not currently in flight on this channel. This is ensured when using the Channel::transfer method, which mutably borrows the channel while the transfer is in progress, preventing the channel modes from being changed.

source

unsafe fn desc_addr_reg(&self) -> &Reg<DMAC_DESC_ADDR_SPEC>

Returns the raw DMAC_DESC_ADDR register corresponding to this channel.

§Safety

Manipulation of raw MMIO registers is generally unsafe. This method aliases the DMAC MMIO register block, and therefore should only be called within a critical section or while DMAC interrupts are disabled.

Manipulating a channel’s MMIO register block while a transfer is in progress on that channel is probably a bad idea. Using the Channel::transfer method, which mutably borrows the channel while the transfer is in progress, will prevent this method from being called until the transfer completes. However, if a transfer is started with Channel::start_descriptor, it is possible to manipulate the channel register block while a transfer is in progress. I don’t know what happens if you do this, but it’s probably bad.

source

unsafe fn en_reg(&self) -> &Reg<DMAC_EN_SPEC>

Returns the raw DMAC_EN register corresponding to this channel.

§Safety

Manipulation of raw MMIO registers is generally unsafe. This method aliases the DMAC MMIO register block, and therefore should only be called within a critical section or while DMAC interrupts are disabled.

Manipulating a channel’s MMIO register block while a transfer is in progress on that channel is probably a bad idea. Using the Channel::transfer method, which mutably borrows the channel while the transfer is in progress, will prevent this method from being called until the transfer completes. However, if a transfer is started with Channel::start_descriptor, it is possible to manipulate the channel register block while a transfer is in progress. I don’t know what happens if you do this, but it’s probably bad.

source

unsafe fn mode_reg(&self) -> &Reg<DMAC_MODE_SPEC>

Returns the raw DMAC_MODE register corresponding to this channel.

§Safety

Manipulation of raw MMIO registers is generally unsafe. This method aliases the DMAC MMIO register block, and therefore should only be called within a critical section or while DMAC interrupts are disabled.

Manipulating a channel’s MMIO register block while a transfer is in progress on that channel is probably a bad idea. Using the Channel::transfer method, which mutably borrows the channel while the transfer is in progress, will prevent this method from being called until the transfer completes. However, if a transfer is started with Channel::start_descriptor, it is possible to manipulate the channel register block while a transfer is in progress. I don’t know what happens if you do this, but it’s probably bad.

source

unsafe fn start_descriptor(&mut self, desc: NonNull<Descriptor>)

Begins a DMA transfer without waiting for it to complete.

This is a lower-level API, and you should probably use Channel::transfer instead.

§Safety

The caller must ensure that the descriptor pointed to by desc is valid for as long as the DMA transfer is active.

The caller must not initiate another transfer on this channel until the transfer started using start_descriptor completes. I don’t know what happens if you do this, but I’m sure it’s bad.

source

unsafe fn stop_dma(&mut self)

Cancel any DMA transfer currently in progress on this channel.

This is a lower-level API, and you should probably use Channel::transfer instead, as it stops the transfer automatically once it has completed or when the future is dropped.

§Safety

This is actually pretty safe. AFAICT, calling stop_dma on a channel with no transfer currently in flight seems fine, actually. But, this does a raw MMIO register write, so.

Trait Implementations§

source§

impl Debug for Channel

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for Channel

source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.