-2

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?

Stefan Bossbaly
  • 6,682
  • 9
  • 53
  • 82

1 Answers1

2

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.

Sean Houlihane
  • 1,698
  • 16
  • 22
  • Although the reference to the barrier instructions is potentially relevant, in this context they're not needed I don't think. A guarantee that the write in `ISR_Routine()` will complete before the next read in `ready()` takes place is unnecessary when the code is just busy-waiting anyway. It'll pick it up on the next try! `volatile` does everything necessary here. – cooperised Sep 03 '18 at 10:43
  • I think it depends if you are answering the end goal, or the 'where are the rules'. Both are useful to the OP, I think. I'm assuming his code will end up with more exceptions eventually. – Sean Houlihane Sep 03 '18 at 10:50
  • Agreed, and your answer is helpful and accurate. But I think that the OP should know that there's no need to go scattering architecture-specific stuff around in code that will work just fine when written in portable C. – cooperised Sep 03 '18 at 11:07
  • Thanks for the answer. After looking up what you suggested I found [this](https://stackoverflow.com/a/15493703/786489) answer which shows a use of these instructions. As far as code portability, the code is written for a PSoC device so the code does not need to be portable. – Stefan Bossbaly Sep 03 '18 at 15:15