New DMA: Overview 

In addition to the four DMA channels that were available with NITRO, the TWL hardware has four new DMA channels. The new DMA allows more precise configuration than was possible with the legacy DMA. This section describes the new DMA.

MINDmaConfig Structure

The new DMA uses the members of the MINDmaConfig structure as parameters when it is running. This structure contains information that is not likely to change for each DMA operation. It does not contain values that will change on a case-by-case basis, such as the overall transfer size or the source/destination addresses for the transfer.

Specifically, the structure contains the following values.

Member Name Description Related Register Initial Value
intervalTimer Interval timer for block transfers. d15-0 in DMAxBCNT MI_NDMA_NO_INTERVAL
prescaler Prescaler of interval timer for block transfers. d17-16 in DMAxBCNT MI_NDMA_INTERVAL_PS_1
blockWord Number of words in the block transfer. d19-16 in DMAx_CNT MI_NDMA_BWORD_1
wordCount Number of words in the transfer. DMAxWCNT MI_NDMA_AT_A_TIME


Separate structures are provided for each of the four new DMA channels within the library, so DMA transfers can be performed using different settings for each channel.

Call the MI_InitNDmaConfig function to initialize the MINDmaConfig structure members for all NDMA channels. You do not have to call this function directly because it is called from the MI_InitNDma function (which in turn is called from the OS_Init function).

Call the MI_GetNDmaConfig function to copy the MINDmaConfig structure set for the current new DMA channel to a MINDmaConfig structure prepared by the user (developer). Call the MI_SetNDmaConfig function to copy a MINDmaConfig structure prepared by the user (developer) to the MINDmaConfig structure set for the new DMA channel.

The MI_SetNDmaInterval, MI_GetNDmaIntervalTimer, MI_GetNDmaIntervalPrescaler, MI_SetNDmaBlockWord, MI_GetNDmaBlockWord, MI_SetNDmaWordCount, and MI_GetNDmaWordCount functions overwrite or get some of the members of the MINDmaConfig structure set for the new DMA.

To initialize settings that have been overwritten, use the MI_InitNDmaConfig function described earlier.

DMA Operation Instructions

The following instructions exist for the new DMA.

MI_NDmaCopy*    Uses the new DMA to copy.
MI_NDmaFill*    Uses the new DMA to fill with the specified data.
MI_NDmaClear*  Uses the new DMA to fill with 0s.
MI_NDmaSend*    Uses the new DMA to send data to a fixed address.
MI_NDmaRecv*    Uses the new DMA to reads data from a fixed address.
MI_NDmaPipe*    Uses the new DMA to send data from a fixed address to another fixed address.

Reading or writing data from a fixed address makes frequent use of operations on the I/O registers.

For each of these, there are derivative functions that have minor differences in terms of their operation. Below is an example that explains the MI_NDmaCopy* functions, but the naming conventions shown below apply to other functions as well.

(1) MI_NDmaCopy and MI_NDmaCopyAsync

Functions that end in Async are asynchronous functions. Conversely, functions that do not are synchronous functions. Synchronous functions are guaranteed to wait for new DMA operations to complete, but control leaves asynchronous functions without waiting for completion. Asynchronous functions can find out that a DMA operation has completed, either by setting a callback function that is called when the operation completes, or by using the MI_IsNDmaBusy function, which determines whether the given new DMA channel is in use. The MI_WaitNDma function waits until the given new DMA channel becomes usable.

(2) MI_NDmaCopy and MI_NDmaCopyEx

Functions that include Ex are provided with an external MINDmaConfig structure. Conversely, functions without "Ex" use the MINDmaConfig structures that are maintained by the library and already configured. Functions with Ex are effective for initiating temporary DMA operations using different parameters from those that are normally used.

(3) MI_NDmaCopy and MI_NDmaCopy_Dev

Functions that end in _Dev synchronize the start of DMA operations with an interrupt from a peripheral device. Conversely, functions without "_Dev" start operations immediately. See DMA Start Timing for the values that can be set as peripheral devices.

(4) MI_NDmaCopy and MI_NDmaCopy_SetUp

Functions that end in _SetUp only perform configuration, and do not start DMA operations. The actual DMA operations start after MI_NDmaRestart is called.


These four specifiers yield a total of 16 variants of the MI_NDmaCopy* function.

