Розвернути біти

Так чи інакше, а ця задачка вилазить.

В моєму випадкові потреба виникла тому, що Altera FPGA при завантаженні по SPI вимагає потік молодшим бітом вперед, а порт SSP мікроконтролерів LPC17 працює лише старшим бітом вперед. Якраз нещодавно на форумі хтось обурювався, що у STM8 USART в режимі SPI працює лише молодшим бітом вперед: «і кому такий SPI потрібен?». Та от, мені…

Як я вже писав у публікації Двійкові дані та програма мікроконтролера (це що, я так довго не повертався до цієї роботи?), можна було б зробити власну програму обробки конфігураційного масиву FPGA, в якій врахувати також і порядок бітів. Але пристрій може отримувати прошивки програмованої логіки ззовні, тому хотілося б приймати файли в такому вигляді, в якому їх видає Quartus. Менше буде плутанини.

На щастя, Cortex-M3 має спеціальну команду розвороту бітів. Ця команда міняє порядок бітів у 32-бітному регістрі, 0-вий біт стає 31-шим, 1-ий — 30-тим і так далі. Тобто для того, щоб розвернути біти в одному байті, результат команди rbit треба зсунути вправо на 24 біти (тут і далі використовуються макроси з файлу від ARM core_cmIntsr.h, який включається до файлу core_cm3.h і вже через нього до LPC17xx.h від NXP):

    // Bit reverse in one byte
    uint32_t v;
    v = __RBIT(v) >> 24;

Cortex-M3 — bit reverse in one byte.

У кортексів, навіть у Cortex-M0, є ще команди обернення порядку байтів у 32-бітному та 16-бітному словах, rev та rev16 відповідно. Основне їх призначення — перехід від мережевого (big-endian) до внутрішнього (little-endian) порядку байтів. Нам команда rev допоможе парою команд розвернути біти відразу у чотирьох байтах, не міняючи їх порядку у слові:

    // Bit reverse in four bytes at once
    uint32_t v;
    v = __REV(__RBIT(v));

Cortex-M3 — bit reverse in four bytes at once

Так можна готувати дані для побайтового виводу конфігураційного масиву у FPGA.

Якщо ж хочеться використати 16-бітний режим SSP, то доведеться врахувати, що він, починаючи передачу зі старшого біту, розверне порядок байтів у парі. Тобто після реверсу порядку бітів (який одночасно зробить і реверс порядку байтів) слід просто взяти старші 16 біт 32-бітового слова. Це можна зробити зсувом на 16 біт.

Я ж завантажую у SSP по одному слову, тому зупинився на реверсі бітів у 16-бітному слові (половині регістра):

    // Bit reverse in 16-bit halfword
    uint16_t *pdata;
    uint32_t v = *pdata++;
    v = __RBIT(v) >> 16;

Cortex-M3 — bit reverse in 16-bit halfword

Далі SSP виводить 16 біт змінної починаючи зі старшого, тобто два байти з конфігурації йдуть у потрібному порядку, спочатку молодший байт молодшим бітом вперед, за ним старший байт.

Leave a Reply

[flagcounter image]