cancel
Showing results for 
Search instead for 
Did you mean: 

C compilers and bit banding

zeetahhs
Associate II
Posted on September 24, 2009 at 20:58

C compilers and bit banding

#bit-banding #bit-banding #cubemx
6 REPLIES 6
zeetahhs
Associate II
Posted on May 17, 2011 at 13:24

Are there any C compilers which take advantage of bit banding?

Ideally, the compiler/linker would know that a variable (and special function register) is located in the bit banding area and depending on what is being done with the variable, it would use the proper access method.

Thanks.

Harjit

joseph239955
Associate II
Posted on May 17, 2011 at 13:24

Keil MDK-ARM and RealView Development Suite has included bit band feature.

But it is not as smart as what you described

http://www.keil.com/support/man/docs/armccref/armccref_babcbgfc.htm

st3
Associate II
Posted on May 17, 2011 at 13:25

There is currently a discussion on the Keil forum about this very thing:

http://www.keil.com/forum/docs/thread15604.asp

nmadinger
Associate II
Posted on March 20, 2015 at 14:39

I know this post is dated, but does any know if there are plans to build the bit banding into the mxCube configuration software.  I am concerned that if I go through all the trouble to implement bit banding, and then have to move to another STM32 micro (Cortex - M3 or greater), this will be lost.

And/Or is this now a feature of the Keil compiler and a non-issue?

 

Posted on March 20, 2015 at 15:28

Bit-banding is rather problematic because it's implementations specific. The compiler doesn't know what memory is going to end up where, that's the linker's job.

It's highly problematic with peripherals, and honestly not that efficient.

Where it shines is atomic semaphore/mutex type situations. I would suggest highly localizing that code, and using inline or define-macro type approaches to avoid headaches porting.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jpeacock
Associate II
Posted on March 20, 2015 at 18:50

Bit-banding doesn't really require any special compiler support. For the Cortex M reserve a section of SRAM for 1 bit variables, and then define in the link loader memory map a region that corresponds to the bit band alias for that SRAM section. In the compiler assign variables to that bitband section and you have 32 bit unsignedlongs that work as single bit variables. I do this for both regular SRAM and the 4K backup RAM in an F4.

