§
|
> Битовый доступ Bit Banding |
Традиционный способ сброса и установки битов переменных ОЗУ при
помощи логических операций "И” и "ИЛИ” требует последовательного считывания
переменной в РОН, модификации и сохранения изменённого значения
в ОЗУ. Такой способ работы с битами, помимо большого объёма
действий, не является атомарным, то есть, не гарантирует нормальную работу с
переменной процессам, имеющим доступ к ней из обработчиков прерываний. Обращение
таких процессов не даст нужного результата, если доступ к переменной произойдёт внутри
цикла чтение – модификация - запись.
Для решения этой проблемы в архитектуре STM32 предусмотрен механизм "Bit Banding”,
обеспечивающий атомарный сброс и установку битов в ячейках RAM. Суть его заключается в том, что пространстве ОЗУ
микроконтроллеров STM32,
помимо области хранения данных имеется дополнительная область регистров каждый
из которых связан с отдельным битом в области хранения или в области
регистров ввода-вывода. При этом запись в указанный регистр нулевого значения
приводит к аппаратному сбросу соответствующего бита в области хранения
переменных, а запись ненулевого значения устанавливает
указанные биты.
Адреса регистров установки и сброса легко вычислить по номеру модифицируемого
бита и адресу переменной или регистра, по формуле:
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); }
|
|