DMA is faster than the task

Hi, I’m using K66 NXP and I’m doing ADC DMA transfer, in the ADS Task I’m reading which DMA has been finished then I process the data on that. What I have noticed that the ADC DMA transfer is fasther than the Task, hence the variable that shows which DMA is finished, is never updated correctly. What’s the solution for that problem ? ~~~ while(1) { if(gedmaTransferDone[ADC0CHANNEL10EDMA0] == true) { gedmaTransferDone[ADC0CHANNEL10EDMA0] = false; bufferSelect = (adcBufferSwitch[ADC0CHANNEL10EDMA0] == 0U) ? I1LOWERREADY : I1UPPERREADY; adcBufferSwitch[ADC0CHANNEL10EDMA0] = 1U – adcBufferSwitch[ADC0CHANNEL10EDMA0]; } else if(gedmaTransferDone[ADC0CHANNEL11EDMA1] == true) { gedmaTransferDone[ADC0CHANNEL11EDMA1] = false; bufferSelect = (adcBufferSwitch[ADC0CHANNEL11EDMA1] == 0U) ? Q1LOWERREADY : Q1UPPERREADY; adcBufferSwitch[ADC0CHANNEL11EDMA1] = 1U – adcBufferSwitch[ADC0CHANNEL11EDMA1]; } else if(gedmaTransferDone[ADC1CHANNEL10EDMA2] == true) { gedmaTransferDone[ADC1CHANNEL10EDMA2] = false; bufferSelect = (adcBufferSwitch[ADC1CHANNEL10EDMA2] == 0U) ? I2LOWERREADY : I2UPPERREADY; adcBufferSwitch[ADC1CHANNEL10EDMA2] = 1U – adcBufferSwitch[ADC1CHANNEL10EDMA2]; } else if(gedmaTransferDone[ADC1CHANNEL11EDMA3] == true) { gedmaTransferDone[ADC1CHANNEL11EDMA3] = false; bufferSelect = (adcBufferSwitch[ADC1CHANNEL11EDMA3] == 0U) ? Q2LOWERREADY : Q2UPPERREADY; adcBufferSwitch[ADC1CHANNEL11EDMA3] = 1U – adcBufferSwitch[ADC1CHANNEL11EDMA3]; }
    /* send the buffer complete events via message queue */
    if(bufferSelect != BUFFERS_NOT_READY)
    {
        if(xQueueSend(g_adcQueue, &bufferSelect,  ( TickType_t ) 10) != pdPASS)
        {
            throwError(ERROR_MESSAGE_QUEUE_FULL);
            PRINTF("%srn", getErrorMessage(ERROR_MESSAGE_QUEUE_FULL));
        }
        bufferSelect = BUFFERS_NOT_READY;
    }
}
~~~

DMA is faster than the task

I’m not sure I understand your question correctly. I would expect a DMA to be fast, and don’t know what is updating the variable. If the DMA end interrupt is setting a variable and expecting the task to read it then it just sounds like a classic race/thread safety condition – the interrupt is updating the variable faster and at the same time that the task is reading it. The DMA is presumably writing the data somewhere, so why is it also updating a variable? Ideally you want to serialise access by writing to some kind of FIFO so the task reads from one end as the interrupt writes to the other – effectively buffering data that can be read out serialy rather than having two threads (an interrupt and a task in this case) accessing a single variable at the same time. Maybe a stream buffer can help – but with a DMA it should not be necessary.

DMA is faster than the task

Thanks for your valuable input. Actually I put the variables that are set by the DMA as volatile. But that didn’t help.