打印
[C语言]

单片机端口的读改写的一个疑问

[复制链接]
3215|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gym216|  楼主 | 2021-5-19 09:17 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
看资料经常有说到单片机的io口的读改写问题,想到一个平时写代码从没注意的问题。假设主程序中操作端口PA0输出,中断程序中操作端口PA1输出。对于端口的位操作都是读改写,那么有可能主程序中操作PA0有可能被中断打断,这样不是会造成端口实际输出是混乱的?如果确实这样,应该怎么避免?要所有中断中都不要操作io输出吗?

使用特权

评论回复

相关帖子

沙发
ayb_ice| | 2021-5-19 09:32 | 只看该作者
一般8位机GPIO操作都是原子操作,不用担心
arm一般也提供额外特殊SFR操作,实现原子操作(专用的置1,清零,取反寄存器)

使用特权

评论回复
板凳
sonicll| | 2021-5-19 09:34 | 只看该作者
有些MCU能实现原子操作,比如cortex-m3的位带操作,这样可以避免中断打断“读改写”的过程;如果无法实现原子操作,那就只能在操作前先关闭中断,操作完再打开中断

使用特权

评论回复
地板
lyjian| | 2021-5-20 08:33 | 只看该作者
不会出现你的说的这种问题。
所有单片机都是执行完当前指令后才会去响应中断。

使用特权

评论回复
5
tom_xu| | 2021-5-20 10:13 | 只看该作者
是有可能出现端口混乱的情况。

使用特权

评论回复
6
coody| | 2021-5-20 21:22 | 只看该作者
tom_xu 发表于 2021-5-20 10:13
是有可能出现端口混乱的情况。

不会出现,设计IC的工程师早想到了的。8位机会执行完指令才响应中断,16位或32位机也会有响应的机制保证不会出现你们担心的问题。如果有这个风险,那就不能位操作了。

使用特权

评论回复
7
ayb_ice| | 2021-5-21 08:27 | 只看该作者
coody 发表于 2021-5-20 21:22
不会出现,设计IC的工程师早想到了的。8位机会执行完指令才响应中断,16位或32位机也会有响应的机制保证 ...

当然有这种可能了,ARM核就有这可能,只不过ARM提供另外的方法解决这个问题,位带操作与GPIO置位,清零特殊寄存器就是方法

使用特权

评论回复
8
tom_xu| | 2021-5-21 09:01 | 只看该作者
coody 发表于 2021-5-20 21:22
不会出现,设计IC的工程师早想到了的。8位机会执行完指令才响应中断,16位或32位机也会有响应的机制保证 ...

会出现的,实际产品上就出现这个问题,查了大半年才找到原因。

使用特权

评论回复
9
lyjian| | 2021-5-21 13:06 | 只看该作者
本帖最后由 lyjian 于 2021-5-21 18:23 编辑

上面几位回答“会的”都没有看清楚楼主的问题。
楼主的问题是“对于端口的位操作都是读改写,那么有可能主程序中操作PA0有可能被中断打断,这样不是会造成端口实际输出是混乱的?”

看重点“有可能主程序中操作PA0有可能被中断打断”。
显然这是没有可能出现的,因为所有MCU都会在执行完当前指令后才会去响应中断,所以不可能出现主程序操作端口到半路后被中断截胡去操作端口这种情况。
(至少51核ARM都是这样,看下面截图。)



那为何有时端口会莫名其妙变了(各位口中的端口混乱?)?这就和读-修改-写指令相关。
有些MCU,读-修改-写指令读的是读端口实际状态。假如某个端口的PA0做输入,PA1做输出,PA0\PA1的输出寄器都置了1,PA0\PA1都被外面的电路拉到了低电平,这时对PA端口执行读-修改-写指令,PA0\PA1会读回0电平,然后被CPU把0写回PA0\PA1的输出寄器(与之前的设置相反了),PA1这时变成了输出0电平(原先要求是输出高电平的,出现了混乱)。PA0因为是输入,输出寄器的值变化没有影响,但后面软件把PA0设成了输出,那就受影响了,怎么输出了低电平?原先软件只设了1呀,怎么出现了混乱?

51不会出现这种问题,因为51的读-修改-写指令读的是器不是端口;PIC会出现这种问题,因为PIC的读-修改-写指令读的是端口。

使用特权

评论回复
10
ayb_ice| | 2021-5-21 13:38 | 只看该作者
lyjian 发表于 2021-5-21 13:06
上面几位回答“会的”都没有看清楚楼主的问题。
楼主的问题是“对于端口的位操作都是读改写,那么有可能主 ...

读改写只是一个概念,又没有规定必须是一条指令搞定
ARM是加载存储体系架构,根本没有办法实现一条指令搞定,必须先加载,再修改,再存储。。。
后来搞了位带概念,虽然也不可能一条指令搞定,但仍能解决原子操作,当然还有位清除,位置一SFR实现

使用特权

评论回复
11
lyjian| | 2021-5-21 18:10 | 只看该作者
ayb_ice 发表于 2021-5-21 13:38
读改写只是一个概念,又没有规定必须是一条指令搞定
ARM是加载存储体系架构,根本没有办法实现一条指令搞 ...

这里讨论的是IO的读改写指令,都是一条指令搞定

使用特权

评论回复
12
William1994| | 2021-5-22 20:51 | 只看该作者
读可以随便读。
而关于写,中断和main函数,只有一个能写IO。
只要是做到上面这行的要求,怎么弄都不会出问题。
我是这样理解的。

使用特权

评论回复
13
ayb_ice| | 2021-5-24 08:30 | 只看该作者
lyjian 发表于 2021-5-21 18:10
这里讨论的是IO的读改写指令,都是一条指令搞定

典型的加载存储内核一般无法一条指令搞定GPIO读改写

使用特权

评论回复
14
gym216|  楼主 | 2021-6-4 11:13 | 只看该作者
coody 发表于 2021-5-20 21:22
不会出现,设计IC的工程师早想到了的。8位机会执行完指令才响应中断,16位或32位机也会有响应的机制保证 ...

赞同你的观点,理论上 读-改-写 绝对不是原子操作,单实际项目中从没考虑过此问题,51 PIC M0+ 内核我都是直接操作的 没有发现过问题。对于其他可能封装了GPIO置位 清除函数的芯片,可能要操作专门的置位清楚寄存器才是保险的。

使用特权

评论回复
15
zwsam| | 2022-9-3 21:29 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

62

帖子

2

粉丝