§
|
> Битовый доступ Bit Banding
|
Традиционный способ сброса и установки битов переменных ОЗУ при
помощи логических операций "И” и "ИЛИ” требует последовательного считывания
переменной в РОН, модификации и сохранения изменённого значения
в ОЗУ. Такой способ работы с битами, помимо большого объёма
действий, не является атомарным, то есть, не гарантирует нормальную работу с
переменной процессам, имеющим доступ к ней из обработчиков прерываний. Обращение
таких процессов не даст нужного результата, если доступ к переменной произойдёт внутри
цикла чтение – модификация - запись.
Для решения этой проблемы в архитектуре
STM
32 предусмотрен механизм "Bit Banding”,
обеспечивающий атомарный сброс и установку битов в ячейках
RAM
. Суть его заключается в том, что пространстве ОЗУ
микроконтроллеров
STM
32,
помимо области хранения данных имеется дополнительная область регистров каждый
из которых связан с отдельным битом в области хранения или в области
регистров ввода-вывода. При этом запись в указанный регистр нулевого значения
приводит к аппаратному сбросу соответствующего бита в области хранения
переменных, а запись ненулевого значения устанавливает
указанные биты.
Адреса регистров установки и сброса легко вычислить по номеру модифицируемого
бита и адресу переменной или регистра, по формуле:
BB_ADR =
SRAM_BB_BASE + ( (
ADR
- SRAM_BASE) *32) + (
BIT
* 4)
|
здесь:
SRAM
_
BASE
- базовый адрес области хранения;
SRAM
_
BB
_
BASE
- базовый
адрес области доступа к битам;
ADR
– адрес переменной,
BIT
– номер изменяемого бита переменной.
В приведённом примере макросы varSetBitBB, varClrBitBB и varGetBitBB осуществляют установку, сброс и проверку состояния битов переменной Flags через регистры Bit Banding:
#include
"stm32F10x.h"
#define
varClrBitBB(var, BitNumber)(*(vu32 *)\
(SRAM_BB_BASE | ((((u32)&var) - SRAM_BASE) << 5) | ((BitNumber) << 2)) = 0)
#define
varSetBitBB(var, BitNumber)(*(vu32 *)\
(SRAM_BB_BASE | ((((u32)&var) - SRAM_BASE) << 5) | ((BitNumber) << 2)) = 1)
#define
varGetBitBB(var, BitNumber)(*(vu32 *)\
(SRAM_BB_BASE | ((((u32)&var) - SRAM_BASE) << 5) | ((BitNumber) << 2)))
#define
FLAG0 0
// Флаг 0.
#define
FLAG1 1
// Флаг 1.
u32 Flags=(1<<FLAG1);
// Битовое поле.
int main (void)
{
varSetBitBB (Flags,FLAG0);
// Установить FLAG0.
// Если FLAG0 установлен, сбросить FLAG1.
if (varGetBitBB(Flags,FLAG0)) varClrBitBB(Flags,FLAG1);
}
|
|