Understanding the operation of STM32 bit band

Publisher:RadiantSerenityLatest update time:2017-10-01 Source: eefocusKeywords:STM32  bit  band Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

    With the support of bit operations in the Cortex-M3, single bits can be read and written using normal load/store instructions.
  In the bit-banding supported by the CM3, bit-banding is implemented in two regions.
  One is the lowest 1MB range of the SRAM region, 0x20000000 ‐ 0x200FFFFF (the lowest 1MB in the SRAM region);
  the second is the lowest 1MB range of the on-chip peripheral region, 0x40000000 ‐ 0x400FFFFF (the lowest 1MB in the on-chip peripheral region).
  In addition to being able to use the addresses in these two regions like normal RAM, they also have their own "bit-band alias region", which expands each bit into a 32-bit word. When you access these words through the bit-band alias region, you can achieve the purpose of accessing the original bit.
  CM3 uses the following terms to represent the addresses associated with bit-band storage: 
  * Bit-band region: Address region that supports bit-band operations 
  * Bit-band alias: Access to the alias address ultimately affects access to the bit-band region (note: there is an address mapping process in between).
  Each bit in the bit-band region is mapped to a word in the alias address region - this is a word with only the LSB being valid (only the least significant bit of the word in the bit-band alias region is meaningful).
  For a certain bit in SRAM,
  the address of the bit in the bit-band alias area is: AliasAddr = 0x22000000 + ((A-0x20000000)*8+n)*4 
                                                = 0x22000000 + (A-0x20000000)*32 + n*4For 

    a certain bit in the on-chip peripheral bit-band area,
  the address of the bit in the bit-band alias area is: AliasAddr = 0x42000000 + ((A-0x40000000)*8+n)*4 
                                                   = 0x42000000 + (A-0x40000000)*32 + n*4Where 
  A is the address of the byte where the bit is located, 0 <= n <= 7
"*4" means that a word is 4 bytes, and "*8" means that there are 8 bits in a byte.

Of course, bit-band operations are not limited to word-based transfers. It can also be transferred in half-word and byte units. 

  Bit-banding operations have many benefits, one of which is that they are used to implement "interlocked" access to shared resources between tasks in a multi-tasking system. Multi-tasking shared resources must satisfy the requirement that only one task accesses it at a time - the so-called "atomic operation". 

  Using bit-banding operations in C language
  There is no direct support for bit-banding operations in the C compiler. For example, the C compiler does not know that the same block of memory can be accessed using different addresses, nor does it know that access to the bit-band alias area is only valid for the LSB.
  To use bit-banding operations in C, the simplest way is to #define the address of a bit-band alias area. For example:

    #define DEVICE_REG0 ((volatile unsigned long *) (0x40000000)) 
    #define DEVICE_REG0_BIT0 ((volatile unsigned long *) (0x42000000)) 

    #define DEVICE_REG0_BIT1((volatile unsigned long *) (0x42000004)) ...

    *DEVICE_REG0 = 0xab; //Use normal address to access register 
        *DEVICE_REG0_BIT1 = 0x1;  

It can be simplified further:
    //Macro to convert "bit band address + bit number" into alias address
    #define BITBAND(addr, bitnum)((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF)<<5)+(bitnum<<2))  
    //Convert the address into a pointer
    #define MEM_ADDR(addr) *((volatile unsigned long *) (addr))
    So:
    MEM_ADDR(DEVICE_REG0) = 0xAB; //Use normal address to access register  
              MEM_ADDR(BITBAND(DEVICE_REG0,1)) = 0x1; //Use bit band alias address

  Note: When you use the bit band function, the variable to be accessed must be defined with volatile. Because the C compiler does not know that the same bit can have two addresses, volatile is used to make the compiler write the new value to the memory faithfully every time, instead of using registers to operate the copy of the data in the middle for optimization reasons, and writing the copy back at the end.

As follows:
// Convert "bit segment address + bit number" to an alias address macro 
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
//Convert the address into a pointer 
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) 
#define BIT_ADDR(addr, bitnum) MEM_ADDR( BITBAND(addr, bitnum) ) 
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C 
#define PA0 BIT_ADDR(GPIOA_ODR_Addr, 0) //Output
the above addr to represent the bit The address of the band ranges from 0x20000000 to 0x200FFFFF, 0x40000000 to 0x400FFFFF,

addr &0xFFFFF table extracts the offset bits, and the upper 12 bits (000) are masked.


  Bit band alias, 32MB in total; Bit band region, 1MB in total; the correspondence between the two is easy to understand, 1 word is 32 bits, each bit in 32 bits is expanded into one word, then one word in the bit band region requires 32 words in the bit band alias, so it is not difficult to understand that 1MB of bit band corresponds to 32MB of bit band alias region.
  I checked the lowest 1MB of Peripheral, starting from 0x4000_0000 to 0x4010_0000. It includes all peripheral registers, that is, all peripheral registers can be viewed using the bit alias region.

    Page 89 of the ARM Cortex-M3 Authoritative Guide lists two equations for calculating the address of the bit-band alias region, such as the Peripheral calculation:

AliasAddr=0x42000000+((A-0x40000000)*8+n)*4=0x42000000+(A-0x40000000)*32+n*4;

In fact, I understand that the latter way of writing is easier to understand.
AliasAddr=0x42000000+(A-0x40000000)*32+n*4,
0x42000000 is the starting address of the bit alias area;
(A-0x40000000)*32, A is the register address, subtracting the starting address, we can get the total number of words offset, each word has 32 bits, we can calculate the starting address of the relative register; n*4, similarly, each bit occupies 4 bytes, and the number of bits is multiplied by 4 to get the offset address of the register; one bit occupies 32 bits in the alias area, four bytes. In
  the example on page 91 of the English content of Cortex_M3, 0x23FFFFE0=0x22000000+(0xFFFFF*32)+0*4;

I think this way of writing is easier to understand. Excluding the base address of the entire peripheral, only the offset address is calculated, which is relatively easier to understand.

  In GCC and RealView MDK (Keil) development tools, it is allowed to manually specify the address of a variable when defining it. For example:
     volatile unsigned long bbVarAry[7]__attribute__(( at(0x20003014) ));
     volatile unsigned long* const pbbaVar= (void*)(0x22000000+0x3014*8*4);
     // The "const" after long* tells the compiler that the pointer can no longer be modified to point to another address.
     // Note: The address in at() must be aligned to a 4-byte boundary.
  In this way, 7 words are allocated at 0x20003014, resulting in a total of 32*7=224 bits.

  When using these bits, you can use the following form:
    pbbaVar[136]=1; //Set bit 136
  However, this has a limitation: the compiler cannot check whether the subscript is out of bounds.
  This is also a limitation of the compiler: it does not know that this array is actually bbVarAry[7], so it will count 224*4 bytes more when calculating the memory usage of the program.
  For pointers, give each bit to be used a literal name, and only use literal names in the subscript instead of actual numbers, which can greatly avoid array out-of-bounds. 
  Please note: when defining these "two" variables, "volatile" is added in front. If you no longer use bbVarAry to access these bits, but only use bit-band aliases to access them, these two volatiles are no longer needed.


Keywords:STM32  bit  band Reference address:Understanding the operation of STM32 bit band

Previous article:Things to note when porting STM32F05x to GD32F1x0
Next article:STM32F enters STOPMode method and precautions after waking up

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号