2009-09-24 11:58 AM
C compilers and bit banding
#bit-banding #bit-banding #cubemx2011-05-17 04:24 AM
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. Harjit2011-05-17 04:24 AM
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.htm2011-05-17 04:25 AM
There is currently a discussion on the Keil forum about this very thing:
2015-03-20 06:39 AM
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?2015-03-20 07:28 AM
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.2015-03-20 10:50 AM
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