This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: ARM Cortex M3 Macro Limitation


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.






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]