<< Previous | Index | Next >>

> ## 11. Direct Memory Access

> Dynamic C version 10 introduced support for the internal DMA controller of the Rabbit 4000 microprocessor. DMA stands for "Direct Memory Access." The DMA controller takes control of the address and data bus from the CPU so that data transfers occur without processor handling.There are eight DMA channels; a DMA channel is a system pathway for transferring data directly to or from memory and peripheral devices without using the CPU. DMA memory addresses are always physical addresses and are never translated by the MMU.

> The rest of this section discusses DMA from a software perspective. For detailed information about the DMA controller, see the Rabbit 4000 Microprocessor User's Manual.

> ### 11.1 DMA Registers and Global Resources

> There are some global resources associated with all DMA channels. These resources are managed by Dynamic C libraries because it would be difficult for most users to determine their optimal usage. The library `DMA.LIB` contains all of the DMA functionality available to the user. The advanced user can manually override the library settings by directly manipulating the DMA control registers; however, this is not recommended.

> The debug function `DMAprintRegs()` lets you view the values of the DMA master registers:

> - DMCR (DMA Master Control Register) - Transfer and interrupt priority levels.

> - DMCSR (DMA Master Control/Status Register) - DMA channel status

> - DMTCR (DMA Master Timing Control Register) - Sets the burst size, the inter-burst timing and the relative prioritization of the channels.

> For more information on Rabbit registers, click on "I/O Registers" on the Dynamic C help menu or consult the Rabbit 4000 Microprocessor User's Manual to get information about directly manipulating the DMA registers.

> ### 11.2 API Functions

> Dynamic C provides several API functions for use with the DMA controller that was introduced with the Rabbit 4000. These functions make it unnecessary for an application to directly manipulate the DMA registers. Complete descriptions for all DMA API functions can be found from within Dynamic C using the Function Lookup feature from the help menu (Ctrl+H); also, in the Dynamic C Function Reference Manual. In this section we will look at some of these functions.

> The function `DMAalloc()` is called to allocate a DMA channel; the function `DMAunalloc()` is called to release it. The handle returned by `DMAalloc()` is passed to all the DMA transfer functions (see Section 11.4) and must be passed to `DMAunalloc()` to release the channel. All eight channels are identical, with the priority between them either fixed or rotating.

> The function `DMAsetParameters()` accepts parameters that set transfer and interrupt priority levels, channel priority, maximum bytes per burst and minimum clocks between bursts. `DMAsetParameters()` must be called by an application before a DMA channel can be used; however, the channel can be allocated before `DMAsetParameters()` is called. The DMA parameters set in `DMAsetParameters()` are global, that is, they apply to all channels.

> Some low-level functions are also provided for the DMA controller. These functions use the DMA channel number instead of the handle returned by `DMAalloc()`. The function `DMAhandle2chan()` provides a DMA channel number when passed a valid handle.

> The low-level functions `DMAsetBufDesc()` and `DMAloadBufDesc()` work with a buffer descriptor associated with a DMA channel. A buffer descriptor is a memory structure that controls the DMA operation. It contains a control byte, a byte count for the data, a source address, a destination address and an optional link address. Low-level transfer functions are provided for use with the buffer descriptor functions. They are `DMAstartAuto()` and `DMAstartDirect()`.

> Sample programs located in `Samples\Rabbit4000\DMA\` illustrate many of the API functions.

> ### 11.3 DMA Interrupts

> An interrupt may be requested when a DMA channel has completed transferring data. All channels assert this type of interrupt at the same priority level, which can be set to level 1, 2, or 3 with a call to `DMAsetParameters()`. Whether or not an interrupt is requested at the end of a transfer is determined by flag options in the DMA transfer function. See Section 11.4.4 for more information.

> Each channel has its own interrupt vector in the processor's external interrupt vector table.

> ### 11.4 DMA Transfer Information

> A DMA transfer is requested when the channel wants the DMA controller to take control of the address and data buses.

> #### 11.4.1 DMA Transfer Priority

> DMA transfers may be programmed to occur at any priority level (0, 1, 2, or 3). Relative prioritization among the DMA channels is set using one of the following constants:

> - `DMA_IDP_FIXED` - fixed priorities, with higher channel numbers taking precedence

> - `DMA_IDP_ROTATE_FINE` - priorities are rotated after every byte transferred

> - `DMA_IDP_ROTATE_COARSE` - priorities rotated after every transfer request, the size of which is determined by "chunkiness," another parameter also passed to the function `DMAsetParameters()`.

> The DMA transfer priority and the relative prioritization among channels are set in `DMAsetParameters()`.

> #### 11.4.2 DMA Transfer Mode

> DMA transfers can happen in burst or single-cycle mode. The "chunkiness" parameter passed to the DMA transfer function determines the burst size.

> #### 11.4.3 DMA Transfer Functions

> There are three types of transfers, with associated transfer functions.

> 1. Memory-to-memory transfers. `Use DMAmem2mem()`.

> 2. Internal I/O address transfers to or from memory. Use `DMAioi2mem()` and `DMAmem2ioi()`, respectively.

> 3. External I/O address transfers to or from memory. Use `DMAioe2mem()` and `DMAmem2ioe()`, respectively.

> #### 11.4.4 DMA Transfer Function Flags

> The DMA transfer functions accept the following flags:

> - `DMA_F_REPEAT` - transfer will be a cycle.

> - `DMA_F_INTERRUPT` - indicates an interrupt will be triggered at the completion of the transfer.

> - `DMA_F_LAST_SPECIAL` - (only for Ethernet or HDLC peripherals) Internal Source: Status byte written to initial buffer descriptor before last data. Internal Destination: Last byte written to offset address for frame termination.

> - `DMA_F_SRC_DEC` - only for transfers with memory source. Indicates the source address should be decremented.

> - `DMA_F_DEST_DEC` - only for transfers with memory destination. Indicates the destination address should be incremented.

> - `DMA_F_STOP_MATCH` - indicates whether or not to stop the DMA transfer when a character is reached. The match byte and mask should have been set previously by calling the `DMAmatchSetup()` function.

> - `DMA_F_TIMER` - indicates the DMA timer will be used. Set the divisor first by calling the `DMAtimerSetup()` function. `DMA_F_TIMER_1BPR` indicates that the timed transfers will send one byte per request instead of the entire descriptor.

> ### 11.5 DMA with Ethernet

> Use of the Rabbit 4000 Ethernet imposes some restrictions on the global DMA settings. It is recommended that applications make use of the DMA API functions to avoid possibly breaking Ethernet by using DMA settings that are not compatible with the Ethernet restrictions. For example, Ethernet uses DMA channels 6 and 7 and fixed prioritization among the channels. There are also requirements regarding burst size and the minimum time between bursts. If you are using Ethernet and call the function `DMAsetParameters()` with parameters that are not compatible with the Ethernet restrictions, those parameters will be quietly ignored.

Dynamic C User's Manual | << Previous | Index | Next>> | rabbit.com