There are some pieces of code that regularly appear when programming embedded systems. They are not really design patterns but rather small tricks that might be confusing the first time you see them.
Bit manipulation
Registers in peripherals typically have single bit fields. It is often needed to clear, set, test or toggle them.
brush: c
unsigned int reg;
reg &= ~(1 << offset); // Clear a bit
reg |= (1 << offset); // Set a bit
reg ^= (1 << offset); // Toggle a bit
if (reg & (1 << offset)) { /// Test a bit
// Bit is set
}
else {
// Bit is not set
}
Create a mask
You often need to create a mask with a certain width. The code below works even for fields that take the whole data width.
brush: c
const int width = 4;
unsigned int mask = ((1 << width) - 1); // mask = 0xf
Clear a field
Clearing a field of several bits in a variable.
brush: c
unsigned int reg;
const unsigned int mask = 0x3f;
const int offset;
reg &= ~(mask << offset);
Setting all bits in a field
Setting all bits in a field to 1.
brush: c
unsigned int reg;
const unsigned int mask = 0x3f;
const int offset;
reg |= (mask << offset);
Field access
When accessing a hardware register in a peripheral, this sequence is often used to extract a bit fields. The C standard has support for them though you still see them.
brush: c
const int offset = 3;
const unsigned int mask = 0x7f;
unsigned int data;
unsigned int field = (data >> offset) & mask; // Get a field
data = (data & (mask << offset)) | ((field & mask) << offset);
Circular buffer
When accessing a circular buffer, address increments can be done quickly if the size is a power of two.
brush: c
unsigned int offset;
offset = (offset + step) & ((1 << width) - 1);
Testing if a number is a power of two
Finding if a number is a power of two is easy.
brush: c
unsigned int number;
if ((number & (number - 1)) == 0) {
// power of two
}
else {
// non-power of two
}