Hello,
I have DMA set up to move data from the HSADC FIFO to memory. This seems to work correctly, however there is some unexpected behavior.
The number of samples transferred is far larger than the 16 words expected. From my understanding, the DMA transfer is initiated when the HSADC FIFO_FULL flag is set. I have set the FIFIO fill level to 15. So after 15 samples, the DMA should trigger and move 16 samples out of the FIFO and into the destination address.
In the DMA handler, I reset the channel to get it ready for another transfer. From my understanding, the next time the DMA transfer occurs, the destination address should be the same (eg: dest[0]), however, it seems as though the destination address is the next address after the last transfer (eg: dest[16]).
This results in the DMA filling up memory incredibly rapidly.
What is going on here?
void DMA_IRQHandler(void)
{
Chip_GPDMA_Interrupt(LPC_GPDMA, dmaCh); //clears it
LPC_GPDMA->CH[dmaCh].SRCADDR = (uint32_t) &LPC_ADCHS->FIFO_OUTPUT[0];
LPC_GPDMA->CH[dmaCh].DESTADDR = ((uint32_t) &dest[0]);
LPC_GPDMA->CH[dmaCh].CONFIG |= 1;
}
void adchs_dma_setup(void)
{
Chip_GPDMA_Init(LPC_GPDMA);
dmaCh = Chip_GPDMA_GetFreeChannel(LPC_GPDMA, GPDMA_CONN_ADCHS_READ);
Chip_GPDMA_Transfer(LPC_GPDMA, dmaCh,
GPDMA_CONN_ADCHS_READ, (uint32_t) &dest[0],
GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL,
NULL);
/* Enable GPDMA interrupt */
NVIC_SetPriority(DMA_IRQn, 0);
NVIC_ClearPendingIRQ(DMA_IRQn);
NVIC_EnableIRQ(DMA_IRQn);
}
void adchs_setup(void)
{
Chip_HSADC_Init(LPC_ADCHS);
Chip_HSADC_SetupFIFO(LPC_ADCHS, 15, false);
Chip_HSADC_ConfigureTrigger(LPC_ADCHS, HSADC_CONFIG_TRIGGER_SW,
HSADC_CONFIG_TRIGGER_RISEEXT, HSADC_CONFIG_TRIGGER_NOEXTSYNC,
HSADC_CHANNEL_ID_EN_NONE, 0x90);
Chip_HSADC_SetACDCBias(LPC_ADCHS, 0, HSADC_CHANNEL_DCBIAS, HSADC_CHANNEL_NODCBIAS);
Chip_HSADC_SetPowerSpeed(LPC_ADCHS, false);
Chip_HSADC_EnablePower(LPC_ADCHS);
Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 0, (HSADC_DESC_CH(0) | HSADC_DESC_BRANCH_FIRST | HSADC_DESC_MATCH(1) | HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER));
Chip_HSADC_EnableInts(LPC_ADCHS, 0, (HSADC_INT0_FIFO_FULL));
Chip_HSADC_UpdateDescTable(LPC_ADCHS, 0);
NVIC_EnableIRQ(ADCHS_IRQn);
}
Hi,
Can you refer to the ticket?
https://community.nxp.com/t5/LPC-Microcontrollers/LPC4370-DMA-Issues/m-p/1636485#M52256
For the hsadc example in LPCopen, the ADC uses software triggering, it can not reach up to 80MSPS.
Hope it can help you
BR
XiangJun Rong
Hi XiangJun,
Maybe I am confused and do not understand you, but I think you might be confused and mixing up my question. I did not say anything in this post about 80MS/s. I did not say anything in this post about problems with the HSADC.
Yes, I understand that the example uses a software trigger executed in a timer interrupt. I am NOT asking about the example, though. I am asking about my code. As you can see in the descriptor entry, I branch to FIRST. This causes the ADC to run continuously. The works correctly.
My question is about DMA. My question is:
Why does the destination address continue to increment upon a new DMA transfer? The destination address should be dest[0], however, it is greater than dest[(16*num_of_transfers)].
Why is this happening? Again, I am NOT asking about ADC functionality.
Hi,
I have checked your code, in the DMA_IRQHandler (), you reinitialize the LPC_GPDMA->CH[dmaCh].DESTADDR
with the line.
LPC_GPDMA->CH[dmaCh].DESTADDR = ((uint32_t) &dest[0]);
So, pls check if you have entered the DMA_IRQHandler ()
BR
XiangJun Rong
Hello. Checking in to see if you have any other ideas as to the cause of the behavior?
Hello,
Thank you for checking my code. Yes, I can confirm that my code enters, executes, and then exits the DMA_IRQHandler properly.