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.
| OffsetIfMatch (7 bits) | OffsetNoMatch (7 bits) | Size (2 bits) | Payload Pointer (16 bits) |
|---|---|---|---|
| 3 | 2 | 0x2 | DMA_Src1 |
| -1 | 3 | 0x2 | DMA_Src2 |
| -1 | 1 | 0x2 | DMA_Src3 |
| 3 | 1 | 0x2 | DMA_Src4 |
| -3 | 1 | 0x2 | DMA_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;
}
