并发访问结构体成员
我使用的是 32 位微控制器 (STR91x)。我正在同时访问(从 ISR 和主循环)枚举类型的结构成员。访问权限仅限于写入 ISR 中的枚举字段并在主循环中进行检查。 Enum 的基础类型不大于整数(32 位)。 我想确保我没有遗漏任何东西并且我可以安全地做到这一点。
I'm using 32-bit microcontroller (STR91x). I'm concurrently accessing (from ISR and main loop) struct member of type enum. Access is limited to writing to that enum field in the ISR and checking in the main loop. Enum's underlying type is not larger than integer (32-bit).
I would like to make sure that I'm not missing anything and I can safely do it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
假设 32 位读取和写入是原子的,几乎可以肯定是这种情况(您可能想确保枚举的字对齐),那么您所描述的就可以了。
Provided that 32 bit reads and writes are atomic, which is almost certainly the case (you might want to make sure that your enum's word-aligned) then that which you've described will be just fine.
作为 paxdiablo & David Knell 说,一般来说这样就可以了。即使您的巴士< 32 位,很可能指令的多个总线周期不会被中断,并且您将始终读取有效数据。
你所说的,以及我们都知道的,但值得重复的是,这对于单作者、N 读者的情况来说是很好的。如果您有多个编写器,那么除非您有保护数据的结构,否则一切都将失败。
As paxdiablo & David Knell said, generally speaking this is fine. Even if your bus is < 32 bits, chances are the instruction's multiple bus cycles won't be interrupted, and you'll always read valid data.
What you stated, and what we all know, but it bears repeating, is that this is fine for a single-writer, N-reader situation. If you had more than one writer, all bets are off unless you have a construct to protect the data.
如果您想确定,请找到生成程序集列表的编译器开关,并检查 ISR 中的写入和主循环中的读取的程序集。即使您不熟悉 ARM 汇编,我相信您也可以快速轻松地辨别读写是否是原子的。
If you want to make sure, find the compiler switch that generates an assembly listing and examine the assembly for the write in the ISR and the read in the main loop. Even if you are not familiar with ARM assembly, I'm sure you could quickly and easily be able to discern whether or not the reads and writes are atomic.
ARM 支持 32 位对齐读取,就中断而言,这些读取是原子的。但是,请确保您的编译器不会尝试将值缓存在寄存器中!要么将其标记为易失性,要么使用显式内存屏障 - 在 GCC 上,可以这样做:
但是请注意,当前版本的 GCC 为 __sync_synchronize< 提供了完整的内存屏障/code>,而不仅仅是一个变量,因此
volatile
可能更适合您的需求。此外,请注意,除非您执行一些奇怪的操作(即显式指定内存中结构的位置,或请求打包结构),否则您的变量将自动对齐。 ARM 上未对齐的变量无法自动读取,因此请确保其对齐,或者在读取时禁用中断。
ARM supports 32-bit aligned reads that are atomic as far as interrupts are concerned. However, make sure your compiler doesn't try to cache the value in a register! Either mark it as a
volatile
, or use an explicit memory barrier - on GCC this can be done like so:Note, however, that current versions of GCC person a full memory barrier for
__sync_synchronize
, rather than just for the one variable, sovolatile
is probably better for your needs.Further, note that your variable will be aligned automatically unless you are doing something Weird (ie, explicitly specifying the location of the struct in memory, or requesting a packed struct). Unaligned variables on ARM cannot be read atomically, so make sure it's aligned, or disable interrupts while reading.
嗯,这完全取决于您的硬件,但如果 ISR 可以被主线程中断,我会感到惊讶。
因此,您可能唯一需要注意的是主线程是否可能在读取过程中被中断(因此它可能会获得部分旧值和部分新值)。
查阅规范应该是一个简单的问题,以确保仅在指令之间处理中断(这很可能是因为替代方案非常复杂)并且您的 32 位负载是单个指令。
Well, it depends entirely on your hardware but I'd be surprised if an ISR could be interrupted by the main thread.
So probably the only thing you have to watch out for is if the main thread could be interrupted halfway through a read (so it may get part of the old value and part of the new).
It should be a simple matter of consulting the specs to ensure that interrupts are only processed between instructions (this is likely since the alternative would be very complex) and that your 32-bit load is a single instruction.
对齐的 32 位访问通常是原子的(除非它是一个特别可笑的编译器!)。
然而,坚如磐石的解决方案(通常也适用于非 32 位目标)是在访问中断之外的数据时暂时禁用中断。最可靠的方法是通过静态范围数据的访问函数,而不是使数据 global 这样您就没有单点访问,因此无法在需要时强制执行原子访问机制。
An aligned 32 bit access will generally be atomic (unless it were a particularly ludicrous compiler!).
However the rock-solid solution (and one generally applicable to non-32 bit targets too) is to simply disable the interrupt temporarily while accessing the data outside of the interrupt. The most robust way to do this is through an access function to statically scoped data rather than making the data global where you then have no single point of access and therefore no way of enforcing an atomic access mechanism when needed.