Bit operations in general and Arm bit banding in particular
This article appeared in the process of writing a small library for working with the bit-banding mechanism for Cortex-M3/M4 processors.
Macros
Probably the most common way. With this method, special macros are created for operations with bits. The most common operations are: setting and clearing the bit. Then the following macros can be used as an example:
The usual bitwise operators of the c language are used here: `|`, `&`, `<<`, `>>`, `~`. Which hide assembler commands for working with bits:
However, the main problem is that in most cases the processor cannot manipulate single bits, i.e. it cannot change the bits stored in RAM in one command. The processor interacts only with registers and can perform all operations only on the data in the register. That is, setting/clearing a bit in a variable is an operation of the form read-modify-write, therefore they are not atomic. And in those cases when it is critical, all bit operations have to be placed in special critical sections. But if atomicity is not important for your code, then this method of working with bits is quite suitable.
Bit fields
Bit fields in c are declared using structures. They allow access to individual bits or groups of bits.
Bit field declaration syntax:
For example:
Each field can be accessed in the same way as the field of the usual structure. For example to set the 3rd bit:
The use of bit fields often simplifies the understanding of the program and working with it, but it is based on the same principle as when using macros: read-modify-write bit operations.
In addition, since bit fields are the structures, working with them contains a certain number of features related to alignment, the order of bytes in memory.
Target related features
Before that, we considered the methods of working with bits that the **c** language provides to us. These methods work on all architectures. But for a specific processor architecture, there may be its own specific methods of working with bits. We will consider some of them in this section.
Assembly instructions
The first and most probably logical method is to use separate processor instructions that would allow you to change individual bits directly in memory, doing it in one processor instruction. As an example, we can consider the commands for the AVR processor: `CBI`, `SBI`
领英推è
These commands allow you to work with individual bits in the I/O registers and this work will be carried out atomically. However, you can do this only with I/O registers. When working with the RAM, you will still need to use the methods described in the previous sections.
Bit Band
This method is implemented, for example, in Cortex-M3 and Cortex-M4 processors. And this is a kind of compensation for the lack of a special command to work with individual bits.
And if we take into account the fact that this method allows you to work atomically with bits not only I/O, but also bits stored in RAM, then I would even say that this method surpasses the convenience of using assembly instructions discussed in the last section.
The essence of this method is as follows. Special memory regions are located in SRAM and peripheral region, which are called bit-band region, and memory regions associated with these regions are called alias regions. And by writing a 32-bit number 1 to a certain address in alias regions, you can set a separate bit associated with this address in the bit-band region, and by writing 0 accordingly, you reset this bit.
According to documentation, the bit-band region occupies 1 MB of SRAM (from address 20000000h) and 1 MB of peripheral region (from address 40000000h), and the corresponding Alias regions occupy 31 MB of SRAM (from address 22000000h) and 31 MB of peripheral region (from address 42000000h), respectively.
This is the maximum possible size that the architecture supports, however, with a specific implementation by each vendor, the sizes of these areas may be smaller
Let's say you want to change the 5th bit of the RAM contents stored at address 20000000h. Since this is the first memory address from the bit-band domain, we can find the alias address pretty quickly. The first alias address is 22000000h, which is the address of the first (actually 0) bit in RAM. The 1st bit in the alias has the address 22000004h, the second bit is addressed 22000008h and so on. Thus, the fifth bit has an alias address of 22000014h. If you want to write or read a bit from an SRAM word, you need to write 1 to the RAM address 22000014h to set the 5th bit at the RAM location 20000000h. This also applies to the bit reading operation.
These transformations are made according to the following formula:
bit_word_offset = (byte_offset x 32) + (bit_number × 4)??
bit_word_addr = bit_band_base + bit_word_offset
Where:??
Bit_word_offset is the position of the target bit in the bit-band memory region.??
Bit_word_addr is the address of the word in the alias memory region that maps to??
the targeted bit.??
Bit_band_base is the starting address of the alias region.??
Byte_offset is the number of the byte in the bit-band region that contains the targeted bit.??
Bit_number is the bit position (0-7) of the targeted bit.
Embedded QA Engineer
2 å¹´Thanks for sharing