AnsweredAssumed Answered

Bit-banding and register field handling made clear and simple

Question asked by Ben K on Mar 8, 2016
Latest reply on Mar 9, 2016 by dembek.radoslaw.001
Welcome everybody,

I have made some development on the CMSIS device descriptors:
- The bit fields are added for each register mapping C structure, so the bit fields appear as simple variables that can be read and written in the C code (the compiler will insert the necessary masking, shifting, etc. operations). An example of how it looks like:
typedefstruct { 
    __IO uint32_t DR; 
    __IO uint8_t IDR; 
         uint8_t __RESERVED0; 
         uint16_t __RESERVED1; 
    union { 
        struct { 
            __IO uint32_t RESET : 1; 
                 uint32_t __RESERVED0 : 2; 
            __IO uint32_t POLYSIZE : 2; 
            __IO uint32_t REV_IN : 2; 
            __IO uint32_t REV_OUT : 1; 
                 uint32_t __RESERVED1 : 24; 
        } b; 
        __IO uint32_t w; 
    } CR; 
         uint32_t __RESERVED2; 
    __IO uint32_t INIT; 
    __IO uint32_t POL; 
} CRC_TypeDef;
For example, the user code can read or write the CRC->CR.b.POLYSIZE field just like any other variable, which makes developing and understanding code much easier.

- The other advancement is to create the bit-band alias equivalents for the peripheral structures. This enables accessing single bits with one load or store operation. Let me demonstrate:
typedefstruct { 
    __IO uint32_t DR[32]; 
    __IO uint32_t IDR[8]; 
         uint32_t __RESERVED0[8]; 
         uint32_t __RESERVED1[16]; 
    struct { 
        __IO uint32_t RESET; 
             uint32_t __RESERVED0[2]; 
        __IO uint32_t POLYSIZE[2]; 
        __IO uint32_t REV_IN[2]; 
        __IO uint32_t REV_OUT; 
             uint32_t __RESERVED1[24]; 
    } CR; 
         uint32_t __RESERVED2[32]; 
    __IO uint32_t INIT[32]; 
    __IO uint32_t POL[32]; 
} CRC_BitBand_TypeDef; 
#defineCRC_BB         ((CRC_BitBand_TypeDef *) PERIPH_BB(CRC_BASE))
The PERIPH_BB macro converts the peripheral base address to the peripheral alias address. From there, the bit offset is provided by the nature of the C structure (every bit is word-addressed in the alias region). For example, to set the RESET bit of the CRC, one can write CRC_BB->CR.RESET = 1; and this will create a single store CPU operation in the binary.

This has only been a short introduction, I have created a GitHub repository where you can find a more detailed description with source code and example code as well:

There is a readme for the whole project, and a separate bit-banding explainer page. The STM32 device headers are created by a code parser and generator, so I cannot guarantee their correctness (only for the parts that are used by the XPD driver code). Keep in mind that this is an experimental (hobby) project at the moment. Further device headers may be published if requested. If you have any questions or suggestions I'm happy to be of service.

Best regards,