13.5.2 Source Descriptor Table (SDT)

The Source Descriptor Table can be enabled independently by setting the DMAxCH.SDTEN bit high. With DMAxSRC.SADDR[23:0] preloaded with the Source Descriptor Table’s base address (first DP) by the application, the DMA module is ready for its source descriptor-based operation.

The code below is an example of a source descriptor. The descriptor table is created using a structure with padding, as shown. An example is shown in the table below.

Table 13-11. Source Descriptor Example
OffsetIfMatch (7 bits)OffsetNoMatch (7 bits)Size (2 bits)Payload Pointer (16 bits)
320x2DMA_Src1
-130x2DMA_Src2
-110x2DMA_Src3
310x2DMA_Src4
-310x2DMA_Src4

The DMA begins by reading from the payload pointer (e.g., DMA_Src1) after the source pointer is set to the starting address of the first descriptor (DMA_SrcPtr[0]) and SDTEN 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)))= 0xa1a2a3a4;
uint32_t DMA_Src3 __attribute((address(0x5008)))= 0xb2b2b2b2; 
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;    
}Src_DP;


Src_DP DMA_SrcPtr[5] __attribute__((address(0x5500)));

int main(void)
{
    //row 1
    DMA_SrcPtr[0].PayloadPointer = (uint16_t)&DMA_Src1;
    DMA_SrcPtr[0].Size = 0x2;
    DMA_SrcPtr[0].OffsetNoMatch = 2;
    DMA_SrcPtr[0].OffsetIfMatch =  3;     
    //row 2   
    DMA_SrcPtr[1].PayloadPointer = (uint16_t)&DMA_Src2;
    DMA_SrcPtr[1].Size = 0x2;
    DMA_SrcPtr[1].OffsetNoMatch = 3;
    DMA_SrcPtr[1].OffsetIfMatch = -1;
    //row 3   
    DMA_SrcPtr[2].PayloadPointer = (uint16_t)&DMA_Src3;
    DMA_SrcPtr[2].Size = 0x2;
    DMA_SrcPtr[2].OffsetNoMatch = 1;
    DMA_SrcPtr[2].OffsetIfMatch = -1;
    //row 4   
    DMA_SrcPtr[3].PayloadPointer = (uint16_t)&DMA_Src4;
    DMA_SrcPtr[3].Size = 0x2;
    DMA_SrcPtr[3].OffsetNoMatch = 1;
    DMA_SrcPtr[3].OffsetIfMatch = 3;
   //row 5
    DMA_SrcPtr[4].PayloadPointer = (uint16_t)&DMA_Src5;
    DMA_SrcPtr[4].Size = 0x2;
    DMA_SrcPtr[4].OffsetNoMatch = 1;
    DMA_SrcPtr[4].OffsetIfMatch = -3;
    
 
    DMACONbits.ON = 0;
    DMA0CH = 0;
    DMAHIGH = 0xFFFFFF;     //Sets the DMA High limit Address 
    DMALOW = 0x4000;           //Sets the DMA Low Limit Address
    //Source Descriptor Enable
    DMA0CHbits.SDTEN = 1;
    
    DMA0PAT = 0xb2b2b2b2;             //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 = 0;         //Source address mode unchanged 
    DMA0CHbits.DAMODE = 1;       //Destination addr mode increment
    DMA0CHbits.TRMODE = 1;         //Repeated One-Shot Mode
    DMA0CHbits.SIZE = 2;                 //Transfer size of 32-bit
    
    DMA0SRC = (uint32_t)&DMA_SrcPtr[0];    //Sets source address as first Descriptor (DMA_SrcPtr[0]) 
    DMA0DST = (uint32_t)&DMA_Dst[0];          //Sets destination address
    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;
}