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.

Table 13-12. Destination Descriptor Example
OffsetIfMatch (7 bits)OffsetNoMatch (7 bits)Size (2 bits)Payload Pointer (16 bits)
320x2DMA_Dst[0]
-130x2DMA_Dst[1]
-110x2DMA_Dst[2]
310x2DMA_Dst[3]
-310x2DMA_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;
}