Spra 529 A
Spra 529 A
ABSTRACT
The TMS320C6000 on-chip direct memory access (DMA) controller from Texas Instruments
is used to transfer data between two locations in the memory map in the background of CPU
operation. Typically, the DMA is used to:
Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 System Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3 Data Relocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.1 Block Move Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 Extremely Large Block Move Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.3 Data-Sorting Transfer Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4 Servicing a Peripheral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.1 Synchronized Data Transfer Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.2 Split-Mode Transfer Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.3 Frame-Synchronized Data Transfer Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.4 Endian Mode Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5 Repetitive DMA Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.1 Transferring Data To and From Circular Buffers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.2 Ping-Pong Transfer Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.3 Program Paging Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1
SPRA529A
List of Figures
Figure 1. Block Move Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Figure 2. Primary Control Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Figure 3. Transfer Counter Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Figure 4. Extremely Large Block Move Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Figure 5. Data Sorting Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Figure 6. Global Index Register A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Figure 7. Synchronized Data Transfer Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Figure 8. Split-Mode Transfer Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Figure 9. Frame-Synchronized Transfer Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Figure 10. Secondary Control Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Figure 11. DXR Byte Locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Figure 12. DRR Byte Locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Figure 13. Circular Buffer Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Figure 14. Ping-Pong Buffer Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Figure 15. Program Paging Example Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
List of Tables
Table 1. DMA Channel Synchronization Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Table 2. DMA Channel SPLIT Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Table 3. Possible DMA Source and Destination Address for Servicing McBSP0,, . . . . . . . . . . . . . . . . . 19
Table 4. DMA Channel Condition Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1 Introduction
The TMS320C6000 on-chip DMA controller transfers data from one memory-mapped location to
another, without the intervention of the central processing unit (CPU). The DMA transfers data
between internal memory, peripherals, and external devices in the background, allowing the
CPU to remain active during data transfers. Four DMA channels can be independently
configured to perform different types of transfers.
The DMA is highly flexible, with many different types of transfers available to enable faster
throughput by the CPU through data organization. With the DMA, data can be transferred to and
from internal program memory, internal data memory, an external memory space, an external
analog front end (AFE) circuit, or the multichannel buffered serial ports (McBSPs). The DMA
also allows data currently in memory to be reorganized to increase the CPU’s effectiveness.
Each channel of the DMA has the following set of registers that must be configured prior to
beginning a data transfer:
• Primary control register – Used to configure the transfer
• Secondary control register – Used to enable interrupts to the CPU, and to monitor the
channel’s activity
• Transfer counter register – Used to keep track of the transferred elements
• Source address register – Memory location from which the element is transferred
• Destination address register – Memory location to which the element is transferred
In addition, several global DMA registers can be used by any of the DMA channels to perform
more complicated transfers:
• Global address registers (A, B, C, and D) – Used as either a split address or address reload
value
• Global index registers (A and B) – Used to control address updates during a transfer
• Global count reload registers (A and B) – Used to reload the transfer counter register of a
DMA channel
Each of the global DMA registers can be used by any of the DMA channels, and more than one
channel can use the same register at a time.
One additional DMA register, the auxiliary control register, is used to set the priority of the
auxiliary channel with respect to the four main DMA channels and the CPU. The auxiliary
channel is used by the host interface to access the C6000 memory.
The TMS320C6000 Peripherals Reference Guide (SPRU190) offers a complete description of
the DMA structure, and should be used in conjunction with this document.
2 System Structure
All accesses to external memory spaces must go through the external memory interface (EMIF).
External memory types supported on the C6000 are synchronous dynamic random-access
memory (SDRAM), synchronous burst static random access memory (SBSRAM), and
asynchronous memories. To understand how to configure different memory spaces, see the
TMS320C6000 Peripherals Reference Guide (SPRU190).
External analog front–end (AFE) circuits predominantly use the asynchronous memory interface
of the C6000. A typical AFE configuration includes a data-in address, a data-out address, a read
sync signal, and a write sync signal. Synchronization events are connected to one of the four
external interrupt pins of the device (EXT_INT[7:4]).
The McBSP is the only on-chip peripheral that can require servicing by the DMA. Each McBSP
has a data receive register (DRR), a data transmit register (DXR), a transmit-event signal
(XEVT), and a receive-event signal (REVT). The DRR and DXR are memory-mapped registers.
The events occur whenever data is transferred out (XEVT) or transferred in (REVT).
Internal data memory is divided into several 16-bit banks. The TMS320C6201 includes four
banks: the C6201B and C6202 have two blocks of four banks, with each block occupying half of
the data memory, and the C6701 has two blocks of eight banks. Each bank can only be
accessed once per cycle, either by the DMA or by one of the CPU sides (A or B). If both the
DMA and the CPU attempt to access the same bank during the same cycle, the priority bit set in
the DMA channel’s priority control register determines the order in which the access is granted.
Internal program memory always gives the CPU priority over the DMA. For the DMA to access
program memory, there must be time slots during which it can get in. These slots occur when a
fetch packet (eight instructions) contains multiple execute packets (a group of instructions
executed in one cycle). This leaves cycles in which the CPU is not requesting a fetch packet, and
the DMA can access the program memory. The C6202 has two blocks of program memory. The
DMA can access one block, while the CPU is executing code from the second, without contention.
3 Data Relocation
The purpose of the DMA is to move data elements from one location to another. Through proper
configuration of the DMA channel control registers, the data to be transferred can be moved in
its current format, or restructured to fit a particular application.
The simple case is a block move, in which a contiguous memory space is copied, unaltered from
one location to another. This transfer requires the minimum amount of setup, and is usually
performed either to transfer a program section from an external memory location to internal
program memory, or to transfer a data section between external memory and internal data
memory.
By taking advantage of some DMA features, a more complicated transfer can be performed, in
which a section of data is reorganized during the transfer. One example of this is sorting, in
which a data block divided into contiguous frames of equal size is reorganized in memory by
ordinal location within a frame. In other words, the first element of the first frame is located next
to the first element of the second frame. This type of transfer is frequently performed when
multiple frames of data are arriving to the device via the serial port (or AFE), or when data arrays
located in external memory are brought on-chip.
The following examples demonstrate how the DMA can be used to relocate and reorganize data.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
31 16 15 0
FRAME COUNT ELEMENT COUNT
R/W-0 R/W-0
Legend: R/W = Read/Write
0x02FFFFF8 0x3FF
0x02FFFFFC 0x400
• The number of elements transferred in the entire block is ((F – 1) x Er) + Ei, where:
– F = Initial value of the frame count
– Ei = Initial value of the element count
– Er = Element count reload value
If the numbers of elements to be transferred is constant for a given application, suitable values
can be used explicitly in a program. For a majority of transfer lengths, many count and reload
values provide the same performance.
If the block length is not a fixed amount, but is established during run-time, an algorithm to
determine the count and reload values during execution is a more convenient solution.
Using the above information, a simple formula can be created to calculate F, Ei, and Er from a
given block size. One possible formula is as follows:
• Ei = 15 LSBs (least-significant bits) of total element count. Fix to 0x8000 if 15 LSBs are all 0.
• Er = 0x8000 (fixed)
• F = Total element count divided by Er, plus 1. Do not add 1 if Ei is forced to 0x8000.
The following C code performs the above calculations:
F =(XFER_SIZE >> 15)+1;
Ei = XFER_SIZE & 0x7FFF;
if (!Ei){
Ei = 0x8000;
F –= 1;
}
Er = 0x8000;
For this set of equations, the maximum transfer size is 0x7FFF7FFF (2.15 GB).
For this example, assume that the entire memory space CE2 (16 MB) is to be transferred to an
off-chip peripheral located at 0x00400000 (CE0). This transfer is 0x00400000 32-bit words. For
this, the following values must be assigned to the DMA registers:1
Primary control register = 0x00000010
1 The sample formulas were used to determine the transfer counter and global count reload A values. If different
formulas are used to obtain the count values, those numbers may be different.
The primary control register for channel 0 (see Figure 2) should be configured as follows:
The setting of 01b in the SRC DIR bit field would cause the DMA channel to increment the
source address by one element size (4 bytes in this example) following each element. Since the
destination is a fixed address, set DST DIR to 00b. See Figure 2.
To initiate the transfer, write a value of 01b to the START bit field.
Many applications require the use of multiple data arrays. It is often desirable to have the arrays
arranged so that the first elements of each array are adjacent, the second elements are
adjacent, and so on. Often, this is not the format in which the data is presented to the device.
Either data is transferred via a peripheral, with the data arrays arriving one after the other, or the
arrays are located in memory, with each array occupying a portion (frame) of contiguous
memory spaces. For these instances, the DMA can be configured to reorganize the data into the
desired format. Figure 5 shows the data sorting of element arrays.
0x80000000 A1 B1 C1 D1
0x80000008 A2 B2 C2 D2
0x80000010 A3 B3 C3 D3
The following formulas can be used to set up a DMA channel to organize the data in memory by
ordinal position:
• FRAME INDEX should be set to –(((E – 1) x F) – 1) x S
• ELEMENT INDEX should be set to F x S, where
– F = initial value of frame count
– E = initial value of element count, as well as the element count reload value
– S = element size in bytes
This example focuses on the second case mentioned above, in which equally sized data arrays
are located in external memory. For this transfer to give the desired results, it is necessary that
the arrays be the same size and reside in contiguous memory.
For this example, it is assumed that the 16-bit data is located in external RAM beginning at
address 0x02000000 (CE2). The DMA channel is configured to bring four frames of 1k
half-words from their locations in RAM to internal data memory beginning at 0x80000000.2 The
index values are:
• FRAME INDEX = –(((1024 – 1) x 4) – 1) x 2 = 0xE00A
• ELEMENT INDEX should be set to 4 x 2 = 8
For this, the following values must be assigned to the DMA channel’s control registers:
Primary control register = 0x000001D0
The setting of 01b in the SRC DIR bit field causes the DMA channel to increment source
address by one element size (2 bytes in this example) following each element. Set DST DIR to
11b, to modify the destination address, according to global index register A (INDEX = 0).
ELEMENT INDEX (value set to 0x0008) is used following each element within each frame, to
increment the destination address by 8 bytes (4 elements). FRAME INDEX (value set to
0xE00A) is used following the last element of each frame, to set the destination address to the
first element of the subsequent frame.
To initiate the transfer, a value of 01b must be written to the START bit field.
4 Servicing a Peripheral
In many applications, a DMA channel services a peripheral sending data to, and receiving data
from, the device. The peripheral is often one of the following:
• Coder-decoder (Codec)
• AFE
• Analog interface chip (AIC)
• Analog-to-digital (A/D) converter
• Digital-to-analog (D/A) converter
These devices send samples to/from the C6000 through the McBSP or the EMIF. If the DMA is
to effectively communicate with the peripheral, it must be configured to perform a synchronized
data transfer. It must write only when the peripheral is able to accept new data, and read only
when the peripheral has new data available.
• Frame synchronization – Each frame transfer waits for the selected event to occur before
proceeding.
Each DMA channel can be configured for read synchronization, write synchronization, both read
and write synchronization, or frame synchronization. If frame synchronization is used, the
read-synchronization event triggers the transfer of an entire frame. The event to which the
transfer is synchronized is set in the DMA channel’s primary control register. Table 1 gives a
complete list of DMA synchronization events.
The transmit-and-receive events to the DMA from each McBSP are XEVT and REVT,
respectively. XEVT is issued when a value has been copied from the data transmit register
(DXR) to the transmit shift register (XSR), signifying that the most recent data has been
transferred out. REVT is issued when a value has been copied from the receive buffer register
(RBR) to the data receive register (DRR), indicating that a new data value has been received.
An external peripheral on the EMIF typically has similar synchronization events arriving through
one or more of the external interrupt pins (EXT_INT[7–4]).
In addition to properly synchronizing the peripherals, you must ensure that the data is
transferred to and from the correct location. This becomes an issue when performing transfers
for 8- and 16-bit elements, particularly when operating in an endian mode that is different than
the peripheral expects. (See section 4 for more details.)
11
SPRA529A
REVT0
0x80000FF8 0x3FF
REVT0
0x80000FFC 0x400
To initialize this transfer, set the four control registers to the following values:
Primary control register = 0x00034040
12
SPRA529A
A McBSP or AFE is more commonly used for bidirectional communication with the device, which
means that the DMA needs to both read and write to the peripheral. Adding to the previous
example (see section 4.1), consider that, at the same time, 1k words are received from the
McBSP, and 1k words are transmitted to it as well. To facilitate this, a channel must be set up to
transfer data from internal memory to McBSP0 DXR. This channel must be write-synchronized
on the event , XEVT0.
Although this could easily be done with a second DMA channel, one of the features of the DMA
is that a single channel can be used to service both the input and output data streams of a
peripheral for which the transmit- and receive-data addresses are fixed. Using this feature, the
synchronized data transfer example, described in the previous section, could be modified so that
a single DMA channel is used to perform both reads from, and writes to, the McBSP. A diagram
of a split-mode transfer is shown in Figure 8.
REVT0 XEVT0
0x80000000 In1 0x80001000 Out1
REVT0 XEVT0
0x80000004 In2 0x80001004 Out2
REVT0 XEVT0
0x80000008 In3 0x80001008 Out3
REVT0 XEVT0
0x8000000C In4 0x8000100C Out4
REVT0 XEVT0
0x80000FF8 In0x3FF 0x80001FF8 Out0x3FF
REVT0 XEVT0
0x80000FFC In0x400 0x80001FFC Out0x400
Setting the SPLIT bit field in the DMA channel primary control register enables a split-mode
transfer and selects the location of the split address. Possible SPLIT values are listed in Table 2.
Global address registers A, B, and C can be used to hold the split address. This address is
assumed to be on an even word boundary, as the three LSBs are reserved and fixed at zero.
This address is used as the split source address. The split destination address is automatically
set to be one word address greater than the split source address. If an external peripheral is to
be serviced by a DMA channel in split-mode, this addressing convention must be followed.
13
SPRA529A
In this example, a block of 1k 32-bit words is transferred to McBSP0, and a block of 1k 32-bit
words is transferred from McBSP0 to memory using the same DMA channel.4 The 1k data block
to be transferred to the McBSP begins at address 0x80001000, while the input data block is again
written to 0x80000000. For this, the following values must be assigned to the DMA registers:
Primary control register = 0x00634450
14
SPRA529A
Consider a modification of the split-mode transfer example with an external AFE as the
peripheral (see section 4.2). If the elements arrive and depart through the AFE at a rate that
does not seriously limit the bandwidth of the EMIF, the only modification to the previous setup is
to replace the global address register A value with the AFE Data-In address.6
If, however, servicing transmit and receive elements individually prevent the EMIF from allowing
further accesses (either by the CPU or another DMA channel), the bursting method can be used.
When performing frame synchronized transfers, two DMA channels must be used, as split-mode
transfers do not allow bursting.
For this example system, assume there is an input FIFO and an output FIFO, each capable of
holding 1k 32-bit elements (one frame size). An external interrupt (EXT_INT4) selects when the
frame of data is ready to be read from the input FIFO. The output FIFO is written to as soon as
the input frame is completed. In this fashion, the input and output transfer rates are identical.7
Figure 9 shows the transfers to and from external FIFOs.
0x00400000 In[1–0x400] 0x00400004 Out[1–0x400]
EXT_INT4 DMA_INTn
0x80000000 In1 0x80001000 Out1
0x80000004 In2 0x80001004 Out2
0x80000008 In3 0x80001008 Out3
0x8000000C In4 0x8000100C Out4
The AFE is mapped into CE0 space (Map 1), with the address of the input FIFO at 0x00400000,
and the address of the output FIFO at 0x00400004.
For the channel servicing the input data, the following values must be assigned to the DMA
registers:
Primary control register = 0x06010040
6 This assumes that the Data Out address is one word size above the Data In address.
7 The input data transfer and the output data transfer can both have external synchronization as well.
15
SPRA529A
23 22 21 20 19 18 17 16
Reserved WSPOL RSPOL FSIG DMAC
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
15 14 13 12 11 10 9 8
WYSYNC WYSYNC RSYNC CLR RSYNC WDROP WDROP RDROP RDROP
CLR STAT STAT IE COND IE COND
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
7 6 5 4 3 2 1 0
BLOCK BLOCK LAST LAST FRAME FRAMD SX SX
IE COND IE COND IE COND IE COND
R/W-1 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
Legend: R/W = Read/Write
16
SPRA529A
The settings of 01b in the DST DIR bit field cause the DMA channel to increment the destination
address by one element size (4 bytes in this example) following each element. Since this is a
frame-synchronized transfer (FS = 1), the entire frame of elements from the source address are
read from the AFE as soon as the read synchronization event (RSYNC = EXT_INT4) is
received. Setting TCINT to 1 causes the DMA channel to generate an interrupt that occurs at the
end of a frame (FRAME IE = 1). This interrupt initiates the transfer to the output FIFO by another
DMA channel.
For the DMA channel servicing the output data, the following values must be assigned to the
DMA registers:
Primary control register = 0x0402X0108
The settings of 01b in the SRC DIR bit field causes the DMA channel to increment the source
address by one element size (4 bytes in this example) following each element. Since this is a
frame synchronized transfer (FS = 1), the entire frame of elements from the source address is
written to the AFE as soon as the read synchronization event (RSYNC = DMA_INTn) is
received.
To initiate the two transfers, write a value of 01b to the START bit field of each channel’s primary
control register.
8 The value of X is equal to 4*n, where n is the DMA channel number servicing the input data. See note 9.
9 The value of RSYNC for this channel depends on the channel servicing the input transfer, where n equals the
DMA channel number.
17
SPRA529A
31 0
Little Endian Byte 3 Byte 2 Byte 1 Byte 0
Big Endian Byte 0 Byte 1 Byte 2 Byte 3
MS MS MS LS
31 0
Little Endian Byte 3 Byte 2 Byte 1 Byte 0
Big Endian Byte 0 Byte 1 Byte 2 Byte 3
MS MS MS LS
When in little-endian mode, the rightmost data location is the base address of the DXR, so no
matter what the element size, a write to the DXR base address properly aligns the element;
however, this is the upper portion of the register in big-endian mode. Depending on the size of
the element, the write must be made to the address of either Byte 0 (32-bit), Byte 2 (16-bit), or to
Byte 3 (8-bit). It is not possible to left-justify outgoing data.
The DRR is configurable to either right- or left-justify the incoming data. The justification
determines the source address of the data element. For right-justified data (default), the source
address is always Byte 0 in little-endian mode. It is in Byte 0 (32-bit), Byte 2 (16-bit), or Byte 3
(8-bit) in big-endian mode. For left-justified data, the reverse is true.
10 The MSB should be either bit 31, 15, or 7 only. If a peripheral that is not 32, 16, or 8 bits wide is used,
the upper data bits should be unconnected.
18
SPRA529A
Table 3 shows the possible endian mode, element size, and DRR justification combinations that
can be encountered in a system. Only the source and destination addresses are given for each.
All of the necessary configurations described previously still apply.
Table 3. Possible DMA Source and Destination Address for Servicing McBSP011,12,13
Endian Destination
Element Size Mode DRR Justification Source Address Address
8 bits Little Right 0x018C0000 0x018C0004
Left 0x018C0003 0x018C0004
Big Right 0x018C0003 0x018C0007
Left 0x018C0000 0x018C0007
12 bits Little Right 0x018C0000 0x018C0004
16 bits
11 Note that the source addresses and destination addresses are identical for both the big- and little-endian
modes when transferring 32-bit elements.
12 12-bit data should be accessed as a 16-bit element.
13 20- and 24-bit data should be accessed as 32-bit elements.
19
SPRA529A
EXT_INT4 DMA_INTn
DMA_INTn
20
SPRA529A
14 Note that the FRAME COND bit must be manually cleared following each frame transfer by this channel.
See section 6 for information on how to do this.
15 The value of X is equal to 4*n, where n is the DMA channel number servicing the input data. See note 16.
21
SPRA529A
22
SPRA529A
EXT_INT4 INTn
Consider a variation of the previous transfer, in which there are two 1k-word-input buffers and
two 1k-word output buffers in data memory. The DMA transfers 1k block of 32-bit words to one
input buffer, located at 0x80000000, and a 1k block of 32-bit words from one output buffer,
located at 0x80001000. After these sets of data are transferred, a new block is transferred to a
second input buffer at 0x80008000, and a new block is transferred from a second output buffer
at 0x80009000. The next pair of transfers returns to the original input/output pair. The CPU
computes data located in the first input buffer, and stores the results in the first output buffer,
following the first DMA transfer.
Once completed, the CPU uses the second input buffer, storing the results in the second output
buffer. The CPU then switches back to the first pair and continues. The control registers from
the previous example are modified such that the source and destination addresses are reloaded
to their original values following each block (two frames) of data transferred.
For the DMA channel that services the input data, the primary control register value must be
modified to allow the channel to post-increment the destination address. Global address register
B is used to return the destination address to the beginning of the first buffer. The control
registers for this channel should be:
23
SPRA529A
18 Note that the FRAME COND bit must be manually cleared following each frame transfer by this channel.
See section 6 for information on how to do this.
24
SPRA529A
19 The value of X is equal to 4*n, where n is the DMA channel number servicing the input data. See note 20.
20 The value of RSYNC for this channel depends on the channel servicing the input transfer, where n equals the
DMA channel number.
21 An example interrupt service routine that does this, and clears the FRAME COND bit, is given in section 6.
25
SPRA529A
22 For information on how to create program sections and organize them in memory, see the TMS320C6000
Assembly Language Tools User’s Guide (SPRU186) and the TMS320C6000 Optimizing C Compiler User’s
Guide (SPRU187).
23 The location of the Interrupt Vector Table should depend on the frequency of interrupts that need to be
serviced. If interrupts are frequent, it is more efficient for the IST to be in internal program memory.
26
SPRA529A
• Page 2 section linked to 0x20004000, with run-time location set to 0x0000A000. This page
of code is transferred into internal program memory multiple times throughout the program
execution.
• Page 3 section linked to 0x20008000, with run-time location set to 0x00006000. This page of
code is transferred into internal program memory multiple times throughout the program
execution.
• Page 4 section linked to 0x2000C000, with run-time location set to 0x0000A000. This page
of code is brought into internal program memory multiple times throughout the program
execution.
Each page (1–4) listed above is of length 16k (0x4000), and each page branches to the next
sequentially. To facilitate this, a DMA channel should be set up by the initialization code to
transfer pages 1 through 4 to their run-time program space. Figure 15 shows a block diagram of
this four-page system.
DMA_INTn
Program paging is typically a background transfer, as it is not desirable to interfere with the
servicing of peripherals or other data transfers. Paging is normally done using a low-priority
channel.
27
SPRA529A
The setting of 01b in the DST DIR and SRC DIR bit fields causes the DMA channel to increment
the destination and source addresses following each element. Since this is a
frame-synchronized transfer (FS = 1), an entire page is transferred to program memory as soon
as the read-synchronization event (RSYNC = EXT_INT6) is received. Setting TCINT to 1 causes
the DMA channel to generate an interrupt that occurs at the end of a block (BLOCK_IE = 1).
This interrupt is used to let the CPU know that valid code is present.
28
SPRA529A
Following each block, global reload registers should be set with the destination and source
addresses for the subsequent transfer. External interrupt EXT_INT6 should not actually be used
during program execution. Instead, the CPU should directly set the RSYNC STAT bit in the
channel’s secondary control register to initiate each transfer. This provides control between the
CPU and the DMA. Each time the CPU finishes executing a page, it should set the RSYNC
STAT bit, then poll the interrupt flag for the interrupt number of the DMA channel. If it is known
that the CPU completes before the DMA every time, the CPU can be placed in IDLE to decrease
the transfer time.
FRAME Frame complete After the last write transfer in each frame is written to memory.
LAST Last frame After all counter adjustments for the next-to-last frame in a block
transfer complete.
WDROP Dropped read/write If a subsequent synchronization event occurs before the last one is
RDROP synchronization cleared.
SX Split transmit overrun receive If the split-mode is enabled, and transmit-element transfers get seven
or more element transfers ahead of receive-element transfers.
The IE bits in the channel’s secondary control register must be set for each condition to
generate an interrupt to the CPU. The TCINT bit in the channel’s primary control register must
also be set. This causes an interrupt to occur whenever the enabled condition transitions from a
0 to a 1, which is reported in the COND bit fields of the channel’s secondary control register.
If the IE bit for a condition is enabled, the CPU must manually clear the COND bit to receive
subsequent interrupts. This feature avoids confusion in the case that multiple events trigger the
same interrupt. The most common way to perform this is to have an interrupt service routine
(ISR) that services each DMA channel in use.24 ISRs range in function from simplistic to
complex, depending on the application. They are typically designed to be as short as possible so
that little time is taken away from the processor.
24 For information on how to set up CPU interrupts, see the TMS320C6000 Peripherals Reference Guide
(SPRU190) and the TMS320C6000 CPU and Instruction Set Reference Guide (SPRU189).
29
SPRA529A
To enable a DMA-generated interrupt to be taken, several steps must be taken by the CPU. The
global interrupt enable (GIE) bit must be set in the control status register (CSR) and the
appropriate interrupt number’s interrupt enable (IEn) bit and the non-maskable interrupt enable
(NMIE) bit must be set in the IER. The setting of NMIE is to prevent the processor from being
interrupted until it is fully out of the system initialization following reset, and no interrupts can be
taken until this is done. The GIE bit globally enables any enabled interrupt to be serviced by the
CPU. This bit can be cleared to protect certain routines. The IEn bit is used to enable the
specific interrupt number of the DMA channel in use.
The most common DMA conditions used to interrupt the CPU are the BLOCK, FRAME, and
LAST conditions.
• BLOCK is signaled after the last element of the last frame is transferred. This is typically
used to signal that a transfer is complete for non-auto-initialized transfers or to cause an ISR
that modifies the global registers used by the channel. The new reloads would be used at
the end of the next block.
• FRAME is signaled after the last element of any frame is transferred. This is typically used to
synchronize other channels or signal to the CPU that a set of data is available to be
processed.
• LAST is signaled after the last element of the second-to-last frame is transferred. This is
typically used to modify the count reload of an auto-initialized transfer. The new count would
take effect on the first frame of the subsequent block.
These are for planned services that occur during program execution. The remaining conditions
are used to service unplanned situations. (R/W)DROP is used in the instance that a
synchronized transfer was skipped, and the SX condition is used in the case that a split-mode
transfer is not symmetric. An ISR for a DMA channel can address any number of these
conditions.
A typical sequence of events in servicing a DMA interrupt is:
• Read the secondary control register.
• Check COND bits to see which condition generated the interrupt.
• Clear the condition(s) by writing 0 to the COND bits.
• Write the secondary control register.25
• Perform necessary tasks to service the condition.
• Resume program execution.
An example of a basic ISR is one that can be used in the ping-pong transfer example (see
section 5.2). In that example, it is desired to initiate the second DMA channel (servicing the output
data) after the second input frame is completed. The FRAME COND bit is also required to be
cleared following each frame as the FRAME IE bit is set. The following C code performs what is
necessary for the case where DMA channel 1 services the input data, and DMA channel 2
services the output data:
25 In a synchronized transfer, it is a good idea to mask the RSYNC STAT and WSYNC STAT bits. If a
synchronization event is serviced during the ISR, writing a 1 to either may cause a spurious synchronization
event. Writing a 0 has no effect.
30
SPRA529A
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA Channel 1 Interrupt Service Routine will execute upon */
/* completion of a frame Transfer by Channel 1. Since Channel 1 */
/* is servicing the input data, when it completes its transfer, */
/* the CPU will be free to begin executing code. */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
/* If second frame has completed, start DMA Channel 2 in */
/* autoinitialization mode, then clear the Block condition */
/* bit and disable Block Interrupt Enable. */
if (DMA_FGET(SECCTL1, BLOCKCOND))
{
DMA_autoStart(hDma2);
DMA_FSET(SECCTL1, BLOCKCOND, 0);
DMA_FSET(SECCTL1, BLOCKIE, 0);
}
7 Conclusion
The TMS320C6000 DMA is a versatile tool that can be used to perform data transfers
throughout device operation with little setup required. Through proper initialization, both simple
and complex data transfers can be run concurrently to provide data to the CPU, and to transmit
data to external devices. The examples provided here offer some of the more common DMA
applications for a system with setups shown to service peripherals, arrange incoming data
streams into useful data, and operate continuously. Knowing how to tie DMA operation into a
system allows designers to maximize data throughput and CPU performance.
8 References
1. TMS320C6000 Peripherals Reference Guide (SPRU190).
2. TMS320C6000 Assembly Language Tools User’s Guide (SPRU186).
3. TMS320C6000 Optimizing C Compiler User’s Guide (SPRU187).
4. TMS320C6000 CPU and Instruction Set Reference Guide (SPRU189).
5. TMS320C6000 Chip Support Library API Reference Guide (SPRU401).
31
SPRA529A
blocktrans_dma.c:
Set up the DMA registers to perform data transfer of a block of data.
This sample code moves a block of data in the DSP internal memory from
one location (dmaOutbuff) to another location (dmaInbuff). These memory
locations are not predefined, but are dynamically allocated by the
program, solely for example purposes (the user can define the memory
space to be allocated if needed). This program uses interrupt 9 to stop
the data transfer process when the transfer is complete by setting a
flag to the CPU (the user can choose any DMA channel and corrsponding
INT associated with it)
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip
Support Library API User’s Guide (SPRU401) for further information.
*/
/* Include files */
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_TRANS 8
#define XFER_TYPE DMA_TRANS
#define BUFFER_SIZE 256 /* BUFFER_SIZE should be >= ELEMENT_COUNT */
#define ELEMENT_COUNT 32
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Declare CSL objects */
DMA_Handle hDma1; /* Handle for DMA */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* External functions and function prototypes */
void set_interrupts_dma(void);
/* Include the vector table to call the IRQ ISRs hookup */
extern far void vectors();
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* main() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void main(void)
{
element_count = ELEMENT_COUNT;
xfer_type = XFER_TYPE;
switch (xfer_type) {
case DMA_TRANS:
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA channels 1 config structure */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA channel 1 */
hDma1 = DMA_open(DMA_CHA1, DMA_OPEN_RESET); /* Handle to DMA ch1 */
DMA_configArgs(hDma1,
DMA_PRICTL_RMK(
DMA_PRICTL_DSTRLD_DEFAULT,
DMA_PRICTL_SRCRLD_DEFAULT,
DMA_PRICTL_EMOD_DEFAULT,
DMA_PRICTL_FS_DEFAULT,
DMA_PRICTL_TCINT_ENABLE, /* TCINT =1 */
DMA_PRICTL_PRI_DMA, /* DMA high priority */
DMA_PRICTL_WSYNC_DEFAULT,
DMA_PRICTL_RSYNC_DEFAULT,
DMA_PRICTL_INDEX_DEFAULT,
DMA_PRICTL_CNTRLD_DEFAULT,
DMA_PRICTL_SPLIT_DISABLE,
DMA_PRICTL_ESIZE_32BIT, /* Element size is 32 bits */
DMA_PRICTL_DSTDIR_INC, /* Increment dest by element size */
DMA_PRICTL_SRCDIR_INC, /* Increment src by element size */
DMA_PRICTL_START_DEFAULT
),
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202/6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202/6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202/6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_ENABLE, // BLOCK IE=1 enables DMA channel int
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_DEFAULT,
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
DMA_SRC_RMK((Uint32)dmaOutbuff), /* source buffer */
DMA_DST_RMK((Uint32)dmaInbuff), /* destination buffer */
DMA_XFRCNT_RMK(
DMA_XFRCNT_FRMCNT_DEFAULT,
DMA_XFRCNT_ELECNT_OF(element_count) /* set xfer element count */
)
);
/* initialize the interrupts: */
/* Enable the interrupts after the DMA channels are opened */
/* as the DMA_OPEN_RESET clears and disables the channel */
/* interrupt when specified and clears the corresponding */
/* interrupt bits in the IER. */
set_interrupts_dma();
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT9 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT1);
return;
}
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISRs */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
transfer_done = TRUE;
return;
}
/*–––––––––––––––––––––––End of blocktrans_dma.c–––––––––––––––––––––––––––––––*/
largeblocktrans_dma.c:
Setup the DMA control registers to perform a large block data transfer.
This sample code moves a block of data from an external memory/space/buffer
(AFEbuff) to the internal DSP data memory (dmaInbuff). The user can define
the external memory space to transfer data from as required in a specific
application, for instance CE0 EMIF space. This program uses interrupt 9 to
stop the data transfer process when the transfer is complete by setting a
flag to the CPU (the user can choose any DMA channel and corrsponding INT
associated with it)
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip Support
Library API User’s Guide (SPRU401) for further information.
*/
/* Chip definition, change this accordingly, only DMA supporting DSPs though */
#define CHIP_6202 1
/* Include files */
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_TRANS 8
#define XFER_TYPE DMA_TRANS
#define BUFFER_SIZE 0x8000 /* BUFFER_SIZE contains 65535 memeory locs. */
#define ELEMENT_COUNT 0xFFFFFF /* Element count greater than 65535 elements */
/* change the element count accordingly */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* main() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void main(void)
{
/* Establish initial count value, and reload value, based on transfer size */
/* ELEMENT_COUNT) of large block. The formula used to calculate the initial */
/* and reload is the following: */
/* */
/* Initial element count = 15 LSBs of total transfer size */
/* Frame count = bits 15 through 30, plus 1 */
/* */
/* NOTE: The maximum size using this method is 0x7FFF7FFF. For larger sizes, */
/* a new formula must be used. */
element_count = ELEMENT_COUNT;
xfer_type = XFER_TYPE;
frame_count = (element_count >> 15 ) + 1;
initial_element = element_count & 0x7FFF;
switch (xfer_type) {
case DMA_TRANS:
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT9 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT1);
return;
}
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISRs */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
transfer_done = TRUE;
return;
}
/*–––––––––––––––––––––––End of largeblocktrans_dma.c––––––––––––––––––––––––––*/
datasort_dma.c:
This sample code sets up the DMA control registers to perform column-wise
sort of data arrays located in internal memory, from dmaOutbuff to dmaInbuff
DSP internal memory. These memory arrays are not predefined by the user but
are dynamically allocated by the program, solely for excample purposes (the
user can define the memory space to be allocated if needed). This program
uses interrupt 9 to stop the data transfer process when the transfer is
complete by setting a flag to the CPU (the user can choose any DMA channel
and corrsponding INT associated with it)
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip Support
Library API User’s Guide (SPRU401) for further information.
*/
#define DMA_TRANS 8
#define XFER_TYPE DMA_TRANS // Let BUFFER SIZE be greater or equal in size to:
#define BUFFER_SIZE 16 // >= (ELEMENT_COUNT * FRAME_COUNT) * (ELEMENT_SIZE/4)
#define ELEMENT_SIZE 1 // ELEMENT_SIZE is the number of bytes/element, 1,2,4
#define FRAME_COUNT 2 // Define the number of frames
#define ELEMENT_COUNT 8 // Define the number of elements to transfer
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* main() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void main(void)
{
/* Calculate the index values, as well as the ESIZE, based on the number of */
/* elements per frame (element_count), the number of frames per block */
/* (frame_count), and the number of bytes in each element (element_size) */
/* covert the number of bytes/element into the CSL HAL MACRO conversion */
if (ELEMENT_SIZE == 1) element_size = 2; /* 8BIT element size */
else if (ELEMENT_SIZE == 2) element_size = 1; /* 16BIT element size */
else element_size = 0; /* 32BIT element size */
switch (xfer_type) {
case DMA_TRANS:
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA channel 1 config structure */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
dmaGblRegMsk = DMA_globalAlloc(dmaGblRegId);
DMA_globalConfigArgs(dmaGblRegMsk,
DMA_GBLADDR_GBLADDR_DEFAULT, /* DMA global address registers A to D */
DMA_GBLADDR_GBLADDR_DEFAULT,
DMA_GBLADDR_GBLADDR_DEFAULT,
DMA_GBLADDR_GBLADDR_DEFAULT,
DMA_PRICTL_SRCDIR_INC,
DMA_PRICTL_START_DEFAULT
),
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT9 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT1);
return;
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISR */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
transfer_done = TRUE;
return;
}
/*–––––––––––––––––––––––End of datasort_dma.c–––––––––––––––––––––––––––––––*/
synctrans_dma.c:
This program sets up the DMA control registers to perform data transfer from
the McBSP0 of a TMS320C6000 device to the DSP internal data memory (dmaInbuff)
using DMA channel 1. This program uses interrupt 9 to stop the
data transfer process when the transfer is complete by setting a flag to the
CPU (the user can choose any DMA channel and corrsponding INT associated with
it). Also note that the McBSP can be configured to match the requirements of
a specific application.
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip Support
Library API User’s Guide (SPRU401) for further information. */
#define CHIP_6202 1
/* Include files */
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
#include <csl_mcbsp.h> /* MCBSP_SUPPORT */
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_XFER 8
#define XFER_TYPE DMA_XFER
#define BUFFER_SIZE 256
#define ELEMENT_COUNT 32
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* External functions and function prototypes */
void init_mcbsp0_dma(void); /* Function prototypes */
void set_interrupts_dma(void);
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* main() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void main(void)
{
/* Declaration of local variables */
static int element_count, xfer_type;
element_count = ELEMENT_COUNT;
xfer_type = XFER_TYPE;
init_mcbsp0_dma();
switch (xfer_type) {
case DMA_XFER:
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_ENABLE, //BLOCK IE=1 enables DMA channel int
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_DEFAULT,
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
DMA_XFRCNT_RMK(
DMA_XFRCNT_FRMCNT_DEFAULT,
DMA_XFRCNT_ELECNT_OF(element_count) /* set recv element count */
)
);
/* Initialize the interrupt(s) */
/* Enable the interrupt after the DMA channels are opened as */
/* the DMA_OPEN_RESET clears and disables the channel interrupt */
/* once specified and clears the corresponding interrupt bits */
/* in the IER. */
set_interrupts_dma();
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* init_mcbsp0_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* MCBSP Config structure */
/* Setup the MCBSP_0 for data receive */
void
init_mcbsp0_dma(void)
{
MCBSP_Config mcbspCfg0 = {
MCBSP_SPCR_RMK(
MCBSP_SPCR_FRST_DEFAULT, //All fields in SPCR set to default values
MCBSP_SPCR_GRST_DEFAULT,
MCBSP_SPCR_XINTM_DEFAULT,
MCBSP_SPCR_XSYNCERR_DEFAULT,
MCBSP_SPCR_XRST_DEFAULT,
MCBSP_SPCR_DLB_DEFAULT,
MCBSP_SPCR_RJUST_DEFAULT,
MCBSP_SPCR_CLKSTP_DEFAULT,
MCBSP_SPCR_RINTM_DEFAULT,
MCBSP_SPCR_RSYNCERR_DEFAULT,
MCBSP_SPCR_RRST_DEFAULT
),
MCBSP_RCR_RMK(
MCBSP_RCR_RPHASE_SINGLE, /* Single phase receive frame */
MCBSP_RCR_RFRLEN2_DEFAULT,
MCBSP_RCR_RWDLEN2_DEFAULT,
MCBSP_RCR_RCOMPAND_DEFAULT,
MCBSP_RCR_RFIG_DEFAULT,
MCBSP_RCR_RDATDLY_1BIT, /* 1-bit receive data delay */
MCBSP_RCR_RFRLEN1_DEFAULT,
MCBSP_RCR_RWDLEN1_DEFAULT
),
MCBSP_XCR_RMK(
MCBSP_XCR_XPHASE_DEFAULT, // All fields in XCR set to default values
MCBSP_XCR_XFRLEN2_DEFAULT,
MCBSP_XCR_XWDLEN2_DEFAULT,
MCBSP_XCR_XCOMPAND_DEFAULT,
MCBSP_XCR_XFIG_DEFAULT,
MCBSP_XCR_XDATDLY_DEFAULT,
MCBSP_XCR_XFRLEN1_DEFAULT,
MCBSP_XCR_XWDLEN1_DEFAULT
),
MCBSP_SRGR_RMK(
MCBSP_SRGR_GSYNC_DEFAULT, //All fields in SRGR set to default values
MCBSP_SRGR_CLKSP_DEFAULT,
MCBSP_SRGR_CLKSM_DEFAULT,
MCBSP_SRGR_FSGM_DEFAULT,
MCBSP_SRGR_FPER_DEFAULT,
MCBSP_SRGR_FWID_DEFAULT,
MCBSP_SRGR_CLKGDV_DEFAULT
),
MCBSP_MCR_RMK(
MCBSP_MCR_XPBBLK_DEFAULT, // All fields in MCR set to default values
MCBSP_MCR_XPABLK_DEFAULT,
MCBSP_MCR_XMCM_DEFAULT,
MCBSP_MCR_RPBBLK_DEFAULT,
MCBSP_MCR_RPABLK_DEFAULT,
MCBSP_MCR_RMCM_DEFAULT
),
MCBSP_RCER_RMK(
MCBSP_RCER_RCEB_DEFAULT, // All fields in RCER set to default values
MCBSP_RCER_RCEA_DEFAULT
),
MCBSP_XCER_RMK(
MCBSP_XCER_XCEB_DEFAULT, // All fields in XCER set to default values
MCBSP_XCER_XCEA_DEFAULT
),
MCBSP_PCR_RMK(
MCBSP_PCR_XIOEN_DEFAULT,
MCBSP_PCR_RIOEN_DEFAULT,
MCBSP_PCR_FSXM_DEFAULT,
MCBSP_PCR_FSRM_DEFAULT,
MCBSP_PCR_CLKXM_DEFAULT,
MCBSP_PCR_CLKRM_DEFAULT,
MCBSP_PCR_CLKSSTAT_DEFAULT,
MCBSP_PCR_DXSTAT_DEFAULT,
MCBSP_PCR_FSXP_DEFAULT,
MCBSP_PCR_FSRP_DEFAULT,
MCBSP_PCR_CLKXP_DEFAULT,
MCBSP_PCR_CLKRP_DEFAULT
)
};
hMcbsp0 = MCBSP_open(MCBSP_DEV0, MCBSP_OPEN_RESET); /* McBSP port 0 */
MCBSP_config(hMcbsp0, &mcbspCfg0);
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT09 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT1);
return;
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISR */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
transfer_done = TRUE;
return;
}
/*–––––––––––––––––––––––End of synctrans_dma.c––––––––––––––––––––––––––––––*/
splitmode_dma.c:
This program sets up the DMA control registers to service the McBSP0 of a
TMS320C6000 device in the data rcev/xmit split mode. Data is transferred
to/from the internal DSP data memory (dmaInbuff stores data in the DSP
internal memory and dmaOutbuff loads data from the DSP internal memory to
external memory) to an external memory/buffer via the McBSP. Although this
transfer can easily be done using a second DMA channel, one channel to handle
data transmit and one to handle data receive, one of the features of the DMA
controller is that a single DMA channel can be used to service both the input
and output data streams of a peripheral for which the transmit and receive
addresses are fixed. In this sample code DMA channel 1 is hooked up to
interrupt 09 (this is a DMA-INT default mapping). Also note that the McBSP
can be configured to match the requirements of a specific application.
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip
Support Library API User’s Guide (SPRU401) for further information. Note that
any DMA channel with the corresponding interrupt and any McBSP port (0 or 1)
can be used for this data transfer.
*/
/* Include files */
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
#include <csl_mcbsp.h> /* MCBSP_SUPPORT */
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_XFER 8
#define XFER_TYPE DMA_XFER
#define BUFFER_SIZE 256 /* set same value as xmit */
#define ELEMENT_COUNT 32 /* set element_count =< buffer_size, set same value as
xmit*/
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* main() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void main(void)
{
/* Declaration of local variables */
static int element_count, xfer_type;
element_count = ELEMENT_COUNT;
xfer_type = XFER_TYPE;
init_mcbsp0_dma();
switch (xfer_type) {
case DMA_XFER:
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_ENABLE, // BLOCK IE=1 enables DMA channel int
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_DEFAULT,
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* init_mcbsp0_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* MCBSP Config structure */
/* Setup the MCBSP_0 for data receive */
void
init_mcbsp0_dma(void)
{
MCBSP_Config mcbspCfg0 = {
MCBSP_SPCR_RMK(
MCBSP_SPCR_FRST_DEFAULT, // All fields in SPCR set to default values
MCBSP_SPCR_GRST_DEFAULT,
MCBSP_SPCR_XINTM_DEFAULT,
MCBSP_SPCR_XSYNCERR_DEFAULT,
MCBSP_SPCR_XRST_DEFAULT,
MCBSP_SPCR_DLB_DEFAULT,
MCBSP_SPCR_RJUST_DEFAULT,
MCBSP_SPCR_CLKSTP_DEFAULT,
MCBSP_SPCR_RINTM_DEFAULT,
MCBSP_SPCR_RSYNCERR_DEFAULT,
MCBSP_SPCR_RRST_DEFAULT
),
MCBSP_RCR_RMK(
MCBSP_RCR_RPHASE_SINGLE, /* Single phase receive frame */
MCBSP_RCR_RFRLEN2_DEFAULT,
MCBSP_RCR_RWDLEN2_DEFAULT,
MCBSP_RCR_RCOMPAND_DEFAULT,
MCBSP_RCR_RFIG_DEFAULT,
MCBSP_RCR_RDATDLY_1BIT, /* 1-bit receive data delay */
MCBSP_RCR_RFRLEN1_DEFAULT,
MCBSP_RCR_RWDLEN1_DEFAULT
),
MCBSP_XCR_RMK(
MCBSP_XCR_XPHASE_DEFAULT, // All fields in XCR set to default values
MCBSP_XCR_XFRLEN2_DEFAULT,
MCBSP_XCR_XWDLEN2_DEFAULT,
MCBSP_XCR_XCOMPAND_DEFAULT,
MCBSP_XCR_XFIG_DEFAULT,
MCBSP_XCR_XDATDLY_DEFAULT,
MCBSP_XCR_XFRLEN1_DEFAULT,
MCBSP_XCR_XWDLEN1_DEFAULT
),
MCBSP_SRGR_RMK(
MCBSP_SRGR_GSYNC_DEFAULT, //All fields in SRGR set to default values
MCBSP_SRGR_CLKSP_DEFAULT,
MCBSP_SRGR_CLKSM_DEFAULT,
MCBSP_SRGR_FSGM_DEFAULT,
MCBSP_SRGR_FPER_DEFAULT,
MCBSP_SRGR_FWID_DEFAULT,
MCBSP_SRGR_CLKGDV_DEFAULT
),
MCBSP_MCR_RMK(
MCBSP_MCR_XPBBLK_DEFAULT, // All fields in MCR set to default values
MCBSP_MCR_XPABLK_DEFAULT,
MCBSP_MCR_XMCM_DEFAULT,
MCBSP_MCR_RPBBLK_DEFAULT,
MCBSP_MCR_RPABLK_DEFAULT,
MCBSP_MCR_RMCM_DEFAULT
),
MCBSP_RCER_RMK(
MCBSP_RCER_RCEB_DEFAULT, // All fields in RCER set to default values
MCBSP_RCER_RCEA_DEFAULT
),
MCBSP_XCER_RMK(
MCBSP_XCER_XCEB_DEFAULT, // All fields in XCER set to default values
MCBSP_XCER_XCEA_DEFAULT
),
MCBSP_PCR_RMK(
MCBSP_PCR_XIOEN_DEFAULT,
MCBSP_PCR_RIOEN_DEFAULT,
MCBSP_PCR_FSXM_DEFAULT,
MCBSP_PCR_FSRM_DEFAULT,
MCBSP_PCR_CLKXM_DEFAULT,
MCBSP_PCR_CLKRM_DEFAULT,
MCBSP_PCR_CLKSSTAT_DEFAULT,
MCBSP_PCR_DXSTAT_DEFAULT,
MCBSP_PCR_FSXP_DEFAULT,
MCBSP_PCR_FSRP_DEFAULT,
MCBSP_PCR_CLKXP_DEFAULT,
MCBSP_PCR_CLKRP_DEFAULT
)
};
hMcbsp0 = MCBSP_open(MCBSP_DEV0, MCBSP_OPEN_RESET); /* McBSP port 0 */
MCBSP_config(hMcbsp0, &mcbspCfg0);
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT09 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT1);
return;
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISR */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
transfer_done = TRUE;
return;
}
/*–––––––––––––––––––––––End of splitmode_dma.c––––––––––––––––––––––––––––––*/
framesync_dma.c:
This program sets up the DMA control registers to perform frame-synchronized
data transfers between internal data memory and the external AFE. DMA channel 1
is setup to transfer data from an external AFE data buffer (AFEInbuff) to
theinternal DSP data memory (dmaInbuff). This channel uses interrupt 9 to stop
thedata transfer process when the transfer is complete by setting a flag to the
CPU.DMA channel 2 is setup to transfer data from the internal DSP data memory
(dmaOutbff) to an external AFE buffer (AFEOutbuff). This channel uses interrupt
11 to stop the data transfer process when the transfer is complete by setting a
flag to the CPU.
Note that the user can modify this program to fit a specific application by
defining the mapping of the external source/destination buffer (for instance,
CE0 EMIF space can be used) and by selecting any of the DMA channels to perform
the transfers along with the corresponding interrupts.
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip Support
Library API User’s Guide (SPRA401) for further information.
*/
/* Include files */
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_XFER 8
#define XFER_TYPE DMA_XFER
#define BUFFER_SIZE 256 /* set element_count =< buffer_size */
#define ELEMENT_COUNT 32
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Declare CSL objects */
DMA_Handle hDma1; /* Handles for DMA */
DMA_Handle hDma2;
Uint32 dmaGblRegMsk; /* DMA Global Register Mask */
Uint32 dmaGblRegId = DMA_GBLCNTA | DMA_GBLADDRB | DMA_GBLADDRC;
/* Select Global Count Reload Register A or Global Address Register B or C */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* main() */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void main(void)
{
/* Declaration of local variables */
static int element_count, xfer_type;
element_count = ELEMENT_COUNT;
xfer_type = XFER_TYPE;
switch (xfer_type) {
case DMA_XFER:
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA channels 1 & 2 config structures */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Establish Global Register Values in the following configuration structure */
dmaGblRegMsk = DMA_globalAlloc(dmaGblRegId);
DMA_globalConfigArgs(dmaGblRegMsk,
DMA_GBLADDR_GBLADDR_DEFAULT, /* DMA global address registers A to D */
DMA_GBLADDR_GBLADDR_OF((unsigned int) dmaInbuff), // point to dmaInbuff
DMA_GBLADDR_GBLADDR_OF((unsigned int) dmaOutbuff), // point to dmaOutbuff
DMA_GBLADDR_GBLADDR_DEFAULT,
/* DMA channel 1 */
hDma1 = DMA_open(DMA_CHA1, DMA_OPEN_RESET); /* Handle to DMA channel 1 */
DMA_configArgs(hDma1,
DMA_PRICTL_RMK(
DMA_PRICTL_DSTRLD_B, /* Use DMA Global Address Reg. B for reload */
DMA_PRICTL_SRCRLD_DEFAULT,
DMA_PRICTL_EMOD_HALT, /* DMA cahnnel pauses during emulation halt */
DMA_PRICTL_FS_RSYNC, /* RSYNC event used to synch entire frame */
DMA_PRICTL_TCINT_ENABLE, /* TCINT =1 */
DMA_PRICTL_PRI_DMA, /* DMA high priority */
DMA_PRICTL_WSYNC_DEFAULT,
DMA_PRICTL_RSYNC_EXTINT4, /* Set sync. event EXT_INT4=00100 */
DMA_PRICTL_INDEX_DEFAULT,
DMA_PRICTL_CNTRLD_A, /* Reload with DMA global reload countrer A */
DMA_PRICTL_SPLIT_DEFAULT,
DMA_PRICTL_ESIZE_32BIT, /* Element size 32 bits */
DMA_PRICTL_DSTDIR_INC, /* Increment desctination by el. Size */
DMA_PRICTL_SRCDIR_DEFAULT,
DMA_PRICTL_START_DEFAULT
),
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_DEFAULT,
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_ENABLE, /* Frame condition enables DMA ch. inter.*/
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
/* DMA channel 2 */
hDma2= DMA_open(DMA_CHA2, DMA_OPEN_RESET); /* Handle to DMA channel 2 */
DMA_configArgs(hDma2,
DMA_PRICTL_RMK(
DMA_PRICTL_DSTRLD_DEFAULT,
DMA_PRICTL_SRCRLD_C, /* Use DMA Global Address Reg. C as reload */
DMA_PRICTL_EMOD_HALT, /* DMA cahnnel pauses during emulation halt */
DMA_PRICTL_FS_RSYNC, /* RSYNC event to synchronize entire frame */
DMA_PRICTL_TCINT_ENABLE, /* TCINT = 1 */
DMA_PRICTL_PRI_DMA, /* DMA high priority */
DMA_PRICTL_WSYNC_DEFAULT,
DMA_PRICTL_RSYNC_DMAINT1, /* Set sync. event DMA_INT1=01001 */
DMA_PRICTL_INDEX_DEFAULT,
DMA_PRICTL_CNTRLD_A, /* Reload with DMA global reload countrer A */
DMA_PRICTL_SPLIT_DEFAULT,
DMA_PRICTL_ESIZE_32BIT, /* Element size 32 bits */
DMA_PRICTL_DSTDIR_DEFAULT,
DMA_PRICTL_SRCDIR_INC, /* Increment destination by element size */
DMA_PRICTL_START_DEFAULT
),
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_DEFAULT,
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_ENABLE, // Frame cond enables DMA ch. inter.*/
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT09 */
IRQ_disable(IRQ_EVT_DMAINT2); /* INT11 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_clear(IRQ_EVT_DMAINT2);
IRQ_enable(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT2);
return;
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISRs */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
recv_done = TRUE;
return;
}
/*––––––––––––––––––––––End of framesync_dma.c–––––––––––––––––––––––––––––––*/
/**************************************************************
9/2/01:
Original by: Dave Bell
Modified by: Michael Haag and Vassos S. Soteriou
/* Include files */
#include <stdio.h>
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_XFER 8
#define XFER_TYPE DMA_XFER
/**************************************************************/
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* BEGIN main() */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/**************************************************************/
void main(void)
{
/* Declaration of local variables */
static int xfer_type, frame_index, element_index;
xfer_type = XFER_TYPE;
}
/**** END SWITCH HERE ****/
DMA_close(hDma1);
DMA_close(hDma2);
}
/********************************************************************/
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* END MAIN (PROGRAM ENDS HERE) */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/********************************************************************/
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* initialize DMA channels 1 and 2 */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void
init_dma(void)
{
Uint32 element_size;
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202/6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202/6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202/6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_DISABLE,
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_ENABLE, /* Enables DMA ch. inter.*/
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_DISABLE,
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_ENABLE,
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
#if (DMA_SUPPORT)
void /* Set the interrupts */
set_interrupts_dma(void) /* if the device supports DMA */
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT09 */
IRQ_disable(IRQ_EVT_DMAINT2); /* INT11 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_clear(IRQ_EVT_DMAINT2);
IRQ_enable(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT2);
return;
}
#endif
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISR */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
++count_recv;
/* Manually clear the FRAME COND bit following each frame transfer */
DMA_FSET(SECCTL1, FRAMECOND, 0);
return;
}
/* Ch2 ISR below entered ONLY if TCINT field in DMA PRICTL2 is enabled */
interrupt void /* vecs.asm hooks this up to IRQ 11 */
c_int11(void) /* DMA ch2 */
{
++count_xmit;
if (count_xmit == (loops)) // – 1) )
xmit_done = TRUE;
/* Manually clear the FRAME COND bit following each frame transfer */
DMA_FSET(SECCTL2, FRAMECOND, 0);
return;
}
/*–––––––––––––––––––End of circularbuff_dma.c–––––––––––––––*/
Description:
This program sets up the DMA control registers to perform data
transfers between internal data memory and the external AFE, using
a ping–pong buffering scheme for both input and outpt data. The
program writes 1 block of data to one input buffer while the other
input buffer is available to the CPU. Also, an output buffer is
read while the other output buffer can receive information from the
CPU. Once the second block is being written, the registers are
edited to reload the first buffers as the source and desitination
for the input and output transfers, respectively.
The sample code is based on TI’s CSL 2.0. See the TMS320C6000
Chip Support Library API User’s Guide (SPRU401) for further
information.
*********************************************************************/
/* Chip definition, change this accordingly */
#define CHIP_6202 1
/* Include files */
#include <stdio.h>
#include <c6x.h>
#include <csl.h> /* CSL library */
#include <csl_dma.h> /* DMA_SUPPORT */
#include <csl_irq.h> /* IRQ_SUPPORT */
/* Define constants */
#define DMA_XFER 8
#define XFER_TYPE DMA_XFER
#define ELEMENT_COUNT 1024
#define ELEMENT_SIZE 4 /* ELEMENT_SIZE is number of bytes/element, 1,2,4 */
#define FRAME_COUNT 2 /* Frames in the block transfer */
#define BUFFER_SIZE ELEMENT_COUNT /* Each buffer fits one frame */
#define LOOPS 3
Uint32 recv_counter = 0;
Uint32 xmit_counter = 0;
Uint32 loops = LOOPS; /* Number of transfers to perform */
/* Declare CSL objects */
DMA_Handle hDma1; /* Handle for DMA */
DMA_Handle hDma2;
Uint32 dmaGblRegMsk; /* DMA Global Register Mask */
/********************************************************************/
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* BEGIN main() */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/********************************************************************/
void main(void)
{
/* Declaration of local variables */
static int element_count, xfer_type, frame_index, element_index;
static int frame_count, element_size;
element_count = ELEMENT_COUNT;
xfer_type = XFER_TYPE;
frame_count = FRAME_COUNT;
/* Calculate the index values, as well as the ESIZE, based on the number of */
/* elements per frame (element_count), the number of frames per block */
/* (frmame_count), and the number of bytes in each element (element_size) */
element_index = ELEMENT_SIZE;
/* covert the number of bytes/element into the CSL HAL MACRO conversion */
if (ELEMENT_SIZE == 1) element_size = 2; /* 8BIT element size */
else if (ELEMENT_SIZE == 2) element_size = 1; /* 16BIT element size */
else element_size = 0; /* 32BIT element size */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA channel 1 & 2 config structures */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
DMA_reset(INV); /* reset all DMA channels */
dmaGblRegMsk = DMA_globalAlloc(dmaGblRegId);
DMA_globalConfigArgs(dmaGblRegMsk,
DMA_GBLADDR_GBLADDR_DEFAULT, /* DMA global address registers A to D*/
DMA_GBLADDR_GBLADDR_OF((Uint32) dmaInbuff1), /* point to dmaInbuff1 */
DMA_GBLADDR_GBLADDR_OF((Uint32) dmaOutbuff1),/* point to dmaOutbuff1 */
DMA_GBLADDR_GBLADDR_DEFAULT,
/* DMA channel 2 */
hDma2= DMA_open(DMA_CHA2, DMA_OPEN_RESET); /* Handle to DMA channel 2 */
DMA_configArgs(hDma2,
DMA_PRICTL_RMK(
DMA_PRICTL_DSTRLD_DEFAULT,
DMA_PRICTL_SRCRLD_C, /* Use Global Address Register C for reload */
DMA_PRICTL_EMOD_DEFAULT,
DMA_PRICTL_FS_RSYNC, /* RSYNC event to synchronize entire frame */
DMA_PRICTL_TCINT_DISABLE, /* TCINT = 0 */
DMA_PRICTL_PRI_CPU,
DMA_PRICTL_WSYNC_DEFAULT,
DMA_PRICTL_RSYNC_DMAINT1, /* Set sync. event DMA_INT1=01001 */
DMA_PRICTL_INDEX_DEFAULT,
DMA_PRICTL_CNTRLD_A, /* reload with DMA global reload counter A */
DMA_PRICTL_SPLIT_DEFAULT,
DMA_PRICTL_ESIZE_OF(element_size), /*Element size defined by user */
DMA_PRICTL_DSTDIR_NONE, /* Increment source by element size */
DMA_PRICTL_SRCDIR_IDX, // Adjust src using DMA Global Index Reg. A
DMA_PRICTL_START_DEFAULT
),
DMA_SECCTL_RMK(
DMA_SECCTL_WSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_RSPOL_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_FSIG_NA, /* only available for 6202 and 6203 devices */
DMA_SECCTL_DMACEN_DEFAULT,
DMA_SECCTL_WSYNCCLR_DEFAULT,
DMA_SECCTL_WSYNCSTAT_DEFAULT,
DMA_SECCTL_RSYNCCLR_DEFAULT,
DMA_SECCTL_RSYNCSTAT_DEFAULT,
DMA_SECCTL_WDROPIE_DEFAULT,
DMA_SECCTL_WDROPCOND_DEFAULT,
DMA_SECCTL_RDROPIE_DEFAULT,
DMA_SECCTL_RDROPCOND_DEFAULT,
DMA_SECCTL_BLOCKIE_ENABLE,
DMA_SECCTL_BLOCKCOND_DEFAULT,
DMA_SECCTL_LASTIE_DEFAULT,
DMA_SECCTL_LASTCOND_DEFAULT,
DMA_SECCTL_FRAMEIE_ENABLE, /* enable */
DMA_SECCTL_FRAMECOND_DEFAULT,
DMA_SECCTL_SXIE_DEFAULT,
DMA_SECCTL_SXCOND_DEFAULT
),
}
/**** END SWITCH HERE ****/
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void) /* if the device supports DMA */
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT09 */
IRQ_disable(IRQ_EVT_DMAINT2); /* INT11 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_clear(IRQ_EVT_DMAINT2);
IRQ_enable(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT2);
return;
}
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISR */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
/* Begin Channel 2 after Channel 1 has completed its transfer */
/* of the first block. Remeber, this means one more block will */
/* will be transfered in than is transfered out if an extra */
/* output is not triggered. */
if (recv_counter == 1)
DMA_autoStart(hDma2);
/* NOTE: Ch2 ISR entered ONLY if TCINT field in DMA PRICTL2 is enabled */
interrupt void /* vecs.asm hooks this up to IRQ 11 */
c_int11(void) /* DMA ch2 */
{
DMA_FSET(SECCTL2, FRAMECOND, 0);
if (DMA_FGET(SECCTL2, BLOCKCOND) )
{
DMA_FSET(SECCTL2, BLOCKCOND, 0);
xmit_counter++;
}
return;
}
/*–––––––––––––––––––––––End of ping_pong__dma.c–––––––––––––––––––*/
paging_dma.c:
This sample code sets up the DMA control registers to perform data
Transfers from external memory to internal DSP program memory using a paging
scheme. There are four external program pages, extPage1, extPage2, extPage3
and extPage4. These are brought into internal program memory locations,
intPage1 and IntPage2, to be executed. extPage1 is first brought into
intPage1, then extPage2 into intPage2, then extPage3 into intPage1
(overwritten) and lastly extPage4 to intPage1 (overwritten). Note that the
extPage1 and extPage 2 are transferred to the internal program memory first
and that in the interrupt service routine the DMA_GBLADDRB and DMA_GBLADDRC
are adjusted (reloaded) with the addresses of extPage3 and extPage4 (and
also with the address of intPage1 and intPage2) to complete the transfers
from extPage3 and extPage4 to the internal DSP program memory.
The sample code is based on TI’s CSL 2.0. See the TMS320C6000 Chip
Support Library API User’s Guide (SPRU401) for further information.
*/
/* Define constants */
#define FALSE 0
#define TRUE 1
#define DMA_TRANS 8
#define XFER_TYPE DMA_TRANS
#define BUFFER_SIZE 256 /* >= (ELEMENT_COUNT * FRAME_COUNT) */
#define FRAME_COUNT 1 /* Keep this value to 1 frame */
#define ELEMENT_COUNT 32 /* Define # of elements to transfer per page */
/* Let these buffers in the global section as they are also used */
/* in the Interrupt Service Routines (ISRs) */
static Uint32 intPage1[BUFFER_SIZE]; /* define internal pages */
static Uint32 intPage2[BUFFER_SIZE];
void main(void)
{
/* Declaration of local variables */
static int element_count, xfer_type, frame_count, page_size;
switch (xfer_type) {
case DMA_TRANS:
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* set_interrupts_dma() */
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
void /* Set the interrupts */
set_interrupts_dma(void)
{
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_disable(IRQ_EVT_DMAINT1); /* INT9 */
IRQ_clear(IRQ_EVT_DMAINT1);
IRQ_enable(IRQ_EVT_DMAINT1);
return;
}
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* DMA DATA TRANSFER COMPLETION ISR */
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
interrupt void /* vecs.asm hooks this up to IRQ 09 */
c_int09(void) /* DMA ch1 */
{
transfer_done = TRUE;
/* Allocate DMA Global Address Registers B & C */
RegId1 = DMA_allocGlobalReg(DMA_GBL_ADDRRLD, 0x0184003C);
RegId2 = DMA_allocGlobalReg(DMA_GBL_ADDRRLD, 0x0184006C);
return;
}
/*–––––––––––––––––––––––End of paging_dma.c–––––––––––––––––––––––––––––––––*/
Texas Instruments Incorporated and its subsidiaries (TI) reserve the right to make corrections, modifications,
enhancements, improvements, and other changes to its products and services at any time and to discontinue
any product or service without notice. Customers should obtain the latest relevant information before placing
orders and should verify that such information is current and complete. All products are sold subject to TI’s terms
and conditions of sale supplied at the time of order acknowledgment.
TI warrants performance of its hardware products to the specifications applicable at the time of sale in
accordance with TI’s standard warranty. Testing and other quality control techniques are used to the extent TI
deems necessary to support this warranty. Except where mandated by government requirements, testing of all
parameters of each product is not necessarily performed.
TI assumes no liability for applications assistance or customer product design. Customers are responsible for
their products and applications using TI components. To minimize the risks associated with customer products
and applications, customers should provide adequate design and operating safeguards.
TI does not warrant or represent that any license, either express or implied, is granted under any TI patent right,
copyright, mask work right, or other TI intellectual property right relating to any combination, machine, or process
in which TI products or services are used. Information published by TI regarding third–party products or services
does not constitute a license from TI to use such products or services or a warranty or endorsement thereof.
Use of such information may require a license from a third party under the patents or other intellectual property
of the third party, or a license from TI under the patents or other intellectual property of TI.
Reproduction of information in TI data books or data sheets is permissible only if reproduction is without
alteration and is accompanied by all associated warranties, conditions, limitations, and notices. Reproduction
of this information with alteration is an unfair and deceptive business practice. TI is not responsible or liable for
such altered documentation.
Resale of TI products or services with statements different from or beyond the parameters stated by TI for that
product or service voids all express and any implied warranties for the associated TI product or service and
is an unfair and deceptive business practice. TI is not responsible or liable for any such statements.
Mailing Address:
Texas Instruments
Post Office Box 655303
Dallas, Texas 75265