Home > ARM Cortex-M3, C/C++ > Bit-Banding Updated

Bit-Banding Updated

Last time, I wrote about bit-banding with ARM Cortex-Mx microcontrollers. Although I am not using my BitWord class in my current project, here is an improved, better documented and slightly better tested version of it:

// Copyright Software Integrity Ltd., 2013
#ifndef SWI_BIT_WORD_H
#define SWI_BIT_WORD_H

#include <limits>

    // These constants should really be declared as static members of BitWord,
    // but then I would have to publish the .cpp file as well, to show the
    // definitions.

    static unsigned int * const pBase
        = reinterpret_cast<unsigned int *>(0x20000000U);
    static unsigned int * const pAlias
        = reinterpret_cast<unsigned int *>(0x22000000U);

    // The following assumes that the number of bits in an unsigned int is a
    // power of 2. Actually, we know it is because it's definitely 32 for the
    // Cortex Mx!
    static unsigned int const mask
        = std::numeric_limits<unsigned int>::digits - 1;

    // class BitWord...
    // Allows bit-banded variables of type BitWord to be defined.
    // The individual bits of a BitWord can be read, set and cleared atomically.
    // Implicit Bitword<->unsigned int conversions are supported.
    // The user must ensure that all BitWord objects are actually located in the
    // valid memory bit-band area (0x200xxxxx).
    // This class does not work for the peripheral bit-band area (0x400xxxxx)!
    class BitWord
        // Constructor, which sets an initial value for the BitWord variable.
        // Also converts from unsigned int to BitWord type.
        BitWord(unsigned int value = 0):
            m_pBit(pAlias + ((&m_value - pBase) << 5))

        // Copy constructor.
        BitWord(const BitWord& orig):
            m_pBit(pAlias + ((&m_value - pBase) << 5))

        // Converts from BitWord to unsigned int.
        operator unsigned int() const volatile
            return m_value;

        // Assignment from BitWord.
        volatile BitWord& operator=(const BitWord& rhs) volatile
            m_value = rhs.m_value;
            return *this;

        // Assignment from unsigned int.
        volatile BitWord& operator=(unsigned int rhs) volatile
            m_value = rhs;
            return *this;

        // Given a bit index, sets that bit in the BitWord.
        // Forces index into valid range first.
        void setBit(unsigned int index) volatile
            index &= mask;
            m_pBit[index] = 1;

        // Given a bit index, clears that bit in the BitWord.
        // Forces index into valid range first.
        void clearBit(unsigned int index) volatile
            index &= mask;
            m_pBit[index] = 0;

        // Given a bit index, reads that bit from the BitWord.
        // Forces index into valid range first.
        unsigned int readBit(unsigned int index) const volatile
            index &= mask;
            return m_pBit[index];

        // Beware! Bit-indexing is not easy to re-implement on
        // microcontrollers without bit-banding.

        // Allows indexing of a BitWord object, e.g...
        //      BitWord x, y = 0x5a5a5a5aU;
        //      x[8] = y[3];
        // Forces index into valid range first.
        volatile unsigned int& operator[](unsigned int index) volatile
            index &= mask;
            return m_pBit[index];

        // Storage for the word-sized operand.
        volatile unsigned int m_value;

        // The aliased base address of m_value.
        volatile unsigned int * const m_pBit;

#endif // SWI_BIT_WORD
Categories: ARM Cortex-M3, C/C++ Tags: ,
  1. abhi
    Tuesday, May 7, 2013 at 18:27

    can m_value be a two dimensional(containing binary values) matrix? like m_value[12][8]. So that using bitbanding these bits of m_value can be set?

  2. Peter Bushell
    Tuesday, May 7, 2013 at 19:03

    Thanks for your comment, Abhi.

    I hadn’t really thought about it, but I don’t see why things couldn’t be configured that way, though the class would then need to be a template to set the array size for the unsigned ints. The other point I would make is that it would be m_value[x][32], the way I have things configured (for unsigned int rather than unsigned char, which would also be possible).

    What I’d prefer to see, as a tidier alternative, is an array of actual BitWord variables, where such a thing might be required – something like this:

    BitWord b[12];
    b[2][1] = 1U;

  3. abhi
    Wednesday, May 8, 2013 at 16:13

    thanks for your response. I have one more query.
    If im right, m_pBit stored the alias of the RAM addresses. Lets suppose there is a variable *add storing the address of a variable. Is it possible to set exactly one bit in this address? It would be great if you can provide an example.
    Thanks in advance..

  4. Peter Bushell
    Wednesday, May 8, 2013 at 17:46

    The C++ class above does not support this way of doing things; it expects you to create a BitWord variable, then access it, either as a word or one bit at a time.

    However, I did write a couple of functions to set and clear bits in a word whose address was given as an argument. I’m not putting those on the blog (unless the demand is overwhelming!) but I’ll send you the code by email.

  5. abhi
    Wednesday, May 8, 2013 at 17:49

    that would be great. thank you 🙂

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: