为什么需要对嵌入式系统上的寄存器进行读 - 修改 - 写入? [英] Why is Read-Modify-Write necessary for registers on embedded systems?

查看:189
本文介绍了为什么需要对嵌入式系统上的寄存器进行读 - 修改 - 写入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 http:// embeddedgurus.com/embedded-bridge/2010/03/different-bit-types-in-different-registers/ ,其中说:


使用读/写位,固件设置并在需要时清除位。它通常首先读取寄存器,修改所需的位,然后将修改后的值写回


,我已经遇到了这个consrtuct在这里保留一些由老盐嵌入的人编码的生产代码。我不明白为什么这是必要的。



当我想设置/清除一点时,我总是只是或/不是一个位掩码。在我看来,这解决了任何线程安全问题,因为我假设设置(通过赋值或者使用掩码)一个寄存器只需要一个周期。另一方面,如果您首先读取注册表,然后修改,然后写入,则读取和写入之间的中断可能会导致将旧值写入注册表。



<为什么读 - 修改 - 写?还有必要吗?

解决方案

这取决于您的特定嵌入式设备的体系结构。我会给出三个例子来涵盖常见的情况。然而,其基本要点是,从根本上说,CPU内核不能直接在I / O设备的寄存器上运行,除了以字节或甚至字面方式读写。



1)68HC08系列,一个8位独立的微控制器。



这包括一个位设置和位清除指令。这些,如果仔细阅读本手册,实际上内部自行执行读 - 修改 - 写周期。他们确实具有原子操作的优点,因为作为单一指令,它们不能被中断。



您还将注意到它们比单独的读取或写入指令花费更长的时间,但是更少的时间比使用三个指令(见下文)。



2)ARM或PowerPC,常规的32位RISC CPU(通常也在高端微控制器中)



这些不包含任何可以同时访问内存并执行计算(和/或)的任何指令。如果你写在C:



* register | = 0x40;



它变成下一个程序集(对于这个PowerPC示例,r8包含寄存器地址):

  LBZ r4 ,r8 
ORI r4,r4,#0x40
STB r4,r8

因为这是多个指令,它不是原子的,它可以被中断。使其成为原子或甚至SMP安全超出了此答案的范围 - 有特殊的说明和技巧。



3)IA32(x86)和AMD64。为什么你使用这些嵌入式是超出我的,但他们是另外两个例子之间的中间房。



我忘记了是否有一个单一的x86上的指令内存位置位和位清零。如果没有,请参阅上面的RISC部分,它只需要两个指令,而不是三个指令,因为x86可以在一个指令中加载和修改。



假设有这样的指令,他们需要内部加载和存储寄存器以及修改它。现代版本将在内部明确地将指令分解为三个类似RISC的操作。



奇怪的是x86(不同于HC08)可能会在内存总线中断由总线主机进行交互,不仅仅是传统的CPU中断。因此,您可以手动向需要执行多个内存周期的指令添加一个LOCK前缀,如这种情况。你不会从平原C得到这个。


I was reading http://embeddedgurus.com/embedded-bridge/2010/03/different-bit-types-in-different-registers/, which said:

With read/write bits, firmware sets and clears bits when needed. It typically first reads the register, modifies the desired bit, then writes the modified value back out

and I have run into that consrtuct while maintaining some production code coded by old salt embedded guys here. I don't understand why this is necessary.

When I want to set/clear a bit, I always just or/nand with a bitmask. To my mind, this solves any threadsafe problems, since I assume setting (either by assignment or oring with a mask) a register only takes one cycle. On the other hand, if you first read the register, then modify, then write, an interrupt happening between the read and write may result in writing an old value to the register.

So why read-modify-write? Is it still necessary?

解决方案

This depends somewhat on the architecture of your particular embedded device. I'll give three examples that cover the common cases. The basic gist of it, however, is that fundamentally the CPU core cannot operate directly on the I/O devices' registers, except to read and write them in a byte- or even word-wise fashion.

1) 68HC08 series, an 8-bit self-contained microcontroller.

This includes a "bit set" and a "bit clear" instruction. These, if you read the manual carefully, actually internally perform a read-modify-write cycle by themselves. They do have the advantage of being atomic operations, since as single instructions they cannot be interrupted.

You will also notice that they take longer than individual read or write instructions, but less time than using three instructions for the job (see below).

2) ARM or PowerPC, conventional 32-bit RISC CPUs (often found in high-end microcontrollers too).

These do not include any instructions which can both access memory and perform a computation (the and/or) at once. If you write in C:

*register |= 0x40;

it turns into the folowing assembly (for this PowerPC example, r8 contains the register address):

LBZ r4,r8
ORI r4,r4,#0x40
STB r4,r8

Because this is multiple instructions, it is NOT atomic, and it can be interrupted. Making it atomic or even SMP-safe is beyond the scope of this answer - there are special instructions and techniques for it.

3) IA32 (x86) and AMD64. Why you would use these for "embedded" is beyond me, but they are a half-way house between the other two examples.

I forget whether there is a single-instruction in-memory bit-set and bit-clear on x86. If not, then see the RISC section above, it just takes only two instructions instead of three because x86 can load and modify in one instruction.

Assuming there are such instructions, they also need to internally load and store the register as well as modifying it. Modern versions will explcitly break the instruction into the three RISC-like operations internally.

The oddity is that x86 (unlike the HC08) can be interrupted on the memory bus in mid-transaction by a bus master, not just by a conventional CPU interrupt. So you can manually add a LOCK prefix to an instruction that needs to do multiple memory cycles to complete, as in this case. You won't get this from plain C though.

这篇关于为什么需要对嵌入式系统上的寄存器进行读 - 修改 - 写入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