Search code examples
cmemoryarmembeddedrace-condition

Enforcement of memory write before execution of later code


I am writing code that triggers a DMA. Once the DMA has completed its operation it will call ISR_Routine. The problem is that I want to ensure that the refreshComplete is set to 0 before the DMA runs. If the DMA runs first, before refreshComplete is set to 0, then it is possible for the ISR_Routine to be called first causing refreshComplete to be 0 even after the DMA has run successfully. This means that the ready() function will always return 0, blocking any further use of the DMA.

The way I have the code written now is that the refreshComplete variable is volatile and I busy wait until the the read back variable is 0 before the DMA runs like so:

volatile uint8 refreshComplete = 0u;

void trigger(void)
{
    /* Write 0 and then busy wait */
    refreshComplete = 0;
    while (refreshComplete != 0);

    /* Code to start the DMA */
    ...
}

/* ISR called once the DMA has completed its operation */
void ISR_Routine(void)
{
    refreshComplete = 1u;
}

/* Function to check the status of the DMA */
uint8 ready(void)
{
    return refreshComplete;
}

Is there a way that I can always guarantee that the code to set refreshComplete always runs before the code to setup and run the DMA?


Solution

  • This is the point where you should look at the architectural information for the processor, and the instruction set.

    You will find DMB, DSB and ISB, maybe also a few others depending on how advanced your processor is. These relate to enforcing the ordering of data transfers, and of instructions relative to oter instructions (hence DMB, ISB is a common sequence). Of course, if you use these within 'C', you need to worry about the ordering guarantees of the language too.