/* DuoMotion.ld Link configuration 
2014/03/18 Loader script for (STM32F405) board 
Memory Spaces Definitions 
The STM32F405VG has one flash bank, 1MB at 0x08000000. 
CCM (Core Coupled Memory) SRAM bank, 64KB at 0x10000000 
One time programmable flash, 512 + 16 bytes at 0x1FFF7800 
User options, 16 bytes at 1FFFC000 
Primary SRAM bank, size 112KB, at 0x20000000 
Auxilliary SRAM bank, size 16KB, at 0x2001C000 
Backup SRAM bank, size 4KB, at 0x40024000 
Backup registers, size 20 (80 bytes), at 0x400028 
The FLASH0 space is used for a DFU field update bootstrap. The FLASH1 space is used 
for two images of field modified configuration parameters. The main firmware image 
is loaded into the FLASH memoy region. 
Bitband regions map single bits from SRAM and peripheral registers 
to a word in an aliased memory region. BitBand regions are used 
to create single bit variables that align on word boundaries. 
The upper 256 bytes of SRAM1 (0x2001AF00) are reserved for single bit objects, 
using the BitBand alias feature in the Cortex M. 256 bytes or 2K bits tanslates to 
8KB (4 bytes or 1 word per bit). 
SRAM BitBand Alias, size 8KB (4 * 8 * 256), at 0x2235E000 
The upper 128 bytes of BKPSRAM (0x40004F80) are reserved for 1K single bit objects, 
using the BitBand alias feature in the Cortex M. 
BKPSRAM BitBand Alias, size 4KB (4 * 8 * 128), at 0x4249F000 
The last register in BKPREG (0x4000289C) is reserved for 32 single bit objects, 
using the BitBand alias feature in the Cortex M. 
BKPREG BitBand Alias, size 32 (4 * 8 * 128), at 0x42051380 
Special note: CCM does not support BitBand. 
The system stack (MSP) is set to the top 4KB of CCM space on reset. The 
large system stack is to accomodate nested interrupts 
The flash memory is organized into sectors: 
Sectors 0-3, 16KB each 
Sector 4, 64KB 
Sector 5-11, 128KB each 
Sectors 0 and 1 hold DFU utility. 
Sectors 2 and 3 are reserved for INFOMEM data parameters (one image per sector). 
Sectors 4-11 are for code storage, firmware image. 
*/ 
MEMORY 
{ 
FLASH0 (rx): ORIGIN = 0x08000000, LENGTH = 32K 
FLASH1 (w): ORIGIN = 0x08008000, LENGTH = 32K 
FLASH (rx): ORIGIN = 0x08010000, LENGTH = 960K 
CCM (w): ORIGIN = 0x10000000, LENGTH = 64K 
OTP (w): ORIGIN = 0x1FFF7800, LENGTH = 512 
OTPLOCK (w): ORIGIN = 0x1FFF7A00, LENGTH = 16 
SRAM1 (wx): ORIGIN = 0x20000000, LENGTH = 0x1AF00 
SRAM2 (w): ORIGIN = 0x2001C000, LENGTH = 16K 
SRAMBB (w): ORIGIN = 0x2235E000, LENGTH = 8K 
BKPSRAM (w): ORIGIN = 0x40024000, LENGTH = 0xF80 
BKPREG (w): ORIGIN = 0x40002850, LENGTH = 0x4c 
SNMPBB (w): ORIGIN = 0x4249F000, LENGTH = 4K 
BKPBB (w): ORIGIN = 0x42051380, LENGTH = 128 
} 
/* Sections Definitions */ 
SECTIONS 
{ 
/* DFU updater utility */ 
.progid : 
{ 
. = ALIGN(4); /* word align */ 
_sflash0 = .; /* start of flash sector 0 */ 
KEEP (*(.dfu_vector)) /* place Cortex M vectors first */ 
. = ALIGN(4); /* word align */ 
*(.dfu .dfu.*) /* DFU updater */ 
_eflash0 = .; /* end of flash sector 1 */ 
} > FLASH0 
/* Main program code and constants */ 
.text : 
{ 
_sflash1 = .; /* start of flash sector 4 */ 
_stext = .; 
. = ALIGN(4); /* word align */ 
KEEP (*(.isr_vector)) /* place Cortex M vectors first */ 
*(.progid .progid.*) /* firmware ID */ 
*(.text .text.*) /* followed by program code */ 
*(.dict*) /* followed by object dictionary */ 
*(.devices*) /* followed pump database */ 
*(.ARM.exidx* .gnu.linkonce.armexidx.*) 
. = ALIGN(4); /* word align */ 
_etext = .; /* end of code */ 
} > FLASH 
.rodata : 
{ 
. = ALIGN(4); /* word align */ 
*(.rodata .rodata.*) /* followed by constants */ 
. = ALIGN(4); /* word align for fast init */ 
_sidata = .; /* followed by runtime init */ 
} > FLASH 
/* start of initialization for RAM 
RAM sections are word aligned at start and end so that initialization loops 
may use whole words for the copy. Data is copied from FLASH into SRAM1 to 
initialize RAM variables in C runtime. */ 
.data : AT (_sidata) 
{ 
_sdata = .; /* start runtime init data */ 
*(vtable) /* not used */ 
. = ALIGN(4); /* word align for code */ 
_srwdata = .; /* start of code in SRAM */ 
*(.rwcode) /* code executing in SRAM */ 
. = ALIGN(4); /* word align */ 
_erwdata = .; /* end of code in SRAM */ 
*(.data*) /* initialized data */ 
. = ALIGN(4); /* word align for fast init */ 
_edata = .; /* end runtime init data */ 
} > SRAM1 
_sfcode = _sidata + (_srwdata - _sdata); /* code init in flash */ 
_sfdata = _sidata + (_edata - _sdata); /* infomem init in flash */ 
/* Configuration parameter defaults 
INFOMEM is initialized from FLASH when no saved parameters are available. The 
FLASH image is cpied to INFOMEM in SRAM1 inside the application. */ 
.infomem : AT (_sfdata) 
{ 
. = ALIGN(4); /* word align, follows runtime init */ 
_sinfo = .; /* start working configuration parameters */ 
*(.infomem*) /* default field parameters */ 
. = ALIGN(4); /* word align for fast init */ 
_einfo = .; /* end working config parameters */ 
} > SRAM1 
_eflash1 = _sfdata + (_einfo - _sinfo); /* end of last flash sector with data */ 
/* the BSS section is for zeroed RAM */ 
.bss (NOLOAD) : 
{ 
. = ALIGN(4); /* word align for fast clear */ 
_sbss = .; 
*(.bss*) /* zeroed RAM, no initialization */ 
*(COMMON) 
. = ALIGN(4); /* word align */ 
_ebss = .; 
} > SRAM1 
/* DMA buffers */ 
.cached (NOLOAD) : 
{ 
. = ALIGN(4); /* word align */ 
*(.cached*) /* DMA buffers, cache */ 
_end = .; /* end of SRAM1 */ 
} > SRAM1 
.nocache (NOLOAD) : 
{ 
. = ALIGN(1024); /* 1KB DMA align */ 
*(.dma1K*) /* DMA buffers, no cache, 1KB align */ 
. = ALIGN(4); /* DMA word align */ 
*(.nocache*) /* DMA buffers, no cache */ 
} > SRAM2 
/* the RAMBB section is used to allocate SRAM bit flags as words */ 
.rambb (NOLOAD) : 
{ 
. = ALIGN(4); /* word align BitBand alias start */ 
_srambb = .; 
*(.rambb*) /* volatile boolean flags */ 
. = ALIGN(4); /* word align for init */ 
_erambb = .; 
} > SRAMBB 
/* the HEAP section is used for RTOS objects, no DMA, no initialization, no bitband */ 
.heap (NOLOAD) : 
{ 
. = ALIGN(4); /* word align */ 
KEEP (*(.eh_frame)) /* error handler frame for GCC */ 
. = ALIGN(8); /* doubleword align heap start */ 
_sheap = .; 
*(.heap*) /* FreeRTOS heap, user stacks */ 
} > CCM 
_eheap = ABSOLUTE(0x1000F000); /* end of heap, 4KB for system stack */ 
_sptop = ABSOLUTE(0x1000FFF0); /* system SP on reset */ 
/* the BKPREG section is used for backup registers */ 
.bkpreg (NOLOAD) : 
{ 
*(.bkpreg) /* backup registers (tamper clear) */ 
} > BKPREG 
/* the BKPBB section is used to allocate backup bit flag registers as words */ 
.bkpbb (NOLOAD) : 
{ 
. = ALIGN(4); /* word align BitBand alias start */ 
_sbkpbb = .; 
*(.bkpbb*) /* backup register boolean flags (tamper clear) */ 
. = ALIGN(4); /* word align for init */ 
_ebkpbb = .; 
} > BKPBB 
/* The SNMP section is used for non-volatile counters, preserved across resets */ 
.snmp (NOLOAD) : 
{ 
. = ALIGN(4); /* word align for fast init */ 
_ssnmp = .; 
*(.snmp) /* statistical objects */ 
. = ALIGN(4); /* word align for init */ 
_esnmp = .; 
} > BKPSRAM 
/* the SNMPBB section is used to allocate non-volatile bit flags as words */ 
.snmpbb (NOLOAD) : 
{ 
. = ALIGN(4); /* word align BitBand alias start */ 
_ssnmpbb = .; 
*(.snmpbb) /* non-volatile boolean flags */ 
. = ALIGN(4); /* word align for init */ 
_esnmpbb = .; 
} > SNMPBB 
/* the OTP section is used to store locked firmware image metadata */ 
.otp (NOLOAD) : 
{ 
. = ALIGN(32); /* 8 word blocks */ 
_sotp = .; 
*(.otp*) /* OTP flash data */ 
_eotp = .; 
} > OTP 
.lock (NOLOAD) : 
{ 
_slock = .; 
*(.lock*) /* OTP flash data */ 
_elock = .; 
} > OTPLOCK 
} 

In this example the xxxBB memory regions overlap regular SRAM or backup RAM so sizes are adjusted to prevent collisions. Using the GCC compiler:

unsigned volatile long __attribute__ ((section(''.srambb''))) cpuColdStart; /*!< POR cold start flag */

sets up a bit band variable in SRAM. Although a long only the LSB is significant, so it can be tested for 0 or not zero as a Boolean operation.

Jack Peacock