ADC with DMA FIFO issue

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

ADC with DMA FIFO issue

跳至解决方案
952 次查看
leannee
Contributor II

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?

 

标签 (1)
0 项奖励
回复
1 解答
933 次查看
leannee
Contributor II

Solved.

In LPC553x Reference Manual, chapter DMA Controller:

leannee_0-1711453871210.png

So in the end of DMA configuration function add this:

    DMA_DisableChannelPeriphRq(*dma_base*, *dma_channel*);

 

在原帖中查看解决方案

0 项奖励
回复
1 回复
934 次查看
leannee
Contributor II

Solved.

In LPC553x Reference Manual, chapter DMA Controller:

leannee_0-1711453871210.png

So in the end of DMA configuration function add this:

    DMA_DisableChannelPeriphRq(*dma_base*, *dma_channel*);

 

0 项奖励
回复