我正在为 Atmega 微控制器编写 C 代码,我想在其中使用 Mutex。要包括什么库?以及如何实现代码?
我希望这个互斥锁可以防止定时器中断在函数期间更改变量。
在常规中断处理程序和主程序之间使用互斥锁是不正确的。一个线程。主要问题是中断处理程序不能暂停,一旦获得互斥体就可以继续。
延迟中断处理程序是不同的,如果操作系统提供相应的功能,它可能会工作(但它仍然不常见)。互斥锁是多线程操作系统的一部分,因此不作为独立库出现。如果您使用操作系统,您应该在其文档中找到如何/何时/将使用它们的信息。
如评论中所述,在修改变量时禁用该中断是一种替代方法。由于没有什么是免费的(当然,除了 FOSS;-),这会增加锁定部分的持续时间的中断延迟。
您可能会交替使用 C11 标准中的原子操作,但不确定它们是否可用于此平台(它们是可选的)。如果这些不可用,@Clifford 已经展示了一个替代方案。
关于中断控制:如果你有一个中断处理程序,你必须已经启用了中断,所以应该直截了当如何禁用它。但是,更好的方法是使用启用/禁用全局中断信号的 CPU 指令(可能类似于 dint/eint - 只需查看参考手册)。大多数工具链都为 C(++) 提供了内置或头文件的内在函数,从而无需汇编程序。
没有中断锁定的解决方案是使用辅助标志:
volatile uint8_t modified; // global like ticks
ticksInterrupt() {
modified = 1;
// update ticks
}
uint32_t getTicks() {
uint32_t result;
do {
modified = 0;
result = ticks;
} while ( modified ) ;
return result;
}
这比 8 位 CPU 上的 32 位比较更快并且可能更少的代码,代价是 RAM 中的额外标志字节和modified
int 处理程序中的额外写入(IIRC,这是 AVR 上的一条指令)。
这种方法假设非嵌套中断(这是 AVR 和其他 8 位/16 位的标准,但不是强制性的 - 但是无论如何您都需要知道这一点)。
如果您使用的是 RTOS 或线程库,它几乎肯定包含互斥体 API,如果您不使用,则不需要互斥体。在任何情况下,您都不能在中断处理程序中使用互斥锁。
相反,如果您的计时器变量在中断上下文中被修改并且是非原子的,那么解决方案是确保连续读取两次相同的值以确保它是一致的。例如:
volatile uint32_t tick ;
__interrupt timerISR()
{
tick++ ;
}
uint32_t getTick()
{
uint32_t tickval = tick ;
while( tickval != tick )
{
tickval = tick ;
}
}