搜索
bottom↓
回复: 7

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

[复制链接]

出0入0汤圆

发表于 2017-10-10 11:56:07 | 显示全部楼层 |阅读模式

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

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

出0入4汤圆

发表于 2017-10-10 12:35:27 | 显示全部楼层
如果之前中断就是关闭的,SREG=sreg后,中断还是关闭的
如果你用sei,破坏了原来状态

出0入0汤圆

发表于 2017-10-10 13:19:20 | 显示全部楼层
有可能之前状态本来就是关闭的,       如果你强迫症成对的对称用,就得IF ELSE了,很啰嗦。

出0入0汤圆

 楼主| 发表于 2017-10-10 14:38:03 | 显示全部楼层
liuqian 发表于 2017-10-10 12:35
如果之前中断就是关闭的,SREG=sreg后,中断还是关闭的
如果你用sei,破坏了原来状态 ...

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

出0入8汤圆

发表于 2017-10-10 15:03:50 | 显示全部楼层
关闭之前有可能是开的,也有可能是关闭的。
如果用sei(),则将关闭的那种情况破坏了。

出200入2554汤圆

发表于 2017-10-10 18:04:01 | 显示全部楼层
写入 SREG 时,就已经包含了 CLI() 或者 SEI() 了。

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

  1. void system_set_exec_alarm(uint8_t code) {
  2.         uint8_t sreg = SREG;
  3.         SREG&=~(1<<7);                // <=> CLI()
  4.         sys_rt_exec_alarm = code;
  5.         SREG = sreg;
  6. }
复制代码


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

出0入0汤圆

 楼主| 发表于 2017-10-11 09:09:23 | 显示全部楼层
t3486784401 发表于 2017-10-10 18:04
写入 SREG 时,就已经包含了 CLI() 或者 SEI() 了。

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

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

出200入2554汤圆

发表于 2017-10-12 18:38:54 | 显示全部楼层
王涛 发表于 2017-10-11 09:09
非常感谢,那么请问对应的STM32F4要想实现这种原子操作该怎么写呢?

并不熟悉 NVIC 的用法,目测也是关一个中断允许位。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 16:57

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表