Look at this (Controller: STM32F407I, uVision 4.23, Armcc 4.1.0.894):
struct __attribute__((bitband)){ unsigned int Bit1:1; unsigned int Bit2:1; }Bits __attribute__((at(0x20000100))); int main( void){ Bits.Bit1= 1; while(1); }
This compiles nicely with the compiler switch --bitband to the following code (for the C command line "Bits.Bit1=1"):
0x08000278 4901 LDR r1,[pc,#4] ; @0x08000280 0x0800027A 2001 MOVS r0,#0x01 0x0800027C 6008 STR r0,[r1,#0x00]
And at address 0x08000280 the correct memory address for bitbanding 0x22000000.
Now, if I insert
#include <stm32f4xx.h>
at the first line of the code, then I get exactly the same assembler code, but at address 0x08000280 the value is 0x20000000. And this of course is NOT correct for bit banding.
Anyone has an idea, what is going on here? How can this be influenced by this standard header file (from the standard Keil folder \Keil\ARM\Inc\ST\STM32F4xx). This is really extremely strange!!! (how can a header file, which is not used in the code, influence the code???).
Looking further into this stm32f4xx.h I finally came nearer to the problem: This includes the core_cm4.h - and the problem is in this file. This further includes the core_cmInstr.h, and again if I comment this out, all works nicely, so the problem is in core_cmInstr.h.
Finally in the core_cmInstr.h the "bad code" is the following:
/** \brief Reverse byte order (16 bit) This function reverses the byte order in two unsigned short values. \param [in] value Value to reverse \return Reversed value */ static __attribute__((section(".rev16_text"))) __inline __asm uint32_t __REV16(uint32_t value) { rev16 r0, r0 bx lr }
If I insert this code directly in my main.c (taking out the stm32f4xx.h - I just need the stdint.h for the uing32_t typedef), then again I get the bad code.
Anybody perhaps has an idea: - why this function disturbs the --bitband so badly? - what to do to solve this problem? (can I comment out this function in core_cmInstr.h, or any other way to fix this?)
BTW: The code will also work, if I allocate the struct "Bits" manually (e. g. __attribute(at(0x20000100))) ), but that really is nasty ... (further in this case the code is not so optimum as with automatic allocation by "--bitband" - for manual allocation even in opt level 3 the assembly will use one command and one register more).