cancel
Showing results for 
Search instead for 
Did you mean: 

Static RAM BitBanding Macro

tmall
Associate II
Posted on April 17, 2010 at 20:22

Static RAM BitBanding Macro

#stm32 #stm32 #bitbanding #bitbanding #bitbanding #bitbanding #stm32 #stm32
11 REPLIES 11
budzyn
Associate
Posted on May 17, 2011 at 13:47

Hi,

You may look at: ''http://www.freddiechopin.info/index.php/pl/download/category/6-przyklady'' (click stm32_blink_led link). It is an example project using bitbanding, gpios, etc. without STM32F10x Standard Peripherals Library (take a look at the gpio configuration macros - they are wonderfull). The web page is in Polish, but the comments in the project are in English

Below is the header file with bitbanding macros from this project:

/** \file hdr_bitband.h

 * \brief Header for bit-banding

 * \author Freddie Chopin

 * \date 2009-09-19

 */

/******************************************************************************

* chip: ARM Cortex-M3

* compiler: arm-none-eabi-gcc 4.3.3

******************************************************************************/

#ifndef HDR_BITBAND_H_

#define HDR_BITBAND_H_

/*

+=============================================================================+

| global definitions

+=============================================================================+

*/

#define BITBAND_SRAM_REF               0x20000000

#define BITBAND_SRAM_BASE              0x22000000

#define BITBAND_PERIPH_REF               0x40000000

#define BITBAND_PERIPH_BASE              0x42000000

/*

+=============================================================================+

| strange variables

+=============================================================================+

*/

#define bitband_t *(volatile uint32_t*)

/*

+=============================================================================+

| macros

+=============================================================================+

*/

#define m_BITBAND_SRAM(address,bit)        (BITBAND_SRAM_BASE +   (((uint32_t)address) - BITBAND_SRAM_REF) * 32 + (bit) * 4)

#define m_BITBAND_PERIPH(address,bit)        (BITBAND_PERIPH_BASE + (((uint32_t)address) - BITBAND_PERIPH_REF) * 32 + (bit) * 4)

/******************************************************************************

* END OF FILE

******************************************************************************/

#endif /* HDR_BITBAND_H_ */

Best Regards, 

tmall
Associate II
Posted on May 17, 2011 at 13:47

Greetings Celetron:

    Thank you for your informative response! I reviewed the source files and agree that the macros are very nicely done. The author uses the bitBand for efficient GPIO pin control. The GCC compiler handles peripheral bitBanding very efficiently. Note that in the case of GPIO pins the set/reset registers can alternatively be used for controlling the pin outputs directly.

    In the case of RAM bitBanding GCC generates roughly the same amount of program code for bitBanding as using AND/OR statements for pointing to the flag bit within the containing word.

    My understanding now, which is based on the information I have received from those with much higher knowledge than myself, is that there is a fundamental issue with regards to bitBand address determination for variables. As the addresses for variables are assigned by the linker following the execution of the compiler pre-processor the address value is not available for the pre-processor to simply do the associated biBand address calculation. GCC currently passes that job on to the STM32 in the form of several additional ASM instruction steps. 

    Apparently it is possible for the pre-processor to do the calculation but it would require specialized, hardware specific compiler code. It apparently is a complicated matter that would require much work with limited return for the effort. BitBanding can still be used with GCC to save a bit of RAM space but at the expense of speed and program code memory. If speed is an issue then byte size variables can be used for single bit semaphore flags at the expense of a little bit of RAM which is usually available anyway. IMHO unless RAM space is an issue the use of byte size variables for semaphore flags is probably the best choice at this point in time when using the GCC compiler for Cortex M3 applications.

    Thanks goes to the many that helped me gain this understanding.

Best Regards,

Tom Alldread

Posted on May 17, 2011 at 13:47

Or, you could assign it to a pointer (either local or global), and access it through the pointer. If done locally, it would probably reside in a register. If you are using it once it probably won't be of benefit, but if you want to repetitively bang a GPIO pin up/down it would be quite effective.

