Bit-Reversing on EFM32/EFR32/EZR32 Microcontrollers

by <a href=""><font color="#000000"><font size="2">Hero Employee</font></font> </a> JohnB on ‎03-31-2017 10:31 AM

Bits in a (32-bit) word on ARM Cortex M-series CPU cores are ordered most-significant bit (MSB) first, where the MSB is the leftmost bit. Software is generally designed to handle data formatted in this fashion, e.g. a (two's complement) number is negative when its MSB is set.




There are some cases where MSB data needs to be reformatted with the bits reversed, say when communicating with certain hardware devices. The Sharp LS013B7DH03 memory LCD is such an example. It is organized as 128 lines of 128 pixels, and the lines, which are numbered from 1 to 128, must be shifted into the display LSB first.


So, while 1 logically references the topmost line of the display, the underlying hardware must be sent 0x80 (10000000 in binary) to address the pixels on this line.




While bit-reversing looks to be a simple operation at the hardware level, software implementations vary in simplicity, speed, and resulting code size. Even the size of the data that needs its bits reversed (byte, halfword, word, or longword) has an impact on the algorithm used. Consider the example implementations presented in this Stack Overflow article and at the Bit Twiddling Hacks web page.


Fortunately, bit reversal is a simple matter on ARM Cortex M3 and M4 cores courtesy of the RBIT instruction. RBIT simply reverses the bits in one of the CPU registers and stores them in the specified register. Better still, ARM has provided a CMSIS intrinsic function that allows C code to make direct use of RBIT, greatly simplifying and speeding up bit reversal.


So, consider the fragment of code below which is part of the update routine for a Sharp memory LCD. The serial bit stream sent to display must embed the line number prior to sending the pixels for that line. As noted above, the line numbers must be sent LSB first while the pixel data is sent MSB first. The EFM32 USART can switch between sending synchronous data MSB or LSB first, but it's easier to leave the hardware configured for MSB first transfers and to bit reverse the line number in the software as shown below:


uint32_t raw2pix, packpix, rfl, j, i, k, line, revline;

k = 1;
i = 0;
line = 1;

// First embedded update command
frame[0] = 0x80;

while (i < FRAMELEN)
  // Embed line number (LSB first)
   revline   = __RBIT(line);
   frame[k] = (uint8_t)(revline >> 24);

  // Work one raw frame buffer line (64 bytes) at a time
  rfl = 0;
  while (rfl < 128)

RBIT is a register instruction, so a 32-bit word is bit reversed. Because the display expects the line number to be sent as an 8-bit quantity, it's necessary to right shift the bit-reversed data into the lower 8 bits of the word and then cast the result as an unsigned 8-bit integer (or character) for embedding in the bit stream sent to the display.


Courtesy of the CMSIS intrinsic, the C compiler (GCC in the case of Simplicity Studio) elegantly translates this into nothing more than a register load, the RBIT instruction, and a register store into the specified variable.