Dma PDF
Dma PDF
Dma PDF
HIGHLIGHTS
This section of the manual contains the following major topics:
Direct Memory
Access (DMA)
38.13 Related Application Notes.......................................................................................... 38-53
(Part III)
38.14 Revision History ......................................................................................................... 38-54
Note: This family reference manual section is meant to serve as a complement to device
data sheets. Depending on the device variant, this manual section may not apply to
all dsPIC33F/PIC24H devices.
Please consult the note at the beginning of the “Direct Memory Access (DMA)”
chapter in the current device data sheet to check whether this document supports
the device you are using.
Device data sheets and family reference manual sections are available for
download from the Microchip Worldwide Web site at: http://www.microchip.com
38.1 INTRODUCTION
The Direct Memory Access (DMA) controller is an important subsystem in Microchip's
high-performance 16-bit Digital Signal Controller (DSC) families. This subsystem facilitates the
transfer of data between the CPU and its peripheral without CPU assistance. The
dsPIC33F/PIC24H DMA controller is optimized for high-performance, real-time, embedded
applications, where determinism and system latency are priorities.
The DMA controller transfers data between peripheral data registers and data space SRAM. The
dsPIC33F/PIC24H DMA subsystem uses Dual Port SRAM (DPSRAM) memory and register
structures that allow the DMA to operate across its own, independent address and data buses
with no impact on CPU operation. This architecture eliminates the need for cycle stealing, which
halts the CPU when a higher priority DMA transfer is requested. Both the CPU and DMA
controller can write and read to/from addresses within data space without interference, such as
CPU stalls, resulting in maximized, real-time performance. Alternately, DMA operation and data
transfer to/from the memory and peripherals are not impacted by CPU processing. For example,
when a Run-Time Self-Programming (RTSP) operation is performed, the CPU does not execute
any instructions until RTSP is finished. This condition, however, does not impact data transfer
to/from memory and the peripherals. Figure 38-1 illustrates the DMA setup.
DPSRAM
The DMA controller supports eight independent channels. Each channel can be configured for
transfers to/from selected peripherals. Peripherals supported by the DMA controller include:
• Enhanced Controller Area Network (ECAN™) technology
• Data Converter Interface (DCI)
• 10-bit/12-bit Analog-to-Digital Converter (ADC)
• Serial Peripheral Interface (SPI)
• Universal Asynchronous Receiver Transmitter (UART)
• Input Capture
• Output Compare
• Digital-to-Analog Converter (DAC)
• Parallel Master Port (PMP)
In addition, DMA transfers can be triggered by timers as well as external interrupts. Each DMA
channel is unidirectional. Two DMA channels must be allocated to read and write to a peripheral.
Should more than one channel receive a request to transfer data, a simple fixed priority scheme,
based on channel number, dictates which channel completes the transfer and which channel, or
channels, are left pending. Each DMA channel moves a block of up to 1024 data elements, after
which it generates an interrupt to the CPU to indicate that the block is available for processing.
The DMA controller provides these functional capabilities:
• Eight DMA channels
• Register Indirect with Post-Increment Addressing mode
• Register Indirect without Post-Increment Addressing mode
• Peripheral Indirect Addressing mode (peripheral generates destination address) 38
• CPU interrupt after half or full block transfer complete
• Byte or word transfers
Direct Memory
Access (DMA)
• Fixed priority channel arbitration
(Part III)
• Manual (software) or Automatic (peripheral DMA requests) transfer initiation
• One-shot or Auto-repeat block transfer modes
• Ping-Pong mode (automatic switch between two DPSRAM start addresses after each block
transfer completes)
• DMA request for each channel can be selected from any supported interrupt source
• Debug support features
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
Direct Memory
Access (DMA)
bit 12 HALF: Block Transfer Interrupt Select bit
1 = Initiate interrupt when half of the data has been moved
(Part III)
0 = Initiate interrupt when all of the data has been moved
bit 11 NULLW: Null Data Peripheral Write Mode Select bit
1 = Null data write to peripheral in addition to DPSRAM write (DIR bit must also be clear)
0 = Normal operation
bit 10-6 Unimplemented: Read as ‘0’
bit 5-4 AMODE<1:0>: DMA Channel Addressing Mode Select bits
11 = Reserved
10 = Peripheral Indirect Addressing mode
01 = Register Indirect without Post-Increment mode
00 = Register Indirect with Post-Increment mode
bit 3-2 Unimplemented: Read as ‘0’
bit 1-0 MODE<1:0>: DMA Channel Operating Mode Select bits
11 = One-shot, Ping-Pong modes enabled (one block transfer from/to each DMA RAM buffer)
10 = Continuous, Ping-Pong modes enabled
01 = One-shot, Ping-Pong modes disabled
00 = Continuous, Ping-Pong modes disabled
Note 1: The FORCE bit cannot be cleared by the user. The FORCE bit is cleared by hardware when the forced
DMA transfer is complete.
Register 38-3: DMAXSTA: DMA Channel X DPSRAM Start Address Offset Register A
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
bit 15-0 STA<15:0>: Primary DPSRAM Start Address Offset bits (source or destination)
Register 38-4: DMAXSTB: DMA Channel X DPSRAM Start Address Offset Register B
Direct Memory
Access (DMA)
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
(Part III)
STB<7:0>
bit 7 bit 0
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
bit 15-0 STB<15:0>: Secondary DPSRAM Start Address Offset bits (source or destination)
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
bit 15-0 DSADR<15:0>: Most Recent DMA DPSRAM Address Accessed by DMA bits
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
Direct Memory
Access (DMA)
bit 12 PWCOL4: Channel 4 Peripheral Write Collision Flag bit
1 = Write collision detected
(Part III)
0 = No write collision detected
bit 11 PWCOL3: Channel 3 Peripheral Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 10 PWCOL2: Channel 2 Peripheral Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 9 PWCOL1: Channel 1 Peripheral Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 8 PWCOL0: Channel 0 Peripheral Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 7 XWCOL7: Channel 7 DPSRAM Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 6 XWCOL6: Channel 6 DPSRAM Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 5 XWCOL5: Channel 5 DPSRAM Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
bit 4 XWCOL4: Channel 4 DPSRAM Write Collision Flag bit
1 = Write collision detected
0 = No write collision detected
Legend:
R = Readable bit W = Writable bit U = Unimplemented bit, read as ‘0’
-n = Value at POR ‘1’ = Bit is set ‘0’ = Bit is cleared x = Bit is unknown
Direct Memory
Access (DMA)
0000 = Last data transfer was by Channel 0
Set to ‘1111’ at Reset. This field is accessible at any time but is primarily intended as a debugging aid.
(Part III)
bit 7 PPST7: Channel 7 Ping-Pong Mode Status Flag bit
1 = DMA7STB register selected
0 = DMA7STA register selected
bit 6 PPST6: Channel 6 Ping-Pong Mode Status Flag bit
1 = DMA6STB register selected
0 = DMA6STA register selected
bit 5 PPST5: Channel 5 Ping-Pong Mode Status Flag bit
1 = DMA5STB register selected
0 = DMA5STA register selected
bit 4 PPST4: Channel 4 Ping-Pong Mode Status Flag bit
1 = DMA4STB register selected
0 = DMA4STA register selected
bit 3 PPST3: Channel 3 Ping-Pong Mode Status Flag bit
1 = DMA3STB register selected
0 = DMA3STA register selected
bit 2 PPST2: Channel 2 Ping-Pong Mode Status Flag bit
1 = DMA2STB register selected
0 = DMA2STA register selected
bit 1 PPST1: Channel 1 Ping-Pong Mode Status Flag bit
1 = DMA1STB register selected
0 = DMA1STA register selected
bit 0 PPST0: Channel 0 Ping-Pong Mode Status Flag bit
1 = DMA0STB register selected
0 = DMA0STA register selected
DMA Controller
DMA IRQ to DMA
DMA Ready and Interrupt
Control
DMA
SRAM DPSRAM Channels Peripheral 1 Controller
0 1 2 3 4 5 6 7 Modules
PORT 1 PORT 2 CPU DMA
Unlike other architectures, the dsPIC33F/PIC24H CPU is capable of a read and a write access
within each CPU bus cycle. Similarly, the DMA can complete the transfer of a byte or word every
bus cycle across its dedicated bus. This also ensures that all DMA transfers are not interrupted.
That is, once the transfer has started, it will complete within the same cycle, irrespective of other
channel activity.
The user application can designate any DMA-ready peripheral interrupt to be a DMA request, the
term given to an IRQ when it is directed to the DMA. It is assumed, of course, that when a DMA
channel is configured to respond to a particular interrupt as a DMA request, the corresponding
CPU interrupt is disabled, otherwise a CPU interrupt will also be requested.
Each DMA channel can also be triggered manually through software. Setting the Force DMA
Transfer bit (FORCE) in the DMA Channel X IRQ Select register (DMAxREQ) initiates a manual
DMA request that is subject to the same arbitration as all interrupt based DMA requests
(see 38.8 “DMA Channel Arbitration and Overruns”).
Direct Memory
Access (DMA)
(Part III)
DMA Ch 5
Control
DMA
SRAM DPSRAM Peripheral 1
PORT 1 PORT 2 CPU DMA
DMA Ch 5
Control
DMA
SRAM DPSRAM Peripheral 1
PORT 1 PORT 2 CPU DMA
DMA Request
SRAM X Bus
CPU
DATA
Control
DMA
DPSRAM Address
Direct Memory
Access (DMA)
External Interrupt 0 (INT0) 0000000 — —
(Part III)
Input Capture 1 (IC1) 0000001 0x0140 (IC1BUF) —
Input Capture 2 (IC2) 0000101 0x0144 (IC2BUF) —
Output Compare 1 Data – OC1 0000010 — 0x0182 (OC1R)
Output Compare 1 Secondary Data (OC1) 0000010 — 0x0180 (OC1RS)
Output Compare 2 Data (OC2) 0000110 — 0x0188 (OC2R)
Output Compare 2 Secondary Data (OC2) 0000110 — 0x0186 (OC2RS)
Timer2 (TMR2) 0000111 — —
Timer3 (TMR3) 0001000 — —
Transfer Done (SPI1) 0001010 0x0248 (SPI1BUF) 0x0248 (SPI1BUF)
Transfer Done (SPI2) 0100001 0x0268 (SPI2BUF) 0x0268 (SPI2BUF)
UART1 Receiver (UART1RX) 0001011 0x0226 (U1RXREG) —
UART1 Transmitter (UART1TX) 0001100 — 0x0224 (U1TXREG)
UART2 Receiver (UART2RX) 0011110 0x0236 (U2RXREG) —
UART2 Transmitter (UART2TX) 0011111 — 0x0234 (U2TXREG)
RX Data Ready (ECAN1) 0100010 0x0440 (C1RXD) —
TX Data Request (ECAN1) 1000110 — 0x0442 (C1TXD)
CODEC Transfer Done (DCI) 0111100 0x0290 (RXBUF0) 0x0298 (TXBUF0)
ADC1 Convert Done (ADC1) 0001101 0x0300 (ADC1BUF0) —
PMP Master Data Transfer (PMP) 0101101 0x0608 (PMDIN1) 0x0608 (PMDIN1)
DAC1 Right Data Transfer (DAC1) 1001110 — 0x03F6 (DAC1RDAT)
DAC1 Left Data Transfer (DAC1) 1001111 — 0x03F8 (DAC1LDAT)
If two DMA channels select the same peripheral as the source of their DMA request, both
channels receive the DMA request simultaneously. However, the highest priority channel
executes its transfer first, leaving the other channel pending. This situation is common where a
single DMA request is used to move data both to and from a peripheral (for example, SPI). Two
DMA channels are used. One DMA channel is allocated for peripheral reads, and the other DMA
channel is allocated for peripheral data writes. Both the DMA channels use the same DMA
request.
If the DMAxPAD register is initialized to a value not listed in Table 38-1, DMA channel writes to
this peripheral address will be ignored. DMA channel reads from this address will result in a read
of ‘0’.
An error condition within a DMA enabled peripheral generally sets a status flag and generates
an interrupt (if interrupts are enabled by the user application). When a peripheral is serviced by
the CPU, the data interrupt handler is required to check for error flags and, if necessary, take the
appropriate action. However, when a peripheral is serviced by the DMA channel, the DMA can
only respond to data transfer requests and it is not aware of any subsequent error conditions. All
error conditions in DMA compatible peripherals must have an associated interrupt enabled and 38
be serviced by the user-defined Interrupt Service Routine (ISR), if such an interrupt is present in
the peripheral.
Direct Memory
Access (DMA)
(Part III)
Figure 38-4: Data Memory Map for dsPIC33F/PIC24H Devices with 16 Kbytes RAM
MSb LSb
Address Address
16 bits
MSb LSb
0x0001 0x0000
2 Kbyte
SFR Space
SFR Space 0x07FE 8 Kbyte
0x07FF
0x0801 0x0800 Near
Data
X Data RAM (X) Space
0x1FFF 0x1FFE
0x8001 0x8000
X Data
Unimplemented (X)
Optionally
Mapped
into Program
Memory
0xFFFF 0xFFFE
To operate properly, the DMA needs to know the DPSRAM address to read from or write to as
an offset from the beginning of the DMA memory. This information is configured in the DMAxSTA
and DMAxSTB register. Figure 38-5 illustrates an example of how the primary and secondary
DMA Channel 4 buffers are set up on the dsPIC33FJ128MC804 device at address 0x4000 and
0x4010, respectively.
Secondary 0x4010
DMA RAM
Buffer &_DMA_BASE+DMA4STA (0x4000 + 0x0010 = 0x4010)
Code Example:
DMA4STA = 0x0000;
DMA4STB = 0x0010;
In Figure 38-5, you must be familiar with the memory layout for the device to hard code this
information into the application. Also, you must use pointer arithmetic to access these buffers
after the DMA transfer is complete. As a result, this implementation is difficult to port from one
processor to another.
The MPLAB® C30 compiler simplifies DMA buffer initialization and access by providing built-in
C language primitives for that purpose. For example, the code in Figure 38-6 allocates two
buffers in the DMA memory and initializes the DMA channel to point to them.
Figure 38-6: Primary and Secondary DMA Buffer Allocation with MPLAB® IDE 38
Direct Memory
Access (DMA)
&_DMA_BASE
(Part III)
DMA RAM
0x47E0
Buffer B
(Secondary)
0x47EE
Buffer A 0x47F0
(Primary)
0x47FE
0x4800
Code Example:
unsigned int BufferA[8] __attribute__((space(dma)));
unsigned int BufferB[8] __attribute__((space(dma)));
DMA0STA = __builtin_dmaoffset(BufferA);
DMA0STB = __builtin_dmaoffset(BufferB);
Note: MPLAB LINK30 linker allocates the primary and secondary buffers in reverse order
starting at the bottom of the DMA memory space.
If the DMAxSTA (and/or DMAxSTB) register is initialized to a value that will result in the DMA
channel reading or writing RAM addresses outside of DMA RAM space, DMA channel writes to
this memory address are ignored. DMA channel reads from this memory address result in a read
of ‘0’.
Direct Memory
Access (DMA)
38.6.2 Transfer Direction
(Part III)
Each DMA channel can be configured to transfer data from a peripheral to the DPSRAM or from
the DPSRAM to a peripheral.
If the Transfer Direction bit (source/destination bus select), DIR (DMAxCON<13>) is clear, data
is read from the peripheral (using the peripheral address as provided by DMAxPAD), and the
destination write is directed to the DPSRAM DMA memory address offset (using DMAxSTA or
DMAxSTB).
If the DIR bit (DMAxCON<13>) is set, data is read from the DPSRAM DMA memory address
offset (using DMAxSTA or DMAxSTB), and the destination write is directed to the peripheral
(using the peripheral address, as provided by DMAxPAD).
Once configured, each channel is a unidirectional data conduit. That is, should a peripheral
require read and write data using the DMA controller, two channels must be assigned – one for
read and one for write.
&_DMA_BASE
COUNT++
Transfer #3 DMAxCNT+1
COUNT =
2
COUNT = 0 Transfer #n
Half Transfer IRQ
to CPU
In all modes, when the HALF bit (DMAxCON<12>) is set, the DMA issues an interrupt only
when the first half of Buffer A and/or B is transferred. No interrupt is issued when Buffer A
and/or B is completely transferred. In other words, interrupts are only issued when DMA
completes (DMAxCNT + 1)/2 transfers. If (DMAxCNT + 1) is equal to an odd number,
interrupts are issued after (DMAxCNT + 2)/2 transfers.
For example, if DMA3 is configured for One-Shot, Ping-Pong buffers (MODE<1:0> = 11), and
DMA3CNT = 7, two DMA3 interrupts are issued. One DMA3 interrupt is issued after transferring
four elements from Buffer A, and the other DMA3 interrupt is issued after transferring four
elements from Buffer B. For more information, refer to 38.6.7 “One-Shot Mode” and
38.6.9 “Ping-Pong Mode”.
Even though the DMA channel issues an interrupt on either half or full block transfers, the user
application can “trick” the DMA channel into issuing an interrupt on half and full block transfers
by toggling the value of the HALF bit (DMAxCON<12>) during each DMA interrupt. For example,
if the DMA channel is set up with the HALF bit (DMAxCON<12>) set to ‘1’, an interrupt is issued
after each half block transfer. If the user application resets the HALF bit (DMAxCON<12>) to ‘0’
while the interrupt is being serviced, the DMA issues another interrupt when the full block transfer
is complete.
To enable these interrupts, the corresponding DMA Interrupt Enable bit (DMAxIE) must be set in
the Interrupt Enable Control (IECx) register in the Interrupt Controller module, as shown in
Table 38-3.
Each DMA channel transfer interrupt sets a corresponding status flag in the interrupt controller,
which triggers the ISR. The user application must then clear that status flag to prevent the
transfer-complete ISR from re-executing.
Table 38-4 shows the Interrupt Flag Status (IFSx) register and the corresponding bit name,
DMAxIF, in the Interrupt Controller module. It also shows the C Structure Access Code that clears
the flag.
Table 38-4: Interrupt Controller Settings for Clearing DMA Interrupt Status Flags
Interrupt Controller
DMA Corresponding Register C Structure
Register Name and
Channel Bit Name Access Code
Bit Number
0 IFS0<4> DMA0IF IFS0bits.DMA0IE
1 IFS0<14> DMA1IF IFS0bits.DMA1IE
2 IFS1<8> DMA2IF IFS1bits.DMA2IE
3 IFS2<4> DMA3IF IFS2bits.DMA3IE
4 IFS2<14> DMA4IF IFS2bits.DMA4IE
5 IFS3<13> DMA5IF IFS3bits.DMA5IE
6 IFS4<4> DMA6IF IFS4bits.DMA6IE
7 IFS4<5> DMA7IF IFS4bits.DMA7IE
As an example, assume DMA channel 0 interrupt is enabled, DMA channel 0 transfer has
finished, and the associated interrupt has been issued to the interrupt controller. The following
code must be present in the DMA channel 0 ISR to clear the status flag and to prevent a pending
interrupt. Example 38-2 shows how DMA channel 0 interrupt is cleared.
38
Example 38-2: Code to Clear DMA Channel 0 Interrupt
Direct Memory
Access (DMA)
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
(Part III)
{
. . .
IFS0bits.DMA0IF = 0;
}
Figure 38-8: Data Transfer with Register Indirect with Post-Increment Addressing
&_DMA_BASE
Peripheral DMA Transfe
1 Channel 3 r 1
Data 1 &_DMA_BASE + DMA3STA + 0
Data 2 &_DMA_BASE + DMA3STA + 1
Data 3 &_DMA_BASE + DMA3STA + 2
&_DMA_BASE
Peripheral DMA
Tran
1 Channel 3 s fer 2 Data 1 &_DMA_BASE + DMA3STA + 0
Data 2 &_DMA_BASE + DMA3STA + 1
Data 3 &_DMA_BASE + DMA3STA + 4
&_DMA_BASE
Peripheral DMA
1 Channel 3 Tra
nsf Data 1 &_DMA_BASE + DMA3STA + 0
er
3 Data 2 &_DMA_BASE + DMA3STA + 1
Data 3 &_DMA_BASE + DMA3STA + 2
Example 38-3: Code for Output Compare and DMA with Register Indirect
Post-Increment Mode
Set up Output Compare 1 module for PWM mode:
OC1CON = 0; // Reset OC module
OC1R = 0x60; // Initialize PWM Duty Cycle
OC1RS = 0x60; // Initialize PWM Duty Cycle Buffer
DMA3STA = __builtin_dmaoffset(BufferA);
Direct Memory
Access (DMA)
Set up DMA Channel 3 Interrupt Handler:
(Part III)
void __attribute__((interrupt, no_auto_psv)) _DMA3Interrupt(void)
{
/* Update BufferA with new Duty Cycle values if desired here*/
Figure 38-9: Contrast of Data Transfer with and without Post-Increment Addressing
&_DMA_BASE
Peripheral DMA Transfe
r1
1 Channel 0
Data 0 &_DMA_BASE + DMA3STA + 0
&_DMA_BASE + DMA3STA + 1
&_DMA_BASE + DMA3STA + 2
&_DMA_BASE + DMA3STA + 3
&_DMA_BASE
Peripheral DMA Tra
nsfe
1 Channel 0 r 2 Data 0 &_DMA_BASE + DMA3STA + 0
Data 1 &_DMA_BASE + DMA3STA + 1
&_DMA_BASE + DMA3STA + 2
&_DMA_BASE + DMA3STA + 3
&_DMA_BASE
Peripheral DMA Tra
1 Channel 0 ns
fer Data 0 &_DMA_BASE + DMA3STA + 0
3
Data 1 &_DMA_BASE + DMA3STA + 1
Data 2 &_DMA_BASE + DMA3STA + 2
&_DMA_BASE + DMA3STA + 3
&_DMA_BASE
Peripheral DMA Tra
1 Channel 0 ns
fer Data 0
4 &_DMA_BASE + DMA3STA + 0
Data 1 &_DMA_BASE + DMA3STA + 1
Data 3 &_DMA_BASE + DMA3STA + 2
&_DMA_BASE + DMA3STA + 3
Example 38-4: Code for Input Capture and DMA with Register Indirect without
Post-Increment Addressing
Set up Input Capture 1 module for DMA operation:
IC1CON = 0; // Reset IC module
IC1CONbits.ICTMR = 1; // Select Timer2 contents for capture
IC1CONbits.ICM = 2; // Capture every falling edge
IC1CONbits.ICI = 0; // Generate DMA request on every capture event
DMA3STA = __builtin_dmaoffset(&CaptureValue);
38
IFS0bits.DMA0IF = 0; // Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; // Set the DMA interrupt enable bit
Direct Memory
Access (DMA)
Set up DMA Channel 0 Interrupt Handler:
(Part III)
void __attribute__((interrupt, no_auto_psv)) _DMA3Interrupt(void)
{
/* Process CaptureValue variable here*/
0. . . . 0 PIA Address
Offset Address 0. . . . 0
Application Responsibility:
Offset Address Set to ‘0’
(from DMAxSTA or DMAxSTB)
The peripheral determines how many Least Significant address bits it will control. The application
program must select a base address for the buffer in DPSRAM and ensure that the
corresponding number of LSbs of that address offset are zero. As with other modes, when the
DMAxSTA or DMAxSTB register is read, it returns a value of the latest DPSRAM transfer address
offset, which includes the address offset calculation described above. If the DMA channel is not
configured for Peripheral Indirect Addressing, the incoming address is ignored and the data
transfer occurs as normal.
Peripheral Indirect Addressing mode is compatible with all other operating modes, and is
currently supported by the ADC and ECAN modules.
Figure 38-11: Data Transfer from ADC with Register Indirect Addressing
&_DMA_BASE
Data Transfer 1
AN0 AN0 Sample 1 &_DMA_BASE+DMA5STA+PIA (for Transfer 1)
DMA Transfer 2
AN1 Channel Trans AN1 Sample 1
ADC fer 3
AN2 5 AN2 Sample 1
AN3 AN3 Sample 1
DMA AN0 Sample 2
Request AN1 Sample 2
AN2 Sample 2
AN3 Sample 2
Tra
n
AN0 Sample 3
sfe
r
AN1 Sample 3
12
AN2 Sample 3
AN3 Sample 3
Example 38-5: Code for Data Transfer from ADC with Register Indirect Addressing
Set up ADC1 for channel 0-3 sampling:
AD1CON1bits.FORM = 3; // Data Output Format: Signed Fraction (Q15 format)
AD1CON1bits.SSRC = 2; // Sample Clock Source: GP Timer starts conversion
AD1CON1bits.ASAM = 1; // Sampling begins immediately after conversion
AD1CON1bits.AD12B = 0; // 10-bit ADC operation
AD1CON1bits.SIMSAM = 0; // Samples individual channels sequentially
AD1CON2bits.BUFM = 0;
AD1CON2bits.CSCNA = 1; // Scan CH0+ Input Selections during Sample A bit
AD1CON2bits.CHPS = 0; // Converts CH0
Direct Memory
Access (DMA)
IFS0bits.T3IF = 0; // Clear Timer3 interrupt
IEC0bits.T3IE = 0; // Disable Timer3 interrupt
(Part III)
T3CONbits.TON = 1; //Start Timer3
Set up DMA Channel 5 for Register Indirect with Post-Increment Addressing:
unsigned int BufferA[32] __attribute__((space(dma)));
unsigned int BufferB[32] __attribute__((space(dma)));
DMA5STA = __builtin_dmaoffset(BufferA);
DMA5STB = __builtin_dmaoffset(BufferB);
Example 38-5: Code for Data Transfer from ADC with Register Indirect Addressing
(Continued)
{
ProcessADCSamples(BufferA);
}
else
{
ProcessADCSamples(BufferB);
}
DmaBuffer ^= 1;
A typical algorithm would operate on a per ADC data channel basis, requiring it to either sort
transferred data or index it by jumping unwanted data. Either of these methods require more
code and consume more execution time. ADC Peripheral Indirect Addressing mode defines a
special addressing technique where data for each ADC channel is placed into its own buffer. For
Example 38-5, if the DMA channel is configured for Peripheral Indirect Addressing mode, the
DMA transfer moves ADC data into separate buffers, as illustrated in Figure 38-12.
Figure 38-12: Data Transfer from ADC with Peripheral Indirect Addressing
Peripheral Indirect Address (PIA)
&_DMA_BASE
Data Transfer 1
AN0 AN0 Sample 1 &_DMA_BASE+DMA5STA+PIA (for Transfer 1)
DMA Transfer 5
AN1 ADC Channel Tr AN0 Sample 2 :
an
5 sfe AN0 Sample 3 :
AN2 r2 :
:
Tr
AN3
ans
:
Tra
AN1 Sample 3 :
ns
:
fer
: :
4
AN2 Sample 1 :
:
Tra
AN2 Sample 2
:
ns
AN2 Sample 3 :
fer
: :
12
:
AN3 Sample 1 :
AN3 Sample 2 :
AN3 Sample 3 &_DMA_BASE+DMA5STA+PIA (for Transfer 12)
:
To enable this kind of ADC addressing, the DMA Buffer Build Mode bit, ADDMABM (ADxCON1),
must be cleared. If the ADDMABM bit (ADxCON1<12>) is set, the ADC generates addresses in
the order of conversion (same as DMA Register Indirect Addressing with Post-Increment mode).
As mentioned earlier, user must pay special attention to the number of LSbs that are reserved
for the peripheral when the DMAxSTA and DMAxSTB registers are initialized by the user
application. For the ADC, the number of bits will depend on the size and number of the ADC
buffers.
The number of ADC buffers is initialized with the Increment Rate for the
SMPI<3:0> bits (ADCxCON2<5:2>). The size of each ADC buffer is initialized with the
DMABL<2:0> bits (ADCxCON4<2:0>). For example, if the SMPI<3:0> bits are initialized to 3
and the DMABL<2:0> bits are initialized to 3, there will be four ADC buffers (SMPI<3:0> + 1),
each with eight words (2DMABL<2:0>), for the total of 32 words (64 bytes). This means that the
address offset that is written into the DMAxSTA and DMAxSTB must have 6 (26 bits = 64 bytes)
LSbs set to zero.
If the MPLAB C30 compiler is used to initialized the DMAxSTA and DMAxSTAB registers, proper
data alignment must be specified through data attributes. For the above conditions, the code
shown in Example 38-6 will initialize the DMAxSTA and DMAxSTB registers.
DMA0STA = __builtin_dmaoffset(BufferA);
DMA0STB = __builtin_dmaoffset(BufferB);
Example 38-7: Code for ADC and DMA with Peripheral Indirect Addressing
38
Set up ADC1 for channel 0-3 sampling:
Direct Memory
Access (DMA)
AD1CON1bits.FORM = 3; // Data Output Format: Signed Fraction (Q15 format)
AD1CON1bits.SSRC = 2; // Sample Clock Source: GP Timer starts conversion
(Part III)
AD1CON1bits.ASAM = 1; // Sampling begins immediately after
conversion
AD1CON1bits.AD12B = 0; // 10-bit ADC operation
AD1CON1bits.SIMSAM = 0; // Samples multiple channels sequentially
AD1CON2bits.BUFM = 0;
AD1CON2bits.CSCNA = 1; // Scan CH0+ Input Selections during Sample A
bit
AD1CON2bits.CHPS = 0; // Converts CH0
Example 38-7: Code for ADC and DMA with Peripheral Indirect Addressing (Continued)
Set up DMA Channel 5 for Peripheral Indirect Addressing:
int BufferA[4][8] __attribute__((space(dma), aligned(64)));
BufferB[4][8] __attribute__((space(dma), aligned(64)));
int
DMA5CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode
DMA5CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
DMA5PAD = (volatile unsigned int)&ADC1BUF0;// Point DMA to ADC1BUF0
DMA5CNT = 31; // 32 DMA request (4 buffers, each with 8 words)
DMA5REQ = 13; // Select ADC1 as DMA Request source
DMA5STA = __builtin_dmaoffset(BufferA);
DMA5STB = __builtin_dmaoffset(BufferB);
DmaBuffer ^= 1;
Figure 38-13: Data Transfer from ECAN™ with Peripheral Indirect Addressing
Peripheral Indirect Address
fer 9
Buffer 0: SID &_DMA_BASE
Data Trans Buffer 0: EID
DMA :
RX Channel : Buffer 0
ECAN
0 :
Tra
ns :
fer :
1 6
DMA :
Request 38
Tra
n
s fe
Buffer 1
r1
Direct Memory
Access (DMA)
Tra
(Part III)
nsfe
Buffer 2: SID
r
Buffer 2: EID
8
:
: Buffer 2
:
;
:
:
As mentioned earlier, you must pay special attention to the number of LSbs that are reserved for
the peripheral when the DMAxSTA and DMAxSTB registers are initialized by the user application
and the DMA is operating in Peripheral Indirect Addressing mode. For the ECAN module, the
number of bits depends on the number of ECAN buffers defined by the DMA Buffer Size
bits (DMABS<2:0>) in the ECAN FIFO Control register (CiFCTRL<15:13>).
For example, if the ECAN module reserves 12 buffers by setting DMABS<2:0> bits to ‘3’,
there will be 12 buffers with 8 words each, for a total of 96 words (192 bytes). This means
that the address offset that is written into the DMAxSTA and DMAxSTB registers must
have 8 LSbs (28 bits = 256 bytes) set to ‘0’. If the MPLAB C30 compiler is used to initialize
the DMAxSTA register, proper data alignment must be specified through data attributes. For
this example, the code in Example 38-8 properly initializes the DMAxSTA register.
DMA0STA = __builtin_dmaoffset(&BufferA[0][0]);
Example 38-9: Code for ECAN™ and DMA with Peripheral Indirect Addressing
Set up ECAN1 with two filters:
/* Initialize ECAN clock first. See ECAN section for example code */
C1CTRL1bits.WIN = 0;
C1TR01CONbits.TXEN0 = 0; // Buffer 0 is a receive buffer
C1TR23CONbits.TXEN2 = 0; // Buffer 2 is a receive buffer
Figure 38-14: Data Transfer from ECAN™ with Register Indirect Addressing
A Receive Buffer 2
RX DMA : DMA TX
an
Direct Memory
ECAN 1 ECAN 1
Access (DMA)
Channel : Channel
sfe
0 : 1
r9
DMA
(Part III)
DMA :
r8
Request
: sfe Request
an
: Tr
Buffer 0: SID
Tra
Buffer 0: EID
n
:
sfe
: Buffer 0
r1
:
6
:
:
:
C Transmit Buffer 0
&_DMA_BASE
&_DMA_BASE+DMAxSTA Transfer #1
Transfer #2
COUNT++
Transfer #3
If the HALF bit (DMAxCON<12>) is set, the DMAxIF bit is set (and the DMA interrupt is
generated, if enabled by the application program) when half of the data block transfer is complete
and the channel remains enabled. When the full block transfer is complete, no interrupt flag is
set and the channel is automatically disabled. For information on how to set up the DMA channel
to interrupt on both half and full block transfer, refer to 38.6.3 “Full or Half Block Transfer
Interrupts”.
If the channel is re-enabled by setting the CHEN bit (DMAxCON<15>) to ‘1’, the block transfer
takes place from the start address, as provided by the DMAxSTA and DMAxSTB registers.
Example 38-10 illustrates the code for One-Shot operation.
Example 38-10: Code for UART and DMA with One-Shot Mode
Set up UART for RX and TX:
#define FCY 40000000
#define BAUDRATE 9600
#define BRGVAL ((FCY/BAUDRATE)/16)-1
Example 38-10: Code for UART and DMA with One-Shot Mode (Continued)
Set up DMA Channel 0 to Transmit in One-Shot, Single-Buffer mode:
unsigned int BufferA[8] __attribute__((space(dma)));
unsigned int BufferB[8] __attribute__((space(dma)));
Direct Memory
Access (DMA)
Set up DMA Interrupt Handlers:
(Part III)
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
{
IFS0bits.DMA0IF = 0; // Clear the DMA0 Interrupt Flag;
}
if(BufferCount == 0)
{
DMA0STA = __builtin_dmaoffset(BufferA); // Point DMA 0 to data
// to be transmitted
}
else
{
DMA0STA = __builtin_dmaoffset(BufferB); // Point DMA 0 to data
// to be transmitted
}
BufferCount ^= 1;
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag
}
&_DMA_BASE
&_DMA_BASE+DMAxSTA Transfer #1
Transfer #2
COUNT++
Transfer #3
COUNT=0
Transfer #n Count = DMAxCNT+1
If the HALF bit (DMAxCON<12>) is set, the DMAxIF is set (and DMA interrupt is generated, if
enabled) when half of the data block transfer is complete. The channel remains enabled. When
the full block transfer is complete, no interrupt flag is set and the channel remains enabled. For
more information on how to set up the DMA channel to interrupt on both half and full block
transfer, refer to 38.6.3 “Full or Half Block Transfer Interrupts”.
&_DMA_BASE
&_DMA_BASE+DMAxSTA Transfer #1
Transfer #2
COUNT++
Transfer #3 Buffer A (Primary)
COUNT = 0
COUNT++
Transfer #3 Buffer B (Secondary)
38
CPU Block Transfer Complete IRQ
Direct Memory
Access (DMA)
(Part III)
Example 38-11: Code for DCI and DMA with Continuous Ping-Pong Operation
Set up DCI for RX and TX:
#define FCY 40000000
#define FS 48000
#define FCSCK 64*FS
#define BCGVAL (FCY/(2*FS))-1
Example 38-11: Code for DCI and DMA with Continuous Ping-Pong Operation
(Continued)
DMA0PAD = (volatile unsigned int) &TXBUF0;
DMA0STA = __builtin_dmaoffset(TxBufferA);
DMA0STB = __builtin_dmaoffset(TxBufferB);
if(BufferCount == 0)
{
/* Notify application that TxBufferA has been transmitted */
}
else
{
/* Notify application that TxBufferB has been transmitted */
}
BufferCount ^= 1;
IFS0bits.DMA0IF = 0; // Clear the DMA0 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA1Interrupt(void)
{
static unsigned int RxBufferCount = 0; // Keep record of which buffer
// has Rx Data
if(BufferCount == 0)
{
/* Notify application that RxBufferA has been received */
}
else
{
/* Notify application that RxBufferB has been received */ }
BufferCount ^= 1;
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag
}
Enable DCI:
/* Force First two words to fill-in Tx buffer/shift register */
DMA0REQbits.FORCE = 1;
while(DMA0REQbits.FORCE == 1);
DMA0REQbits.FORCE = 1;
while(DMA0REQbits.FORCE == 1);
If One-Shot mode is selected while the DMA controller is operating in Ping-Pong mode, the DMA
responds by reinitializing to point to the secondary buffer after transferring primary buffer and
then transfers the secondary buffer. Subsequent block transfers will not occur, however, because
the DMA channel disables itself. Figure 38-18 illustrates One-Shot data transfer in Ping-Pong
mode.
&_DMA_BASE
&_DMA_BASE+DMAxSTA Transfer #1
Transfer #2
COUNT++
Transfer #3 Buffer A (Primary)
COUNT=0
COUNT++
Transfer #3 Buffer B (Secondary)
Direct Memory
Access (DMA)
Transfer #n COUNT = DMAxCNT+1
(Part III)
CPU Block Transfer Complete IRQ
Disable DMA Channel
CPU Write to
FORCE Bit
&_DMA_BASE
Peripheral DMA Transfe
1 Channel 6 r 1
Data 0 &_DMA_BASE + DMA3STA
Data 1 &_DMA_BASE + DMA3STA + 1
Data 2 &_DMA_BASE + DMA3STA + 2
DMA Request
&_DMA_BASE
Peripheral DMA Tra
n sf
1 Channel 6 Tra er 2
nsf Data 0 &_DMA_BASE + DMA3STA
er &_DMA_BASE + DMA3STA + 1
3 Data 1
Data 2 &_DMA_BASE + DMA3STA + 2
Direct Memory
Access (DMA)
adjustment, which must be taken into account. Example 38-12 demonstrates the code SPI and
DMA with Null Data Write mode.
(Part III)
Figure 38-20: Data Transfer with Null Data Write Mode
Null Data Writes
generated by DMA
&_DMA_BASE
Tra
TX DMA ns
SPI Tra fer 1
Channel 1 n sf
RX Tra er 2 Data 0 &_DMA_BASE + DMA3STA
n sf
er Data 1 &_DMA_BASE + DMA3STA + 1
3
Data 2 &_DMA_BASE + DMA3STA + 2
Data Transfer
Example 38-12: SPI and DMA with Null Data Write Mode
Set up SPI for Master mode:
SPI1CON1bits.MODE16 = 1; //Communication is word-wide (16 bits)
SPI1CON1bits.MSTEN = 1; //Master Mode Enabled
SPI1STATbits.SPIEN = 1; //Enable SPI Module
DMA1STA = __builtin_dmaoffset(BufferA);
DMA1STB = __builtin_dmaoffset(BufferB);
DMA1PAD = (volatile unsigned int) &SPI1BUF;
IFS0bits.DMA1IF = 0;
IEC0bits.DMA1IE = 1; // Enable DMA interrupt
DMA1CONbits.CHEN = 1; // Enable DMA Channel
if(BufferCount == 0)
{
ProcessRxData(BufferA); // Process received SPI data in
// DMA RAM Primary buffer
}
else
{
ProcessRxData(BufferB); // Process received SPI data in
// DMA RAM Secondary buffer
}
BufferCount ^= 1;
IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag
}
Direct Memory
Access (DMA)
In this configuration, no DMA request is issued until the first block of SPI data is received.
(Part III)
However, in Master mode, no data is received until the SPI transmits it. To initiate DMA
transfers, the user application must first send data using the DMA Manual Transfer mode,
or it must first write data into the SPIxBUF independently of the DMA.
• TX only in Slave mode
In this configuration, no DMA request is issued until the first block of SPI data is received.
To initiate DMA transfers, the user application must first send data using the DMA Manual
Transfer mode, or it must first write data into the SPIxBUF independently of the DMA.
• RX only in Slave mode
This configuration generates a DMA request as soon as the first SPI data has arrived, so no
special steps need to be taken by the user to initiate DMA transfer.
• RX and TX in Slave mode
In this configuration, no DMA request is issued until the first SPI data block is received. To
initiate DMA transfers, the user application must first send data utilizing DMA Manual
Transfer mode, or it must first write data into the SPIxBUF independently of the DMA.
Direct Memory
Access (DMA)
data. Subsequent incoming data is lost and the SPI Receive Overflow (SPIROV) bit is set in
(Part III)
the SPI Status register (SPIxSTAT<6>). Also the SPIx fault interrupt is generated if the SPI
Error Interrupt Enable bit (SPIxEIE) is set in the Interrupt Enable Control register (IECx), in
the Interrupt Controller module.
UART Data waiting to be moved by the DMA channel is not overwritten by additional incoming
data. Subsequent incoming data is lost and the Overflow Error bit (OERR) is set in the
UART Status register (UxSTA<1>). Also, the UARTX Error interrupt is generated if the
UART Error Interrupt Enable bit (UxEIE), is set in the IECx register in the Interrupt
Controller module.
DCI Data waiting to be moved by the DMA channel is overwritten by additional incoming data
and the Receive Overflow bit (ROV) is set in the DCI Status register (DCISTAT<1>). Also
the DCI fault interrupt is generated if the DCI Error Interrupt Enable bit, DCIEIE (IEC3<11>),
is set in the Interrupt Controller module.
10-bit/12-bit ADC Data waiting to be moved by the DMA channel is overwritten by additional incoming data.
The overrun condition is not detected by the ADC.
Other DMA-Ready No data overrun can occur.
Peripherals
Data overruns are only detectable in hardware when the DMA controller is moving data from a
peripheral to DPSRAM. DMA data transfers from DPSRAM to a peripheral (based on, for
example, a buffer empty interrupt) will always execute. Any consequential DPSRAM data
overruns must be detected using software. The duplicate DMA request is ignored and the
pending request remains pending. As usual, the DMA channel clears the DMA request when the
transfer is eventually completed. If the CPU does not intervene in the meantime, the data
transferred will be the latest (overrun) data, and the prior data will be lost.
The user application can handle an overrun error in different ways, depending on the nature of
the data source. Data recovery and resynchronization of the DMAC with its data source/sink is a
task that is highly application dependent. For streaming data, such as that from a CODEC
(through the DCI peripheral), the application can ignore the lost data. After fixing the source of
the problem (if possible), the DMA interrupt handler should attempt to resynchronize the DMAC
and DCI so that data is again buffered correctly. The user application should react fast enough
to prevent any further overruns occurring.
By the time the peripheral overrun interrupt is entered, the pending DMA request will have
already moved the overrun data value to the address where the lost data should have gone. That
data can be moved to its correct address, and a null data value inserted into the missing data
slot. The DPSRAM address of the channel can then be adjusted accordingly. Subsequent DMA
requests to the faulted channel then initiate transfers as normal to the corrected DPSRAM
address. For applications where the data cannot be lost, the peripheral overrun interrupt will need
to abort the current block transfer, reinitialize the DMA channel and request a data resend before
it is lost.
Direct Memory
Access (DMA)
flags are automatically cleared when the user application clears the DMAC Error Status
(Part III)
bit (DMACERR) in the Interrupt Controller register (INTCON1<5>).
Subsequent DMA requests to a channel that has a write collision error are ignored while the
XWCOLx or PWCOLx remain set.
Under write collision conditions, either XWCOLx or PWCOLx could be set due to write collision,
but not both. Setting both flags is used as a unique means to flag a rare manual trigger event
error without adding more status bits (see 38.6.10 “Manual Transfer Mode”).
Example 38-13 illustrates DMA controller trap handling with DMA Channel 0 transferring data
from the DPSRAM to the peripheral (UART), and DMA Channel 1 transferring data from the
peripheral (ADC) to the DPSRAM.
A summary of the registers associated with the DMA controller is provided in Table 38-6.
Table 38-6: DMA-Associated Register Map
All
File Name Bit 15 Bit 14 Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Resets
DMA0CON CHEN SIZE DIR HALF NULLW — — — — — AMODE<1:0> — — MODE<1:0> 0000
DMA0REQ FORCE — — — — — — — — IRQSEL<6:0> 0000
DMA0STA STA<15:0> 0000
0000
DMA5STB STB<15:0> 0000
DMA5PAD PAD<15:0> 0000
DMA5CNT — — — — — — CNT<9:0> 0000
DMA6CON CHEN SIZE DIR HALF NULLW — — — — — AMODE<1:0> — — MODE<1:0> 0000
DMA6REQ FORCE — — — — — — — — IRQSEL<6:0> 0000
Legend: x = unknown value on Reset, — = unimplemented, read as ‘0’. Reset values are shown in hexadecimal.
Note: Not all bits are available on all devices. Refer to the specific device data sheet for availability.
(Part III)
Access (DMA)
38
Direct Memory
DS70215C-page 38-52
Note: Please visit the Microchip web site (www.microchip.com) for additional Application
Notes and code examples for the dsPIC33F/PIC24H family of devices.
38
Direct Memory
Access (DMA)
(Part III)
• Microchip believes that its family of products is one of the most secure families of its kind on the market today, when used in the
intended manner and under normal conditions.
• There are dishonest and possibly illegal methods used to breach the code protection feature. All of these methods, to our
knowledge, require using the Microchip products in a manner outside the operating specifications contained in Microchip’s Data
Sheets. Most likely, the person doing so is engaged in theft of intellectual property.
• Microchip is willing to work with the customer who is concerned about the integrity of their code.
• Neither Microchip nor any other semiconductor manufacturer can guarantee the security of their code. Code protection does not
mean that we are guaranteeing the product as “unbreakable.”
Code protection is constantly evolving. We at Microchip are committed to continuously improving the code protection features of our
products. Attempts to break Microchip’s code protection feature may be a violation of the Digital Millennium Copyright Act. If such acts
allow unauthorized access to your software or other copyrighted work, you may have a right to sue for relief under that Act.
ISBN: 978-1-62076-274-5