Hi!

The interesting thing is something different:

While ADC12CTL0 is defined as volatile unsigned int, why dows the compiler read 
it in two parts? It SHOULD read it with a word instruction into a register no 
matter where it is located (whether 16bit I/O space or 
anywhere else) as it could be modified in an ISR (or by hardware) between the 
two byte accesses.
I think the reason is that the very strange construct to return and typecast 
the content of ADC12CTL0 causes the compiler to forget about the volatile type 
of the source.
&ADC12CTL0 resolves to a pointer to a volatile unsigned int which is then 
typecasted to a pointer to a adc12ctl0_t structure. In this conversion it loses 
all information about being volatile. It's just a plain vanilla pointer 
pointing to something to be interpreted as an adc12ctl0_t structure. In the 
following steps, the compiler does what it would do with any other normal 
pointer.

If I compiler the below example, I get a

ez3.c: In function `getCtl0':
ez3.c:45: warning: cast discards qualifiers from pointer target type

So the compiler tells you that there's something going possibly wrong. And it 
does. And this is not the compilers fault.

I'd say it is not a compiler bug but a programmer bug.

return  (adc12ctl0_t) ADC12CTL0;

should do better. And should be much faster. But fails due to the incompatible 
type of data (non-scalar struct and scalar word value). This is also the reason 
why the compiler does not use a word instruction for 
constructing the result: the target is not a scalar type. And it has been 
packed, so it cannot be assumed word-aligned at all. The compiler does not know 
that in this special case it could just transfer a source word to 
a target word-size structure. It just assembles the target, and it does so 
(unoptimized) field by field, using the source only byte-wise. even after 
optimisation, when the optimisation algorithm discovers that the bit-wise 
assembly is unnecessary, the byte-wise source access still remains, as the 
optimisation does not know that it could be put together again. It does not 
even know for sure whether the target is word-aligned. Only the 
linker can tell.

Even faster and way more logical would be:

volatile adc12ctl0_t ctl0 __asm ("0x01A0");

no inline function, no function call, just a volatile word-sized struct placed 
somewhere in memory. But here again the compiler must fail due to the packed 
non-scalar type.

Handling this very special problem by type conversion is simply not in the 
range of the C language. You must give the compiler additional help here. 

There are two possible solutions: either you program the inlince code in direct 
assembly (by just loading the ADC12CTL0 into R14) or tell the compiler to use 
an intermediate storage place.

adc12ctl0_t getCtl0(void )
{
int i = ADC12CTL0;
return * (adc12ctl0_t *)&i;
}


This results into

 212 0000 0512                  push    r5
 213 0002 0412                  push    r4
 214 0004 0541                  mov     r1, r5
 215 0006 3550 0600             add     #6, r5
 216 000a 2183                  sub     #2, r1  ;       2, fpn 1
 217 000c 0441                  mov     r1,r4
 223 000e 9442 A001             mov     &0x01A0, @r4 
 226 0014 0E43                  mov     #llo(0), r14 
 227 0016 6F44                  mov.b   @r4, r15
 228 0018 7FF3                  and.b   #-1, r15
 229 001a 3EF0 00FF             and     #0xff00, r14
 230 001e 0EDF                  bis     r15, r14
 231 0020 5F44 0100             mov.b   1(r4), r15
 232 0024 7FF3                  and.b   #-1, r15
 233 0026 8F10                  swpb    r15
 234 0028 7EF3                  and.b   #-1, r14
 235 002a 0EDF                  bis     r15, r14
 236 002c 0F4E                  mov     r14, r15 
 242 002e 2153                  add     #2, r1
 243 0030 3441                  pop     r4
 244 0032 3541                  pop     r5
 245 0034 3041                  ret


Which is still big and bloadted but at least correct.

With optimisation -Os you'll get the smaller, but still unnecessary big

 212 0000 2183                  sub     #2, r1  ;       2, fpn 0
 218 0002 9142 A001             mov     &0x01A0, @r1 
 221 0008 6E41                  mov.b   @r1, r14
 222 000a 5F41 0100             mov.b   1(r1), r15
 223 000e 8F10                  swpb    r15
 227 0010 0FDE                  bis     r14, r15
 230 0012 2153                  add     #2, r1
 231 0014 3041                  ret

The same result (but even without optimisation) gives 

static inline adc12ctl0_t getCtl0(void )
{
 adc12ctl0_t i;
 __asm__ __volatile__ ("mov.w %1,%0":"=m"(i):"m"(ADC12CTL0));
 return i;
}

If you want it really short, just define a macro that resolves into an inline 
assembly code for the transfer:

#define getCtl0(dest) __asm__ __volatile__ ("mov.w 
%1,%0":"=m"(dest):"m"(ADC12CTL0))

it simply compiles to 

 222 0000 9242 A001             mov.w &0x01A0,&dest

what is what you want, but requires "dest" to be word-aligned else the result 
will be unpredictable. And of course it will not resolve to a value and 
therefore cannot be used in assignments or calculations.

If you remove the packed attribute from the struct, the inline function with 
ASM code gives (with -Os):

 218 0000 2183                  sub     #2, r1  ;       2, fpn 0
 228 0002 9142 A001             mov.w &0x01A0,@r1
 234 0008 A241 0000             mov     @r1, &dest
 239 000c 2153                  add     #2, r1

and it will ensure that dest is always word-aligned in memory (except you do 
some more pointer typecasting or include the struct into other packed structs).

JMGross


----- Ursprüngliche Nachricht -----
Von: Rohit Pagariya
An: GCC for MSP430 - http://mspgcc.sf.net
Gesendet am: 14 Okt 2009 01:28:15
Betreff: [Mspgcc-users] Compiler Bug Report: Read of registers in peripheral 
address space

I don't if this bug has been already reported, I couldn't find a bug 
report. So here goes:

The latest version of mspgcc3 (I built it on October 11) has a bug which 
affects the ADC12 operation.

The specification says : The address space from 0100 to 01FFh is 
reserved for 16-bit peripheral modules. These modules should be accessed 
with word instructions. If byte instructions are used, only even 
addresses are permissible, and the high byte of the result is always 0.

Thus byte reads at odd addresses are not permissible and the result is 
unpredictable.

For the following ADC related function in TinyOS 2.1,

typedef struct __nesc_unnamed4254 {
   volatile unsigned
   adc12sc : 1,
   enc : 1,
   adc12tovie : 1,
   adc12ovie : 1,
   adc12on : 1,
   refon : 1,
   r2_5v : 1,
   msc : 1,
   sht0 : 4,     
   sht1 : 4;
 } __attribute((packed))  adc12ctl0_t;

volatile unsigned int ADC12CTL0 __asm ("0x01A0");

static inline adc12ctl0_t getCtl0(void )
{
return * (adc12ctl0_t *)&ADC12CTL0;
}

The assembly produced at -O0 for msp430F1611 is

<getCtl0>:
     push    r5              
     push    r4               
     clr     r14              
     mov.b   &0x01a0,r15      
     and.b   #-1,    r15     ;r3 As==11
     and     #-256,  r14     ;#0xff00
     bis     r15,    r14      
     mov.b   &0x01a1,r15      /* A byte read at an odd address in the 
peripheral address space is not permitted. */*
     and.b   #-1,    r15     ;r3 As==11
     swpb    r15              
     and.b   #-1,    r14     ;r3 As==11
     bis     r15,    r14      
     mov     r14,    r15      
     pop     r4               
     pop     r5               
     ret                  

This bug is present at all levels of optimization. Has anyone else run 
into this bug as well?

Rohit

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Mspgcc-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mspgcc-users


Reply via email to