STM32: Bit Banding

6 хв. читання

В статті ми будемо розглядати Bit Banding та зупинимось на таких питаннях:

  • Технологія Bit Banding
  • Використання Bit Banding
  • Bit Banding масив
  • Допустимі значення

Технологія Bit Banding

Bit Banding – технологія, що зв'язує окремий біт регістру або проміжку пам'яті (SRAM) з Bit Banding регіоном в пам'яті контролера та дозволяє керувати ним. Все це працює, так би мовити, з "коробки" та не потребує ініціалізації або якихось додаткових дій, окрім вирахування адреси потрібної частини Bit Banding. Але про все по порядку. Розглянемо невеликий приклад. Припустимо, що ми зв'язали деяку змінну BitBandingGPIOA5 з п'ятим бітом порту А (нехай порт А буде складатися з восьми біт). Тепер спробуємо змінити значення BitBandingGPIOA5:

BitBandingGPIOA5 = 0x01; // порт А тепер виглядає так:  0b00100000
BitBandingGPIOA5 = 0x00; // порт А тепер виглядає так:  0b00000000

Якщо спробувати прочитати значення змінної BitBandingGPIOA5, то ми побачимо, що вона буде приймати значення 0x00 або 0x01, залежно від значення п'ятого біту порту А.

Поглянемо, як це виглядає з середини. Припустимо, що адреса порту А буде 0x4001080С, а адреса початку регіону Bit Banding, відповідального за порт А, 0x42021180. Схематично відношення Bit Banding секції до порту А, буде виглядати так: enter image description here Сподіваюсь, що сама концепція зрозуміла. Тепер про те, як це все використовувати.

Використання Bit Banding

Головна задача програміста у даному випадку – це вирахувати адрес у Bit Banding регіоні, що відповідає за значення потрібного біту. Сама формула розрахунку наведена в офіційній документації до STM32, ось вона:

bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4);

Поглянемо докладніше:

  • bit_word_addr – адрес у Bit Banding регіоні
  • bit_band_base – початок (база) Bit Banding регіону
  • byte_offset – зсув адреси порту чи частини пам'яті відносно початку (бази) секції де розташовано потрібний регістр або проміжок пам'яті.
  • bit_number – номер біту, яким ми хочемо керувати (нагадую: нумерація починається з нуля: 0, 1, 2, 3 і так далі).

Маючи цей "пінцет" в наших руках, можемо починати практикуватися. Для початку з портом вводу/виводу (GPIO). Я використовую контролер STM32F100C8, тому всі адреси портів, регістрів та в середині пам'яті будуть стосуватися саме цього контролеру. Отже, спробуємо керувати уявним діодом, що підключено до п'ятого виводу ("біту") порту GPIOA. Треба зауважити, що, наприклад, адреса порту GPIOA буде 0x40010800, але дана адреса вказує лише на групу регістрів, що відносяться до порту GPIOA. Для керування діодом, нам потрібна адреса самого регістру вводу/виводу порту (який впливає на виводи контролера). Цей регістр називається ODR. Згідно документації, зміщення цього регістру, відносно адреси порту, дорівнює 0x0C.Також, дивимось адресу початку регіону Bit Banding для периферійних пристроїв – 0x42000000, та адресу початку регіону самих периферійних пристроїв – 0x40000000 . Маємо:

bit_band_base = 0x42000000;
byte_offset   =  (0x0C + 0x40010800 — 0x40000000); //0x01080C
bit_number    =  0x05;
bit_word_addr = 0x42000000 + (0x01080C * 32) + (0x05 * 4);

Запишемо тепер це все на C:

#define PERIPH_BB_BASE	0x42000000
#define GPIOA_OFFSET	0x01080C
#define BIT_NUM		0x05
#define PINA (*(volatile uint32_t *)(PERIPH_BB_BASE + (GPIOA_OFFSET * 32) + (BIT_NUM * 4)))

Тепер використовуючи нашу константу PINA, можемо написати:

PINA = 0x01;

Що встановить п'ятий біт регістру ODR порту GPIOA і потрібний нам біт буде дорівнювати 0x01. Діод включено! Аналогічно записавши 0x00 ми очистімо біт.

PINA = 0x00; //діод більше не горить, п'ятий біт ODR дорівнює нулю

Bit Banding масив

Але можемо піти ще далі. Поглянемо на наш дефайн PINA.(BIT_NUM * 4) – це зміщення відносно позиції Bit Banding регіону, що відповідає нульовому біту ODR. Якщо прибрати його з розрахунку, та не розіменувати вказівник, ми отримаємо адресу масиву, який складається з 32-бітних слів, що відповідають кожному біту, у нашому випадку, регістру ODR порту GPIOA.

#define PERIPH_BB_BASE	0x42000000
#define GPIOA_OFFSET	0x01080C
#define PINA ((volatile uint32_t *)(PERIPH_BB_BASE + (GPIOA_OFFSET * 32)))

Тепер, ми можемо звертатись до PINA, як до масиву:

PINA[1] = 0x01; // біт номер один встановлено
PINA[1] = 0x00; // біт номер один очищено
PINA[0] = 0x00; // нульовий біт очищено
PINA[7] = 0x01;  // сьомий біт встановлено

І згадаємо про XOR. Для того, щоб змінювати стан біту з 0x00до 0x01 і навпаки:

PINA[1] ^= 0x01; //в циклі ця команда, буде "переключати" значення біту 1

Отже, таким чином маємо доступ до будь-якого біту потрібного нам регістру чи області пам'яті.

Допустимі значення

Наостанок ще одна невелика ремарка. Оскільки у відповідність до біту Bit Banding ставить 32-бітне слово, то зрозуміло, що в нього можна записати не лише 0x01 або 0x00. Будь-яке число у діапазоні від 0 до 4294967295 може бути записане у Bit Banding секцію. Але процесор у будь-якому випадку бере до уваги лише нульовий біт Bit Banding слова відповідального за біт. Тобто, має значення чи число є парним чи непарним. Уявімо, що ми маємо Bit Banding байт (назвемо його BBOdr2), що зв'язаний з другим бітом регістру ODR (нехай теж буде 8-бітний) деякого порту:

BBOdr2 = 0b00000000;
ODR = 0b00000000;

Запишемо в BBOdr2 парне число, наприклад 10:

BBOdr2 = 0b00001010;

У цьому випадку нульовий біт BBOdr2 не змінився і тому ODR теж залишився без змін. Тепер запишемо непарне число 11 у BBOdr2:

BBOdr2 = 0b00001011;

Нульовий біт встановлено і він дорівнює одиниці, тому ODR тепер має вигляд:

ODR = 0b0000100; 

Також треба пам'ятати, що неважливо, яке число було записано в BBOdr2, все одно, результат зчитування значення BBOdr2 буде або 0x00, або 0x01.

Звичайно, незважаючи на все вище викладене, краще використовувати 0x00 та 0x01 для очищення та встановлення біту, але знати про поведінку з не зовсім передбачуваними значеннями теж не буває зайвим.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 629
Приєднався: 1 рік тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід