gpt4 book ai didi

c - 如何保护 isr 和常规函数共享的全局变量?

转载 作者:太空狗 更新时间:2023-10-29 17:21:27 24 4
gpt4 key购买 nike

假设我有function 1 和一个isr routine,两者共享和更新相同的标志,它们之间没有任何锁定。 系统是单线程的。

while 将是一个 3 臂汇编指令,这意味着它不是原子操作,是否可以在非 isr 和 isr 函数之间共享一个全局变量而没有任何锁定或保护?

功能一:

while (flag == false);
flag = false;

isr 例程:

do something
flag=true

我不记得有一个 linux 内核机制可以在可 sleep 和不可 sleep 上下文之间进行锁定,例如irq内核线程


感谢@artless 的回答,这里有一些我不确定的问题:

  1. 有没有办法让我完全不会错过中断?

  2. 内存屏障是怎么解决的,单cpu运行有效果吗?

  3. 在不同上下文之间使用屏障时的预期行为是什么?

  4. while loop 中的 sleep 能否解决同步问题?

最佳答案

使用 volatile 通常被引用为一种解决方案,但事实并非如此。它通常会掩盖一个问题,因为 volatile 总是会使代码变慢。如果您的唯一用途如图所示,那么 volatile 可能会起作用。

单个读取器单个写入可能更好地使用memory barriers .这将是您的代码,

主线:

volatile int *p = &flag;
while (*p == false); /* You must use volatile if you poll */
flag = false;
asm volatile ("" : : : "memory"); /* gcc barrier */

是:

/* do something */
flag=true
asm volatile ("" : : : "memory"); /* gcc barrier */

此处,barrier 只是强制编译器在该点执行 ARM str 指令。优化器不会在之前或之后移动任何代码。您还可以使用 swpldrexstrex,具体取决于您的 ARM CPU。同样,环形缓冲区通常与 ISRmainlines 一起使用,因为它们不需要任何特殊的 CPU 支持;只有编译器内存障碍

参见 并专门搜索 lock-free and arm .

编辑:对于添加,

Is there a way I won't miss interrupt at all ?

这取决于中断源。如果它是一个计时器并且您知道计时器源永远不会比XX 指令快并且系统中没有其他中断处于事件状态,那么您当前的代码将工作。但是,如果中断来自外部源,例如 以太网 Controller 、非去抖动键盘等。多个中断可能会很快到来。有时新的中断甚至发生在中断处理程序期间。根据 ISR 源,有不同的解决方案。 环形缓冲区 通常用于将来自 ISR 的工作项目排队到主线。对于 UART,环可能包含实际字符数据。它可以是指针列表等。当通信变得更加复杂时,很难从主线同步ISR;所以我相信答案取决于中断源。这就是为什么每个 OS 都有如此多的原语和基础结构来解决这个问题。

How the memory barriers solve the issue, does it have effect when the code runs on single cpu ?

内存屏障并不能完全解决错过的中断问题;就像 volatile 没有。它们只是使窗口小得多。它们强制编译器安排更早的加载或存储。比如主线循环,

  1: ldr r0, [r1]
cmp r0, #0 ; xxx
bne 1b ; xxx
mov r0,#1 ; xxx
str r0, [r1]

如果第 2 次中断发生在 xxx 行期间,那么您的 flag 应该设置两次并且您错过了一次中断。 障碍 只是确保编译器将 ldrstr 放在一起。

What is the expected behavior when using barriers between different contexts?

我展示的编译器内存屏障只是让编译器做事更快。它在上下文之间没有影响。有不同的障碍;但它们主要用于多 CPU 设计。

Can a sleep in the while loop can solve problems of syncs?

不是真的,这只是一种更高效的使用方式。 ARM WFI 指令可以暂时停止 CPU,这样可以节省电量。这通常是 sleep() 在 ARM 上执行的操作。如果这是一个问题,我认为您需要更改 ISRma​​inline 之间的通信。这取决于 ISR 来源。

关于c - 如何保护 isr 和常规函数共享的全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18088873/

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