ADC with DMA FIFO issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ADC with DMA FIFO issue

Jump to solution
391 Views
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?

 

Labels (1)
0 Kudos
Reply
1 Solution
372 Views
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*);

 

View solution in original post

0 Kudos
Reply
1 Reply
373 Views
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 Kudos
Reply