-Clive

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
tmall
Associate II
Posted on May 17, 2011 at 13:47

Hi Clive:

    Thanks for the suggestions!

    Although I think all of your suggestions would work IMHO the assignment of an 8 bit global variable per semaphore option is conditionally the best alternative for the GCC ARM compiler I use.

    I tried using a local pointer during my testing but found that method didn't save instruction cycles as the STM32 still needed to calculate the bitBand RAM address to load the pointer each time the function is called. In addition the pointer for each single bit flag would need to occupy a 32 bit space in non volatile memory somewhere during the function execution period.

    The use of a global pointer loaded during initialization would use 4 bytes of RAM for every flag bit address. It would also require STM32 instructions for the macro calculation at the onset.

    Thanks again for your suggestions! Just thinking about new alternatives helps me.

Best Regards,

Tom Alldread

Posted on May 17, 2011 at 13:47

''GCC currently passes that job on to the STM32 in the form of several additional ASM instruction steps. Apparently it is possible for the pre-processor to do the calculation but it would require specialized, hardware specific compiler code.''

 

Have you looked at how Keil, IAR, and other specifically embedded compilers treat this?

It is my personal impression that GCC strives to be generalist & ''standard'' as its key aim - but that often does not give the most desirable results for embedded (especially small embedded - as suited to the STM32) applications.

Because compilers like Keil, IAR, et al are specifically targetted at embedded applications, they tend to handle this kind of stuff more appropriately...

''It apparently is a complicated matter that would require much work with limited return for the effort.''

 

I guess the ''return on the effort'' would be of far more value to specifically embedded compilers...?

epassoni950
Associate II
Posted on May 17, 2011 at 13:47

Hello,

You can have compact code if you reserve a block at an absolute address and you affect bit for bitbanding access in this block. In this case, compiler can calculate bitbanding address at compilation time like for bitbanding in peripheral registers.

You must note that reading a bit with bitbanding cost no more time than reading a boolean with normal address. But for write access, you must note that if even if there is only one instruction STR, core generate a read/modify/write access to modify only one bit in a word. Ram and peripheral register don't have bit access. For that, controlling GPIO pin is more efficient with BRR and BSRR registers than with bitbanding.

A very important advantage with bitbanding is that read/modify/write access is not interruptible. So if you want to change only a bit in a peripheral register or in Ram word sometime in main thread and sometime in interrupt handler it is not necessarry to disable interrupt for modify bit.

Best regards

Eric
tmall
Associate II
Posted on May 17, 2011 at 13:47

Greetings Eric:

    Thanks for what sounds like a possible solution!

    The reserving of a block of RAM at a pre-defined address for the words that contain the flags has potential for providing the value the pre-processor needs to do the bitBand address calculation prior to linking. I would like to experiment with this suggestion. I guess it depends on whether or not the GCC pre-processor will use it.

    Does standard C support the specification of an address for a variable in advance? I do not know how to do this. Do you have time to point me to some example code?

    Thanks again!

Best Regards,

Tom Alldread

    

Posted on May 17, 2011 at 13:47

If you want to control addresses, the linker may be the place to look.

In C you can use casts to set addresses

unsigned char *foo = (unsigned char *)0x2000F000;

typedef struct _BAR

{

    uint32 a;

    uint32 b;

    uint32 c;

    uint32 d;

} BAR;

BAR *bar = (BAR *)0x2000E000;

bar->a = 1;

bar->b = 0;

bar->c = 1;

bar->d = 1;

Or you could use two parallel structures, one for byte access and the other for bit access. It does strike me as overly complicated. I think bit banding is more aimed at assembler efficiency, or the atomic R-M-W mentioned earlier.

-Clive
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2011 at 13:47

''Does standard C support the specification of an address for a variable in advance?''

 

No, it doesn't.

Compilers that do so do it as an extension