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?
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.