ARM Cortex M3 Macro Limitation

Thomas M. Alldread tmall@telus.net
Tue Apr 20 06:43:00 GMT 2010


Hi Richard:

   OK I will try to write a little app to do that. I am new to the GCC 
support area. I did post to the STM32 forum. I was first looking for a 
suitable GCC forum but I missed it somehow. I will post to gcc-help.

Thanks,
Tom Alldread

Richard Earnshaw wrote:
> It would help if you posted a compilable example that demonstrates your
> point rather than fragments that can't be analysed by the compiler.
>
> Also, I'm regret that I can't enter into private email discussion on the
> subject (otherwise I'll end up having to repeat myself each time the
> issue comes up).  If you'd like to continue to progress the issue,
> you'll need to do so in a public forum (like gcc-help).
>
> R.
>
> On Mon, 2010-04-19 at 10:00 -0700, Thomas M. Alldread wrote:
>  
>> Greetings Richard,
>>
>>     Many thanks for finding the time to reply!
>>
>>     However I am still puzzled. I also had thought at one point that 
>> the pre-processor just didn't have the variable address assignment 
>> (&varName) information available to do the calculation at the time 
>> during the processing. But then I noticed that part of the 
>> calculation was not being done within the STM32 ASM code concluding 
>> that the &varName calculation must have been done by the 
>> pre-processor. For confirmation I decided to do a test by doing the 
>> bitBand address calculation without the (*(volatile unsigned int *) 
>> pointer cast as follows:
>>
>> RAMBBTEST(varName,bit)  
>> (uint32_t)&varName-SRAM_BASE*32+4*bit+SRAM_BB_BASE
>> #define HEARTBEAT_500MS_BBFLG   RAMBBTEST(tick_500mS_Flags,1)
>>
>>     I then inserted a test statement that would simply load the 
>> resulting constant and found the result to be correct. The debugger 
>> shows that the entire calculation was done by the pre-processor as 
>> the C statement just generates a pair of load and store instructions 
>> in the ASM code.
>>             uint32_t test1 = HEARTBEAT_500MS_BBFLG;
>>        4B16       ldr r3, [pc, #0x058]
>>        603B       str r3, [r7, #0x00]
>>
>>     The test1 variable result shown by the debugger is 0x22005304 
>> which is the correct bitBand target address.
>>
>>     I also noticed by accident, whilst I was trying several 
>> unacceptable variations of syntax, that the compiler would generate 
>> an error message that showed the correct calculation result. It was 
>> apparent, as I understand it, that the value was correctly calculated 
>> even before the linker was called.
>>
>>     It appears the problem does not appear until  the (*(volatile 
>> unsigned int *) pointer cast is added.
>>
>>     I finally concluded that I must be overloading the pre-processor 
>> somehow and now wonder if there is a way to work around it.
>>
>>     Again I wish to thank you for taking the time to reply! I hope 
>> this additional info will shed some new light on the nature of the 
>> problem.
>>
>>
>> Best Regards,
>> Tom Alldread
>>
>>
>>
>>
>>
>> Richard Earnshaw wrote:
>>    
>>> On Sun, 2010-04-18 at 10:14 -0700, Thomas M. Alldread wrote:        
>>>> Greetings:
>>>>
>>>>     I would like to learn a macro technique for the
>>>> address assignment of single bit variables to the
>>>> bitBand region of an ARM Cortex M3 MPU.
>>>>
>>>>      I wrote the following macro for defining and accessing
>>>> single bit semaphore variables:
>>>>
>>>> #define SRBB(varName, bit) (*((volatile unsigned int *)\
>>>> ((((uint32_t)&varName - SRAM_BASE)*32)+(bit*4)+SRAM_BB_BASE)))
>>>>
>>>> where:
>>>> &varName       =   0x20000298 // for this example
>>>> bit            =   1          // for this example
>>>> SRAM_BASE      =   0x20000000 // mem map constant
>>>> SRAM_BB_BASE   =   0x22000000 // mem map constant
>>>>
>>>>      For a reference I pre-calculated the bitBand address
>>>> and took a look at the associated ASM steps. As shown in
>>>> example 1 the GCC compiler matched the textbook
>>>> efficiency of 3 ASM instructions for setting the bit.
>>>> ....
>>>>
>>>> 1) Example with manually calculated bitBand address:
>>>>
>>>> (*((volatile unsigned int *)0x22005304)) = (uint16_t)1;;
>>>>         4A20                  ldr r2, [pc, #0x080]
>>>>         F04F0301               mov.w r3, #0x00000001
>>>>         6013                   str r3, [r2, #0x00]
>>>>
>>>> ....
>>>>
>>>>      I then decided to generate the bitBand address with my
>>>> macro and discovered that it took 7 instruction cycles to
>>>> set the bit as some of the address arithmetic was assigned
>>>> by GCC to the STM32 processor.
>>>>
>>>> ....
>>>>
>>>> 2)Example that uses the macro:
>>>>
>>>>         HEARTBEAT_500MS_BBFLG = 1;
>>>>         4B22          ldr r3, [pc, #0x088]
>>>>         EA4F1343      mov.w r3, r3, lsl #0x05
>>>>         F1035308      add.w r3, r3, #0x22000000
>>>>         F1030304      add.w r3, r3, #0x00000004
>>>>         461A          mov r2, r3
>>>>         F04F0301      mov.w r3, #0x00000001
>>>>         6013          str r3, [r2, #0x00]
>>>> ....
>>>>
>>>>      It appears the compiler pre calculates the 0x298 byte
>>>> offset and bit offsets. Then the 32 times multiplication
>>>> and offset sum steps are passed to the STM32.
>>>>
>>>>      I wonder if someone here knows why the GCC
>>>> pre-processor does not complete my macro calculation?
>>>> If so please advise me or point me to information that
>>>> describes what I need to change so that the GCC
>>>> pre-processor will complete the macro calculation
>>>> without adding STM32 instructions.
>>>>
>>>>       Thanks in advance for any help!
>>>>             
>>> I'm afraid there isn't much that can be done about this without adding
>>> explicit bit-band support to the compiler (a lot of work).  The problem
>>> is at least in part a representational limit of object files.
>>> The compiler does not know where your variable will eventually be 
>>> placed
>>> (the linker is the only thing that will know that).  So it can't
>>> simplify your expression statically.  Further, it can't represent the
>>> entire expression as a relocation because they cannot get this
>>> complicated (being limited essentially to a symbol plus a simple
>>> constant offset).  So the compiler has to leave your expression pretty
>>> much as you've written it.
>>>
>>> R.
>>>
>>>
>>>         
>>     
>
>
>   



More information about the Gcc-help mailing list