volatile unsigned int counter = 0;
volatile __bit flag = 0; // 标志位,bit类型
void ISR() __interrupt(1) {
counter++; // 计数器非原子操作,风险大
flag = 1; // 标志位设置不需要原子保护
}counter++由多条汇编指令组成(读、加、写),中断可能发生在中间,导致计数错误。__critical关键字(推荐简单安全)int foo() __critical {
// 进入函数自动关闭中断
// 退出函数恢复中断状态
}void bar(void) {
__critical {
// 多条语句自动临界区执行
i++;
// 其他代码
}
}volatile unsigned int counter = 0;
volatile __bit flag = 0;
void increment_counter() __critical {
counter++; // 自动中断保护
}
void ISR() __interrupt(1) {
increment_counter();
flag = 1; // 标志位设置无需保护
}
void ISR2() __interrupt(1) {
__critical {
counter++;
}
flag = 1;
}void func() {
bit ea_save = EA; // 保存中断使能位
EA = 0; // 禁用中断
// 临界区代码
EA = ea_save; // 恢复中断使能位
}volatile unsigned int counter = 0;
volatile __bit flag = 0;
void ISR() __interrupt(1) {
bit ea_save = EA;
EA = 0;
counter++;
EA = ea_save;
flag = 1;
}JBC(Jump if Bit set and Clear)硬件指令,实现位的原子测试与清零。
volatile __bit lock = 1; // 锁标志位,1表示未锁定
if (lock) {
lock = 0; // 加锁(JBC指令自动完成测试并清零)
// 临界区
lock = 1; // 解锁
}volatile __bit lock = 1;
volatile unsigned int counter = 0;
volatile __bit flag = 0;
void ISR() __interrupt(1) {
if (lock) {
lock = 0; // JBC原子操作加锁
counter++;
lock = 1; // 解锁
}
flag = 1;
}方法 | 内存占用 | 执行速度 | 代码复杂度 | 适用场景 |
|---|---|---|---|---|
非原子操作 | 最小 | 最高(无额外指令) | 简单 | 无多任务或中断保护需求 |
__critical | 较多(保存中断状态) | 中等 | 简单自动 | 常规临界区保护 |
手动EA保存恢复 | 类似__critical | 视实现灵活 | 复杂易错 | 复杂长临界区或特殊控制 |
JBC指令锁 | 极小(1bit位) | 最高(单条指令) | 需要硬件支持 | 简单锁机制,单个位保护 |
EA时,必须确保中断状态正确恢复,避免死锁。__critical支持嵌套,调用多次会额外占用栈空间。__critical伪汇编流程push EA ; 保存中断使能状态
clr EA ; 关闭中断
; 临界区代码
pop EA ; 恢复中断使能状态
ret ; 返回mov A, EA ; 保存EA到累加器
clr EA ; 关闭中断
; 临界区代码
mov EA, A ; 恢复EA状态
retjbc lock_bit, skip ; 测试并清零lock_bit,跳转到skip失败(锁被占用)
; 成功获得锁的代码
skip:
; 临界区代码
setb lock_bit ; 解锁
ret__critical,自动管理,减少错误。EA,但要确保代码严谨。