Почему Read-Modify-Write необходим для регистров во встроенных системах?

Я читал http://embeddedgurus.com/embedded-bridge/2010/03/different-bit-types-in-different-registers/, в котором было сказано:

С битами чтения-записи встроенное микропрограммное обеспечение устанавливает и очищает биты при необходимости. Это обычно сначала читает регистр, изменяет желаемый бит, затем записывает измененное значение обратно

и я столкнулся с этим, consrtuct при поддержании некоторого производственного кода, кодированного старым моряком, встроил парней здесь. Я не понимаю, почему это необходимо.

Когда я хочу установить/очистить немного, я всегда просто или/NAND с битовой маской. По моему мнению это решает любые ориентированные на многопотоковое исполнение проблемы, так как я принимаю установку (или присвоением или oring с маской), регистр только берет один цикл. С другой стороны, если Вы первое чтение регистр, затем измените, затем запишите, прерывание, происходящее между чтением и записью, может закончиться в письменной форме старое значение к регистру.

Итак, почему read-modify-write? Это все еще необходимо?

12
задан Adam Shiemke 31 March 2010 в 01:55
поделиться

4 ответа

Это в некоторой степени зависит от архитектуры вашего конкретного встроенного устройства. Приведу три примера, которые охватывают распространенные случаи. Основная суть его, однако, заключается в том, что ядро процессора не может работать непосредственно на регистрах устройств ввода-вывода, за исключением чтения и записи их в байтовом или даже словесном виде.

1) Серия 68HC08, 8-разрядный автономный микроконтроллер.

Это включает в себя «набор битов» и инструкцию «bit clear». Они, если вы внимательно прочитаете руководство, на самом деле внутренне выполняют цикл чтения-изменения-записи сами по себе. Они имеют то преимущество, что являются атомными операциями, поскольку как единые инструкции они не могут быть прерваны.

Вы также заметите, что они занимают больше времени, чем отдельные инструкции по чтению или написанию, но меньше времени, чем использование трех инструкций для работы (см. Ниже).

2) ARM или PowerPC, обычные 32-разрядные RISC-процессоры (часто встречаются и в высокопроизводительных микроконтроллерах).

Они не включают в себя какие-либо инструкции, которые могут как получить доступ к памяти, так и выполнить вычисления (и/или) одновременно. Если вы пишете в C:

*register |= 0x40;

он превращается в сборку (для этого примера PowerPC r8 содержит адрес регистра):

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

Поскольку это несколько инструкций, он НЕ атомарный, и его можно прервать. Сделать его атомарным или даже SMP-безопасным выходит за рамки этого ответа – для этого существуют специальные инструкции и методики.

3) IA32 (x86) и AMD64. Почему вы используете их для «встроенного», я не вникаю, но они находятся на полпути между двумя другими примерами.

Я забыл, есть ли в памяти битовый набор с одной инструкцией и bit-clear на x86. Если нет, то см. раздел RISC выше, он просто занимает только две инструкции вместо трех, потому что x86 может загружать и изменять в одной инструкции.

Предполагая, что такие инструкции есть,они также должны внутренне загружать и хранить регистр, а также изменять его. Современные версии будут разбивать инструкцию на три RISC-подобные операции внутри.

Странность заключается в том, что x86 (в отличие от HC08) может быть прерван на шине памяти в середине транзакции хозяином шины, а не только обычным прерыванием процессора. Таким образом, вы можете вручную добавить префикс LOCK к инструкции, для выполнения которого необходимо выполнить несколько циклов памяти, как в этом случае. Однако вы не получите этого из простого C.

16
ответ дан 2 December 2019 в 05:40
поделиться

Когда я хочу немного установить / сбросить, я всегда просто или / nand с битовой маской.

Для некоторых регистров этого достаточно. В таком случае микропрограммное обеспечение ЦП по-прежнему будет выполнять чтение-изменение-запись.

На мой взгляд, это решает любые проблемы, связанные с безопасностью потоков , поскольку я предполагаю, что установка (либо путем присвоения, либо с помощью маски ) регистра занимает всего один цикл.

Если вы позволите микропрограмме ЦП выполнять чтение-изменение-запись за вас, очевидно, что она будет включать как минимум цикл чтения и цикл записи. Теперь большинство процессоров не будут прерывать эту инструкцию посередине, поэтому ваш поток выполнит всю эту инструкцию до того, как процессор вашего потока проверит прерывания, но если вы не заблокировали шину, другие процессоры могут изменить тот же регистр. Ваша нить и другие нити все еще могут перемещаться друг по другу.

0
ответ дан 2 December 2019 в 05:40
поделиться

Если вам необходимо изменить подмножество битов в слове, а архитектура поддерживает только чтение / запись на уровне слова, вы должны прочитать биты, которые не должны изменяться, чтобы знать, что записывать обратно, чтобы они не изменялись. .

Некоторые архитектуры поддерживают доступ к памяти на уровне битов либо глобально, либо для определенных областей памяти. Но даже тогда при изменении нескольких битов многие операции чтения-изменения-записи приводят к меньшему количеству инструкций. В многопоточных системах необходимо следить за тем, чтобы два потока не могли одновременно выполнять это неатомарное действие с одним и тем же словом.

2
ответ дан 2 December 2019 в 05:40
поделиться

Дело в том, что если вы не хотите изменять другие биты в регистре, вы должны знать, что они собой представляют, прежде чем что-то записывать. Следовательно, чтение / изменение / запись. Обратите внимание, что если вы используете оператор C, например:

*pRegister |= SOME_BIT;

Event, хотя на первый взгляд это может выглядеть как простая операция записи, компилятор должен сначала выполнить чтение, чтобы сохранить другие биты в значении (обычно это правда, даже если вы не говорите об аппаратных регистрах, если компилятор не может использовать другие знания о значении для оптимизации чтения).

Обратите внимание, что отображенные в память аппаратные регистры обычно помечаются volatile специально для того, чтобы эти оптимизации не могли иметь место (в противном случае многие подпрограммы аппаратных регистров не работали бы должным образом).

Наконец, иногда имеется аппаратная поддержка регистров, которые специально устанавливают или очищают биты в оборудовании, не требуя последовательности чтения / изменения / записи. Некоторые микроконтроллеры Atmel ARM, с которыми я работал, имеют это с определенными регистрами, которые очищают или устанавливают биты в аппаратном обеспечении только тех битов, которые устанавливаются при записи в регистр (оставляя все неустановленные биты в покое). Кроме того, процессор Cortex M3 ARM поддерживает доступ к одному биту (для чтения или записи) в памяти или в аппаратных регистрах через доступ к определенному адресному пространству с помощью техники, которую они называют «полосой битов» . Алгоритм разбиения на биты на первый взгляд выглядит сложным, но на самом деле это всего лишь простая арифметика, позволяющая сопоставить смещение бита в одном адресе другому «зависящему от бита» адресу.

В любом случае, суть в том, что есть некоторые процессоры, где можно обойтись без последовательного чтения / изменения / записи, но это ни в коем случае не всегда верно.

7
ответ дан 2 December 2019 в 05:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: