AnsweredAssumed Answered

LPC845, DMA : destination increment after transfer

Question asked by jo mos on Apr 11, 2019
Latest reply on Apr 12, 2019 by Alice_Yang

Hi everyone,

 

I'm trying to set the DMA to get the USART RX data when it's available.

 

So I set up the DMA for a hardware trigger, 1 byte transfer (no BURST). The source USART RX (not incremented) to a buffer I declared in the RAM (incremented), and to be reloaded with the same descriptor at the end.

 

The transfer happens and I do get the data. But when the descriptor is reloaded, I suppose that the destination address does not get incremented, thus overwriting the previous data over and over...

 

As a work around, I implemented the DMA IRQ to increment my dest address at th end of a transfer, it is now working.

 

But isn't there a way for the DMA to automatically increment the dest address over several transfers ? (I did set the DSTINC flag in the XFERCFG register, but I suppose it's only incrementing the dest address within the same transfer...)

 

Many thanks.

 

Here's my code : 

 

typedef enum _DMA_CHANNEL
{
DMA_CHANNEL_USART0_RX = 0,
DMA_CHANNEL_USART0_TX,
DMA_CHANNEL_USART1_RX,
DMA_CHANNEL_USART1_TX,
DMA_CHANNEL_USART2_RX,
DMA_CHANNEL_USART2_TX,
DMA_CHANNEL_USART3_RX,
DMA_CHANNEL_USART3_TX,
DMA_CHANNEL_USART4_RX,
DMA_CHANNEL_USART4_TX,
DMA_CHANNEL_SPI0_RX,
DMA_CHANNEL_SPI0_TX,
DMA_CHANNEL_SPI1_RX,
DMA_CHANNEL_SPI1_TX,
DMA_CHANNEL_I2C0_MST,
DMA_CHANNEL_I2C0_SLV,
DMA_CHANNEL_I2C1_MST,
DMA_CHANNEL_I2C1_SLV,
DMA_CHANNEL_I2C2_MST,
DMA_CHANNEL_I2C2_SLV,
DMA_CHANNEL_I2C3_MST,
DMA_CHANNEL_I2C3_SLV,
DMA_CHANNEL_DAC0,
DMA_CHANNEL_DAC1,
DMA_CHANNEL_CAPT1,
DMA_CHANNEL_COUNT
} T_DMA_CHANNEL;

 

typedef struct _DMA_DESCRIPTOR
{
volatile t_uint32 xfercfg; //!< Transfer configuration
t_uint8 *srcEndAddr; //!< Last source address of DMA transfer
t_uint8 *dstEndAddr; //!< Last destination address of DMA transfer
t_uint_32 *linkToNextDesc; //!< Address of next DMA descriptor in chain
} T_DMA_DESCRIPTOR;

 

__attribute__((aligned(512))) static T_DMA_DESCRIPTOR s_dma_descriptor_table[DMA_CHANNEL_COUNT] = {0};

 

t_uint8 rxBuffer[20] = { 0 };

DMA0->SRAMBASE = (t_uint32)s_dma_descriptor_table;
DMA0->CTRL = DMA_CTRL_ENABLE_MASK;
DMA0->COMMON->ENABLESET |= 1 << DMA_CHANNEL_USART0_RX;
DMA0->COMMON->INTENSET |= 1 << DMA_CHANNEL_USART0_RX;

DMA0->CHANNEL[DMA_CHANNEL_USART0_RX].CFG = 1 << DMA_CHANNEL_CFG_CHPRIORITY_SHIFT |
1 << DMA_CHANNEL_CFG_PERIPHREQEN_SHIFT |
1 << DMA_CHANNEL_CFG_HWTRIGEN_SHIFT |
1 << DMA_CHANNEL_CFG_TRIGPOL_SHIFT | 
0 << DMA_CHANNEL_CFG_TRIGTYPE_SHIFT | 
0 << DMA_CHANNEL_CFG_TRIGBURST_SHIFT |
0 << DMA_CHANNEL_CFG_BURSTPOWER_SHIFT |
1 << DMA_CHANNEL_CFG_SRCBURSTWRAP_SHIFT |
0 << DMA_CHANNEL_CFG_DSTBURSTWRAP_SHIFT;

DMA0->CHANNEL[DMA_CHANNEL_USART0_RX].XFERCFG = 1 << DMA_CHANNEL_XFERCFG_CFGVALID_SHIFT |
1 << DMA_CHANNEL_XFERCFG_RELOAD_SHIFT |
0 << DMA_CHANNEL_XFERCFG_SWTRIG_SHIFT |
0 << DMA_CHANNEL_XFERCFG_CLRTRIG_SHIFT |
1 << DMA_CHANNEL_XFERCFG_SETINTA_SHIFT |
0 << DMA_CHANNEL_XFERCFG_SETINTB_SHIFT |
0 << DMA_CHANNEL_XFERCFG_WIDTH_SHIFT |
0 << DMA_CHANNEL_XFERCFG_SRCINC_SHIFT |
1 << DMA_CHANNEL_XFERCFG_DSTINC_SHIFT |
0 << DMA_CHANNEL_XFERCFG_XFERCOUNT_SHIFT;

// Setup Descriptor
s_dma_descriptor_table[DMA_CHANNEL_USART0_RX].xfercfg = DMA0->CHANNEL[DMA_CHANNEL_USART0_RX].XFERCFG;
s_dma_descriptor_table[DMA_CHANNEL_USART0_RX].srcEndAddr = (t_uint8 *) &USART0->RXDAT;
s_dma_descriptor_table[DMA_CHANNEL_USART0_RX].dstEndAddr = rxBuffer;
s_dma_descriptor_table[DMA_CHANNEL_USART0_RX].linkToNextDesc = (t_uint32*) &s_dma_descriptor_table[DMA_CHANNEL_USART0_RX].xfercfg;

INPUTMUX->DMA_ITRIG_INMUX[DMA_CHANNEL_USART0_RX] = 0x9;

 

// The IRQ workaround solution that I tried

void DMA_IRQ_handler( void )
{
s_dma_descriptor_table[DMA_CHANNEL_USART0_RX].dstEndAddr++;
}

Outcomes