Functions Synchronous/Asynchronous MINDmaConfig Start DMA
No _SetUp (Run DMA)
MI_NDmaCopy Synchronous Stored in the library Immediately
MI_NDmaCopyAsync Asynchronous Stored in the library Immediately
MI_NDmaCopyEx Synchronous User-defined Immediately
MI_NDmaCopyExAsync Asynchronous User-defined Immediately
MI_NDmaCopy_Dev Synchronous Stored in the library Interrupt from peripheral device
MI_NDmaCopyAsync_Dev Asynchronous Stored in the library Interrupt from peripheral device
MI_NDmaCopyEx_Dev Synchronous User-defined Interrupt from peripheral device
MI_NDmaCopyExAsync_Dev Asynchronous User-defined Interrupt from peripheral device
With _SetUp (Only perform configuration for running DMA)
MI_NDmaCopy_SetUp Synchronous Stored in the library Immediately
MI_NDmaCopyAsync_SetUp Asynchronous Stored in the library Immediately
MI_NDmaCopyEx_SetUp Synchronous User-defined Immediately
MI_NDmaCopyExAsync_SetUp Asynchronous User-defined Immediately
MI_NDmaCopy_Dev_SetUp Synchronous Stored in the library Interrupt from peripheral device
MI_NDmaCopyAsync_Dev_SetUp Asynchronous Stored in the library Interrupt from peripheral device
MI_NDmaCopyEx_Dev_SetUp Synchronous User-defined Interrupt from peripheral device
MI_NDmaCopyExAsync_Dev_SetUp Asynchronous User-defined Interrupt from peripheral device

Stopping New DMA

Call MI_StopNDma to stop the specified new DMA channel.

Call MI_StopAllNDma to stop all new DMA channels. This function calls MI_StopNDma for the new DMA channels 0-3 in order.

Arbitration Method

You can select the the arbitration method used between the new DMA channels. Two options are available: the fixed method and the round-robin method.

With the fixed method, fixed priorities are set. If a request for a DMA channel is issued whose priority is higher than the DMA channel that is currently running, the current request is paused once the block transfer has completed for the number of words specified in WORDCNT, and the DMA transfer for the higher-priority DMA channel is run. Conversely, if a request is issued for a DMA channel that is lower in priority than the one currently running, the incoming request is put on hold.

With the round-robin method, the MI library looks up the DMA channel during the startup request, and once the block transfer has completed for WORDCNT words (this number is specified for each general-purpose DMA channel), the ownership rights to the AHB bus alternates in round-robin fashion in the order DMA0, DMA1, DMA2, DMA3, DSP or ARM9, DMA0, DMA1, DMA2, ... (including all DMA channels for which there are DMA transfer requests).

When using the round-robin method, you can set the number of cycles for which access is possible during requests for the AHB bus of the DSP or ARM9.

The following function is used to configure the arbitration method and the number of cycles that are accessible when the round-robin method is used. MI_SetNDmaArbitrament

The following functions are used to get the values that are currently set.
MI_GetNDmaArbitrament
MI_GetNDmaArbitramentRoundRobinCycle

Priority

The priorities for the AHB bus are shown below.

If using the fixed method for DMA arbitration:

Old DMAC0 > Old DMAC1 > Old DMAC2 > Old DMAC3 > New DMAC0 > New DMAC1 > New DMAC2 > New DMA3 > DSP > ARM9

If using the round-robin method for DMA arbitration:

The new DMA priorities are removed, and the bus ownership is passed around in the following order:

Old DMAC0 > Old DMAC1 > Old DMAC2 > Old DMAC3 > (New DMAC0 = New DMAC1 = New DMAC2 = New DMA3) > DSP > ARM9

DMA Start Timing

Among the new DMA functions, functions that end in _Dev, such as MI_NDmaCopy_Dev, can make the timing of starting DMA dependent on a startup request based on an interrupt from a peripheral device. Functions that do not end in _Dev start immediately.

You can specify this by passing the MINDmaDevice type value (u32 typedef) as an argument of a function. The following table shows the values and start timings.

MINDmaDevice Type Value New DMA Start Timing
MI_NDMA_TIMING_TIMER0 DMA startup request from Timer 0
MI_NDMA_TIMING_TIMER1 DMA startup request from Timer 1
MI_NDMA_TIMING_TIMER2 DMA startup request from Timer 2
MI_NDMA_TIMING_TIMER3 DMA startup request from Timer 3
MI_NDMA_TIMING_CARD DMA startup request from Card
MI_NDMA_TIMING_V_BLANK DMA startup request from V-Blank
MI_NDMA_TIMING_H_BLANK DMA startup request from H-Blank
MI_NDMA_TIMING_DISP DMA startup request synchronized with display
MI_NDMA_TIMING_DISP_MMEM DMA startup request synchronized with the work RAM display
MI_NDMA_TIMING_GXFIFO DMA startup request from the geometry command FIFO
MI_NDMA_TIMING_CAMERA DMA startup request from camera transfer

Revision History

2008/11/19 Added startup timing information.
2008/09/11 Initial version.


CONFIDENTIAL