MCU: LPC5536. Board: custom.
I am trying to read ADC measurements with DMA. However, on the first run, only 3 out of 9 values are "grabbed" by DMA, which results in DMA transfer done callback getting called only after the second ADC trigger.
Here is how it looks. ADC0 is 10 channels, ADC1 is 9 channels. Watermarks FIFO0 are 9 and 8 respectively. DMA0 channels are 21 for ADC0 and 27 for ADC1.
ADC clocks are 24 MHz.
Reading procedure:
// On the first run:
void ReadAllChannels()
{
uint32_t testFifoAdc0 = LPADC_GetConvResultCount(ADC0, 0U); // = 0
LPADC_DoSoftwareTrigger(LPADC_ADC0, 1U);
testFifoAdc0 = LPADC_GetConvResultCount(ADC0, 0U); // = 10
DMA_DoChannelSoftwareTrigger(ADC_DMA_BASE, DMA_ADC0_CHANNEL);
testFifoAdc0 = LPADC_GetConvResultCount(ADC0, 0U); // = 7!!!
uint32_t testFifoAdc1 = LPADC_GetConvResultCount(ADC1, 0U); // =0
LPADC_DoSoftwareTrigger(LPADC_ADC1, 1U);
testFifoAdc1 = LPADC_GetConvResultCount(ADC1, 0U); // = 9
DMA_DoChannelSoftwareTrigger(ADC_DMA_BASE, DMA_ADC1_CHANNEL);
testFifoAdc1 = LPADC_GetConvResultCount(ADC1, 0U); // = 6!!!
}
// On the SECOND and consecutive runs:
void ReadAllChannels()
{
uint32_t testFifoAdc0 = LPADC_GetConvResultCount(ADC0, 0U); // = 7
LPADC_DoSoftwareTrigger(LPADC_ADC0, 1U);
// here ADC0 DMA callback fires...
testFifoAdc0 = LPADC_GetConvResultCount(ADC0, 0U); // = 10
DMA_DoChannelSoftwareTrigger(ADC_DMA_BASE, DMA_ADC0_CHANNEL);
testFifoAdc0 = LPADC_GetConvResultCount(ADC0, 0U); // still = 7!!!
uint32_t testFifoAdc1 = LPADC_GetConvResultCount(ADC1, 0U); // =6
LPADC_DoSoftwareTrigger(LPADC_ADC1, 1U);
// here ADC1 Dma callback fires...
testFifoAdc1 = LPADC_GetConvResultCount(ADC1, 0U); // = 9
DMA_DoChannelSoftwareTrigger(ADC_DMA_BASE, DMA_ADC1_CHANNEL);
testFifoAdc1 = LPADC_GetConvResultCount(ADC1, 0U); // = 6!!!
}
DMA configs:
#define LPADC0_RESFIFO_REG_ADDR (uint32_t)(&(ADC0->RESFIFO[0]))
static DMA_ALLOCATE_LINK_DESCRIPTORS(adc0DmaDesc, 1);
uint32_t adc0ConvResults[10];
static void DMA_ADC0_Configuration()
{
dma_channel_config_t dmaChannelConfigStruct;
DMA_EnableChannel(ADC_DMA_BASE, DMA_ADC0_CHANNEL);
DMA_CreateHandle(&dmaAdc0HandleStruct, ADC_DMA_BASE, DMA_ADC0_CHANNEL);
DMA_SetCallback(&dmaAdc0HandleStruct, ADC0_DMA_Callback, NULL);
uint32_t g_XferConfig = DMA_CHANNEL_XFER(true,
true,
true,
false,
sizeof(uint32_t),
kDMA_AddressInterleave0xWidth,
kDMA_AddressInterleave1xWidth,
10* sizeof(uint32_t)
);
DMA_PrepareChannelTransfer(&dmaChannelConfigStruct,
(void *)LPADC0_RESFIFO_REG_ADDR,
(void*)adc0ConvResults,
g_XferConfig,
ADC_DMA_TRANSFER_TYPE, // peripheral to memory
NULL,
(dma_descriptor_t *)&(adc0DmaDesc[0])
);
DMA_SetupDescriptor(
(dma_descriptor_t *)&(adc0DmaDesc[0]),
g_XferConfig,
(void *)LPADC0_RESFIFO_REG_ADDR,
(void*)adc0ConvResults,
(dma_descriptor_t *)&(adc0DmaDesc[0]));
DMA_SubmitChannelTransfer(&dmaAdc0HandleStruct, &dmaChannelConfigStruct);
DMA_SetChannelConfigValid(ADC_DMA_BASE, DMA_ADC0_CHANNEL);
}
#define LPADC1_RESFIFO_REG_ADDR (uint32_t)(&(ADC1->RESFIFO[0]))
static DMA_ALLOCATE_LINK_DESCRIPTORS(adc1DmaDesc, 1);
uint32_t adc1ConvResults[9];
static void DMA_ADC1_Configuration()
{
dma_channel_config_t dmaChannelConfigStruct;
DMA_EnableChannel(ADC_DMA_BASE, DMA_ADC1_CHANNEL);
DMA_CreateHandle(&dmaAdc1HandleStruct, ADC_DMA_BASE, DMA_ADC1_CHANNEL);
DMA_SetCallback(&dmaAdc1HandleStruct, ADC1_DMA_Callback, NULL);
uint32_t g_XferConfig = DMA_CHANNEL_XFER(true,
true,
true,
false,
sizeof(uint32_t),
kDMA_AddressInterleave0xWidth,
kDMA_AddressInterleave1xWidth,
9* sizeof(uint32_t)
);
DMA_PrepareChannelTransfer(&dmaChannelConfigStruct,
(void *)LPADC1_RESFIFO_REG_ADDR,
(void*)adc1ConvResults,
g_XferConfig,
ADC_DMA_TRANSFER_TYPE,
NULL,
(dma_descriptor_t *)&(adc1DmaDesc[0])
);
DMA_SetupDescriptor(
(dma_descriptor_t *)&(adc1DmaDesc[0]),
g_XferConfig,
(void *)LPADC1_RESFIFO_REG_ADDR,
(void*)adc1ConvResults,
(dma_descriptor_t *)&(adc1DmaDesc[0]));
DMA_SubmitChannelTransfer(&dmaAdc1HandleStruct, &dmaChannelConfigStruct);
DMA_SetChannelConfigValid(ADC_DMA_BASE, DMA_ADC1_CHANNEL);
}
ADC channels for both ADC peripherals are configured to send conv values to FIFO0.
I have seen this post, they report a similar behaviour https://community.nxp.com/t5/LPC-Microcontrollers/Using-Configtools-to-set-up-ADC-and-DMA-from-scrat...
What can I do?
Solved! Go to Solution.
Solved.
In LPC553x Reference Manual, chapter DMA Controller:
So in the end of DMA configuration function add this:
DMA_DisableChannelPeriphRq(*dma_base*, *dma_channel*);
Solved.
In LPC553x Reference Manual, chapter DMA Controller:
So in the end of DMA configuration function add this:
DMA_DisableChannelPeriphRq(*dma_base*, *dma_channel*);