gpt4 book ai didi

c - Atmel 驱动程序和 GCC 内存屏障用例

转载 作者:行者123 更新时间:2023-11-30 15:07:49 31 4
gpt4 key购买 nike

当我查看 Atmel 软件框架中的一些驱动程序实现时,我遇到了几种使用内存屏障的情况。

障碍定义:

#define barrier()        asm volatile("" ::: "memory")

示例 1(中断辅助函数):

static inline void cpu_irq_restore(irqflags_t flags)
{
barrier();
SREG = flags;
}

这个障碍对我来说很有意义。由于 cpu_irq_restore 是隐式内联的,因此它可以防止关键(从执行顺序角度来看)SREG 分配从实际函数调用位置重新排序。

作为旁注:SREG 被定义为特殊功能寄存器,定义为:

#define _SFR_MEM8(mem_addr) (*(volatile uint8_t *)(mem_addr))

示例 2(来自 AVR TWI 驱动程序):

static inline status_code_t twim_release(void)
{
/* First wait for the driver event handler to indicate something
* other than a transfer in-progress, then test the bus interface
* for an Idle bus state.
*/
while (OPERATION_IN_PROGRESS == transfer.status);

while (! twim_idle(transfer.bus)) { barrier(); }

status_code_t const status = transfer.status;

transfer.locked = false;

return status;
}

但是,我不清楚第二个用例。编译器可以通过什么方式优化该代码,使其在没有 barrier() 的情况下中断?

阅读 this article 后,我想我了解了软件内存障碍背后的基本推理。 .

在第二个示例中使用屏障的原因是什么?

最佳答案

twim_idle 函数可能会执行类似读取 TWI 相关特殊功能寄存器的值并检查其中某些位的操作。如果没有屏障,危险在于编译器可能会优化该寄存器的读取并将其移至第二个循环之前。那么第二个循环的行为将如下所示:

bool idle = twim_idle(transfer.bus);
while (!idle);

这是一种优化,可以使循环更快,并且对于读取普通变量是有效的,但在这种情况下显然会导致问题。在循环中放置障碍应该可以防止优化发生。

实际上,您不需要内存屏障,因为所有特殊功能寄存器都使用 volatile 关键字进行限定,因此编译器不会尝试缓存对它们的访问。

关于c - Atmel 驱动程序和 GCC 内存屏障用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37916566/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com