80 lines
2.9 KiB
ReStructuredText
80 lines
2.9 KiB
ReStructuredText
.. _dma_api:
|
|
|
|
Direct Memory Access (DMA)
|
|
##########################
|
|
|
|
Overview
|
|
********
|
|
|
|
Direct Memory Access (Controller) is a commonly provided type of co-processor that can typically
|
|
offload transferring data to and from peripherals and memory.
|
|
|
|
The DMA API is not a portable API and really cannot be as each DMA has unique memory requirements,
|
|
peripheral interactions, and features. The API in effect provides a union of all useful DMA
|
|
functionality drivers have needed in the tree. It can still be a good abstraction, with care, for
|
|
peripheral devices for vendors where the DMA IP might be very similar but have slight variances.
|
|
|
|
Driver Implementation Expectations
|
|
**********************************
|
|
|
|
Synchronization and Ownership
|
|
+++++++++++++++++++++++++++++
|
|
|
|
From an API point of view, a DMA channel is a single-owner object, meaning the drivers should not
|
|
attempt to wrap a channel with kernel synchronization primitives such as mutexes or semaphores. If
|
|
DMA channels require mutating shared registers, those register updates should be wrapped in a spin
|
|
lock.
|
|
|
|
This enables the entire API to be low-cost and callable from any call context, including ISRs where
|
|
it may be very useful to start/stop/suspend/resume/reload a channel transfer.
|
|
|
|
Transfer Descriptor Memory Management
|
|
+++++++++++++++++++++++++++++++++++++
|
|
|
|
Drivers should not attempt to use heap allocations of any kind. If object pools are needed for
|
|
transfer descriptors then those should be setup in a way that does not break the promise of
|
|
ISR-allowable calls. Many drivers choose to create a simple static descriptor array per channel with
|
|
the size of the descriptor array adjustable using Kconfig.
|
|
|
|
Channel State Machine Expectations
|
|
++++++++++++++++++++++++++++++++++
|
|
|
|
DMA channels should be viewed as state machines that the DMA API provides transition events for in
|
|
the form of API calls. Every driver is expected to maintain its own channel state tracking. The busy
|
|
state of the channel should be inspectable at any time with :c:func:`dma_get_status()`.
|
|
|
|
A diagram showing those expectated possible state transitions and their API calls is provided here
|
|
for reference.
|
|
|
|
.. graphviz::
|
|
:caption: DMA state finite state machine
|
|
|
|
digraph {
|
|
node [style=rounded];
|
|
edge [fontname=Courier];
|
|
init [shape=point];
|
|
|
|
CONFIGURED [label=Configured,shape=box];
|
|
RUNNING [label=Running,shape=box];
|
|
SUSPENDED [label=Suspended,shape=box];
|
|
|
|
init -> CONFIGURED [label=dma_config];
|
|
|
|
CONFIGURED -> RUNNING [label=dma_start];
|
|
CONFIGURED -> CONFIGURED [label=dma_stop];
|
|
|
|
RUNNING -> CONFIGURED [label=dma_stop];
|
|
RUNNING -> RUNNING [label=dma_start];
|
|
RUNNING -> RUNNING [label=dma_resume, headport=w];
|
|
RUNNING -> SUSPENDED [label=dma_suspend];
|
|
|
|
SUSPENDED -> SUSPENDED [label=dma_suspend];
|
|
SUSPENDED -> RUNNING [label=dma_resume];
|
|
SUSPENDED -> CONFIGURED [label=dma_stop];
|
|
}
|
|
|
|
API Reference
|
|
*************
|
|
|
|
.. doxygengroup:: dma_interface
|