13.5.3 Destination Descriptor Table (DDT)
The Destination Descriptor Table can be enabled independently by setting the DMAxCH.DDTEN bit high. With DMAxSRC.DADDR[23:0] preloaded with the Destination Descriptor Table’s base address (first DP) by the application, the DMA module is ready for its destination descriptor-based operation.
The following code is an example of a destination descriptor. The descriptor table is created using a structure with padding, as shown. An example is provided below.
| OffsetIfMatch (7 bits) | OffsetNoMatch (7 bits) | Size (2 bits) | Payload Pointer (16 bits) |
|---|---|---|---|
| 3 | 2 | 0x2 | DMA_Dst[0] |
| -1 | 3 | 0x2 | DMA_Dst[1] |
| -1 | 1 | 0x2 | DMA_Dst[2] |
| 3 | 1 | 0x2 | DMA_Dst[3] |
| -3 | 1 | 0x2 | DMA_Dst[4] |
The DMA begins by reading from the payload point (e.g., DMA_Dst[0]) after the destination
pointer is set to the starting address of the first descriptor (DMA_DestPtr[0]) and
DDTEN is enabled. Following this transaction, the DMA checks if pattern matching is
active (MATEN = 1). If a match is detected, it uses the OffsetIfMatch
value to move to the next descriptor. If no match is found, the OffsetNoMatch value is
used instead.
#include <xc.h>
#include<stdlib.h>
#include<stdint.h>
//Source address for DMA
uint32_t DMA_Src1 __attribute((address(0x5000)))= 0xa1a2a3a4;
uint32_t DMA_Src2 __attribute((address(0x5004)))= 0xc1c1c1c1;
uint32_t DMA_Src3 __attribute((address(0x5008)))= 0xa1a2a3a4;
uint32_t DMA_Src4 __attribute((address(0x500C)))= 0xb2b2b2b2;
uint32_t DMA_Src5 __attribute((address(0x5010)))= 0xa1a2a3a4;
//Dest Address for DMA
uint32_t DMA_Dst[5] __attribute((address(0x4500)))= {0};
typedef struct DescriptorTable
{
uint32_t PayloadPointer:16;
uint32_t Size:2;
int32_t OffsetNoMatch:7;
int32_t OffsetIfMatch:7;
}Dest_DP;
Dest_DP DMA_DestPtr[5] __attribute__((address(0x5500)));
int main(void)
{
//row 1
DMA_DestPtr[0].PayloadPointer = (uint16_t)&DMA_Dst[0];
DMA_DestPtr[0].Size = 0x2;
DMA_DestPtr[0].OffsetNoMatch = 2;
DMA_DestPtr[0].OffsetIfMatch = 3;
//row 2
DMA_DestPtr[1].PayloadPointer = (uint16_t)&DMA_Dst[1];
DMA_DestPtr[1].Size = 0x2;
DMA_DestPtr[1].OffsetNoMatch = 3;
DMA_DestPtr[1].OffsetIfMatch = -1;
//row 3
DMA_DestPtr[2].PayloadPointer = (uint16_t)&DMA_Dst[2];
DMA_DestPtr[2].Size = 0x2;
DMA_DestPtr[2].OffsetNoMatch = 1;
DMA_DestPtr[2].OffsetIfMatch = -1;
//row 4
DMA_DestPtr[3].PayloadPointer = (uint16_t)&DMA_Dst[3];
DMA_DestPtr[3].Size = 0x2;
DMA_DestPtr[3].OffsetNoMatch = 1;
DMA_DestPtr[3].OffsetIfMatch = 3;
//row 5
DMA_DestPtr[4].PayloadPointer = (uint16_t)&DMA_Dst[4];
DMA_DestPtr[4].Size = 0x2;
DMA_DestPtr[4].OffsetNoMatch = 1;
DMA_DestPtr[4].OffsetIfMatch = -3;
DMACONbits.ON = 0;
DMA0CH = 0;
DMAHIGH = 0xFFFFFF; //Sets the DMA High limit Address
DMALOW = 0x4000; //Sets the DMA Low Limit Address
//Destination Descriptor Enable
DMA0CHbits.DDTEN = 1;
DMA0PAT = 0xc1c1c1c1; //Configures the pattern register for pattern match
DMA0MSK = 0xFFFFFFFF; //Configures the pattern mask register for pattern match
DMA0CHbits.MATEN = 1; //Enables Pattern match
DMA0CHbits.SAMODE = 1; //Source address mode increment
DMA0CHbits.DAMODE = 0; //Destination address mode unchanged
DMA0CHbits.TRMODE = 1; //Repeated One-Shot Mode
DMA0CHbits.SIZE = 2; //Transfer size of 32-bit
DMA0SRC = (uint32_t)&DMA_Src1; //Sets Source address
DMA0DST = (uint32_t)&DMA_DestPtr[0]; //Sets destination address as first Descriptor (DMA_DestPtr[0])
DMA0CNT = 4; //count value of 4
DMA0CHbits.CHEN = 1; //Enables channel
DMACONbits.ON = 1; //Enables DMA module
//First Trigger (No match)
DMA0CHbits.CHREQ = 1;
while(DMA0CHbits.CHREQ == 1);
//Second Trigger (Match))
DMA0CHbits.CHREQ = 1;
while(DMA0CHbits.CHREQ == 1);
//Third Trigger (No match))
DMA0CHbits.CHREQ = 1;
while(DMA0CHbits.CHREQ == 1);
while(1);
return 1;
}
