Hi Gerald,
My suggestion was not to use a pointer (constant or not) to a location
(volatile or not) but rather generate a volatile variable and tell the
assembler that it is located at a fixed location.
No need to generate a pointer variable that points to the desired register and
use an inferece to access the members. Just use the variable at its native
location.
All standard MSPGCC defines are done this way, albeit usually the type is just
char or int. But any type (including structs) is fine as well.
from iomacros.h:
#define sfrb_(x,x_) volatile unsigned char x asm(#x_)
#define sfrw_(x,x_) volatile unsigned int x asm(#x_)
and from one of the include files:
#define UCA0CTL0_ 0x0060 /* USCI A0 Control Register 0 */
sfrb(UCA0CTL0, UCA0CTL0_);
which leads to a volatile unsigned char UCA0CTL0 variable located at fixed
memory address 0x0060.
If, by chance, the destination address (the hardware register) holds a
(hardware-generated) pointer to data in module ram instead of the data itself
(I don't know anything about the USB module and its registers), the
data type would be a struct* instead of a struct, and both, the pointer
register and its destination type must be declared volatile.
In your original suggestion (see the bottom of the quoted text), you create a
separate pointer variable and initialize it with the address of the register.
One level of reference more than necessary during code execution
and two wasted bytes of ram. The result would be the same and the compiler
might optimize some or all of the code overhead, but it also decreases
readability of the source code. and (obviously) adds some sources
of possible misunderstandings. :)
JMGross
----- Ursprüngliche Nachricht -----
Von: Gerald Lutter
An: 'GCC for MSP430 - http://mspgcc.sf.net'
Gesendet am: 03 Dez 2009 21:05:23
Betreff: Re: [Mspgcc-users] msp430x5529 support
Hi,
> Also, the below proposed usage will make the pointer volatile (so the
> compiler will NOT store it in a local register but constantly reload
> it from RAM) and not the hardware register it points to. It might happen
> that the value, once read, is calculated with again and again without
> ever reloading it.
There is one thing I forgot inside my declaration it should be:
volatile OutputEndDescriptorType *tOutputEndDescriptorBlock = (volatile
OutputEndDescriptorType*) ...
otherwise it would lead to an implicit cast from a pointer to volatile data
to
a pointer to plain data. But I think there is something wrong in your
explanation. Because if i've understood your suggestion, my version should
be something like that:
OutputEndDescriptorType * volatile tOutputEndDescriptorBlock =
(OutputEndDescriptorType * volatile) ...
Therefore I have copied an explanation out of the C-Standard. If I'am wrong
please correct me:
EXAMPLE The following pair of declarations demonstrates the difference
between a variable pointer to a constant value and a constant
pointer to a variable value.
const int *ptr_to_constant;
int *const constant_ptr;
The contents of any object pointed to by ptr_to_constant shall not be
modified through that pointer, but ptr_to_constant itself may be changed
to point to another object. Similarly, the contents of the int pointed
to by constant_ptr may be modified, but constant_ptr itself shall always
point to the same location.
The behaviour is the same for any other qualifier (like volatile in our
case).
For further explanation take a look on page 115 to 117 at
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1362.pdf
Best regards,
Gerald
-----Ursprüngliche Nachricht-----
Von: JMGross [mailto:[email protected]]
Gesendet: Donnerstag, 3. Dezember 2009 18:34
An: MSPGCC mailing list,
Betreff: Re: [Mspgcc-users] msp430x5529 support
Hi!
Why using a pointer?
The normal defines in MSPGCC are evaluated to
volatile unsigned char/int NAME asm(#ADDRESS);
So in this case
volatile OutputEndDescriptorType tOutputEndPointDescriptorBlock
asm(#USBOEPCNF_1);
should do the trick. Any member of the struct is then accessed by
tOutputEndPointDescriptorBlock.xyz
It not only saves two bytes of RAM for storing the pointer to the register,
it will also generate slightly smaller code, depending on usage.
Also, the below proposed usage will make the pointer volatile (so the
compiler will NOT store it in a local register but constantly reload it from
RAM) and not the hardware register it points to. It might happen that the
value, once read, is calculated with again and again without ever reloading
it.
JMGross
----- Ursprüngliche Nachricht -----
Von: Gerald Lutter
An: 'GCC for MSP430 - http://mspgcc.sf.net'
Gesendet am: 03 Dez 2009 09:19:06
Betreff: Re: [Mspgcc-users] msp430x5529 support
Hi Bernie,
changing addresses inside the assembler section does not change the symbol
for your C-Code. This is because the assembler Section of the header is only
available if you use assembler. But I think you are using C-Code therefore
your changes will have no effect. By the way, the assembler section of
msp430x55x9_newversion.h is generated automatically during the build of the
library out of msp430x55x9_template.header (this file does only exist before
you build the msp430-libc after applying our patch).
But now to your actual question:
if tOutputEndPointDescriptorBlock is of type OutputEndDescriptorType then
you have to define your tOutputEndPointDescriptorBlock as pointer: volatile
OutputEndDescriptorType *tOutputEndDescriptorBlock = (volatile
OutputEndDescriptorType *)&USBOEPCNF_1;
you are now able to configure your component using this code
tOutputEndDiscriptorBlock-><any field inside your struct> = <any value
tOutputEndDiscriptorBlock->you
need>;
Best regards,