王涛 发表于 2017-10-10 11:56:07

AVR 关全局中断的函数cli();的疑问


void system_set_exec_alarm(uint8_t code) {
uint8_t sreg = SREG;
cli();
sys_rt_exec_alarm = code;
SREG = sreg;
}
上面的这个函数的意思是不是这样
把状态寄存器的数据保存到sreg这里。
然后关全局中断的函数cli();
变量赋值
还原状态寄存器的值

后面为什么不调用sei();开中断呢?
ARM中怎么才能获得状态寄存器的值呢?

liuqian 发表于 2017-10-10 12:35:27

如果之前中断就是关闭的,SREG=sreg后,中断还是关闭的
如果你用sei,破坏了原来状态

huangqi412 发表于 2017-10-10 13:19:20

有可能之前状态本来就是关闭的,       如果你强迫症成对的对称用,就得IF ELSE了,很啰嗦。

王涛 发表于 2017-10-10 14:38:03

liuqian 发表于 2017-10-10 12:35
如果之前中断就是关闭的,SREG=sreg后,中断还是关闭的
如果你用sei,破坏了原来状态 ...

谢谢
这样写的好处是为了保证函数的原子操作。如果之前是关闭的,那么还写这句话干什么呢?为什么sei后就破坏了呢?

rube 发表于 2017-10-10 15:03:50

关闭之前有可能是开的,也有可能是关闭的。
如果用sei(),则将关闭的那种情况破坏了。

t3486784401 发表于 2017-10-10 18:04:01

写入 SREG 时,就已经包含了 CLI() 或者 SEI() 了。

你把 CLI() 换成 SREG&=~(1<<7) 就看懂了:

void system_set_exec_alarm(uint8_t code) {
        uint8_t sreg = SREG;
        SREG&=~(1<<7);                // <=> CLI()
        sys_rt_exec_alarm = code;
        SREG = sreg;
}

这个过程就是个 保存现场——执行原子操作——恢复现场 的过程,无论之前是否 I 置位,都不会发生错误或影响。

王涛 发表于 2017-10-11 09:09:23

t3486784401 发表于 2017-10-10 18:04
写入 SREG 时,就已经包含了 CLI() 或者 SEI() 了。

你把 CLI() 换成 SREG&=~(1

非常感谢,那么请问对应的STM32F4要想实现这种原子操作该怎么写呢?

t3486784401 发表于 2017-10-12 18:38:54

王涛 发表于 2017-10-11 09:09
非常感谢,那么请问对应的STM32F4要想实现这种原子操作该怎么写呢?

并不熟悉 NVIC 的用法,目测也是关一个中断允许位。
页: [1]
查看完整版本: AVR 关全局中断的函数cli();的疑问