【问题标题】:Enforcement of memory write before execution of later code在执行后面的代码之前强制执行内存写入
【发布时间】:2019-02-07 20:55:25
【问题描述】:

我正在编写触发 DMA 的代码。一旦 DMA 完成其操作,它将调用ISR_Routine。问题是我想确保在 DMA 运行之前将refreshComplete 设置为0。如果 DMA 先运行,在将 refreshComplete 设置为 0 之前,则可能首先调用 ISR_Routine,从而导致 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;
}

有没有一种方法可以始终保证设置refreshComplete 的代码始终在设置和运行 DMA 的代码之前运行?

【问题讨论】:

    标签: c memory arm embedded race-condition


    【解决方案1】:

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

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

    【讨论】:

    • 虽然对屏障指令的引用可能是相关的,但在这种情况下,我认为不需要它们。当代码只是忙于等待时,不需要保证ISR_Routine() 的写入将在ready() 的下一次读取发生之前完成。它会在下次尝试时捡起它! volatile 在这里做了所有必要的事情。
    • 我认为这取决于您是在回答最终目标还是“规则在哪里”。我认为两者都对 OP 有用。我假设他的代码最终会出现更多异常。
    • 同意,您的回答很有帮助且准确。但我认为 OP 应该知道,没有必要在代码中散布特定于架构的东西,这些代码在用可移植 C 编写时可以正常工作。
    • 感谢您的回答。在查看了您的建议后,我找到了this 答案,它显示了这些说明的使用。就代码可移植性而言,代码是为 PSoC 设备编写的,因此代码不需要可移植。
    猜你喜欢
    • 1970-01-01
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 2018-05-29
    • 2013-05-31
    • 1970-01-01
    相关资源
    最近更新 更多