C 在执行后续代码之前执行内存写入

C 在执行后续代码之前执行内存写入,c,memory,arm,embedded,race-condition,C,Memory,Arm,Embedded,Race Condition,我正在编写触发DMA的代码。一旦DMA完成其操作,它将调用ISR\u例程。问题是,我想确保在DMA运行之前,refreshComplete设置为0。如果DMA在refreshComplete设置为0之前先运行,则可以先调用ISR_例程,使refreshComplete成为0,即使DMA已成功运行。这意味着ready()函数将始终返回0,阻止进一步使用DMA 我现在编写代码的方式是refreshComplete变量是volatile,我忙着等待,直到读回变量是0,DMA才会这样运行: volati

我正在编写触发DMA的代码。一旦DMA完成其操作,它将调用
ISR\u例程
。问题是,我想确保在DMA运行之前,
refreshComplete
设置为
0
。如果DMA在
refreshComplete
设置为
0
之前先运行,则可以先调用
ISR_例程
,使
refreshComplete
成为
0
,即使DMA已成功运行。这意味着
ready()
函数将始终返回0,阻止进一步使用DMA

我现在编写代码的方式是
refreshComplete
变量是
volatile
,我忙着等待,直到读回变量是
0
,DMA才会这样运行:

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;
}

是否有一种方法可以保证设置刷新完成的代码总是在设置和运行DMA的代码之前运行?

这是您应该查看处理器架构信息和指令集的地方


您将发现
DMB
DSB
ISB
,根据处理器的先进程度,可能还有其他一些。这些与强制执行数据传输的顺序以及指令相对于oter指令的顺序有关(因此,
DMB,ISB
是一个常见的顺序)。当然,如果您在“C”中使用这些,您也需要担心语言的顺序保证。

尽管对屏障说明的引用可能是相关的,但在这种情况下,我认为它们不需要。当代码正忙着等待时,无需保证写入
ISR\u例程()
将在下一次读入
ready()
之前完成。它会在下一次尝试时恢复
volatile
在这里做所有必要的事情。我认为这取决于你是在回答最终目标,还是“规则在哪里”。我认为这两种方法都对OP有用。我假设他的代码最终会有更多的异常。同意,你的答案是有用的和准确的。但是我认为OP应该知道,没有必要将特定于体系结构的东西分散在代码中,这样在用portable C编写时就可以很好地工作。谢谢你的回答。在查阅了您的建议后,我找到了答案,其中显示了这些说明的用法。就代码可移植性而言,代码是为PSoC设备编写的,因此代码不需要是可移植的。