Basically, it's due to my desire for requirement R3 in the attached
analysis, which avoids bringing every name in the header file into the
global symbol table.   The net effect is that if you want to interact
with a peripheral register in the debugger, you have to prepend a
double-underscore to the name.

(gdb) p/x __CALDCO_8MHZ
$4 = 0xa0

Peter

On Sun, Sep 18, 2011 at 4:27 PM, Crazy Casta <crazyca...@gmail.com> wrote:
> I've been wondering for a while why we handle peripherals the way we
> do. As far as I can tell, it seems to confuse the other tools (like
> msp430-gdb). I'm wondering why we don't do something like:
>
> libperiph.c:
>
> volatile unsigned int ADC12CTL0;
> volatile unsigned int ADC12CTL1;
> volatile unsigned int ADC12CTL2;
>
> periph.x
>
> SECTIONS {
>   .peripheral_16bit 0x0100:
>   {
>      ADC12CTL0 = 0x600;  /* 0x600 rel to 0x0100, ABS is 0x0700 */
>      ADC12CTL1 = 0x602;
>      ADC12CTL1 = 0x604;
>   }
> }
>
> etc, etc for the other peripherals (anything that needs to be mapped
> to a specific address).
>
> Unless I'm mistaken, that should fix issues like msp430-gdb not
> knowing about the peripherals.
>
> ------------------------------------------------------------------------------
> BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
> http://p.sf.net/sfu/rim-devcon-copy2
> _______________________________________________
> Mspgcc-users mailing list
> Mspgcc-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/mspgcc-users
>
Currently msp430-libc defines MCU memory mapped registers with C constructs
such as:

  volatile unsigned int P1IN asm("0x0020");

This has two problems:

* The address of the register is defined when the translation unit is
  assembled; there are no relocatable symbols left

* The register name is added as a global symbol

Interestingly, when the same headers are included in assembly files the
first holds, but the second does not as the symbol is not marked global.

  P1IN = 0x0020

As I noted in an earlier email, encoding register addresses in the object
files requires that a separate object file be created for every chip for
which the peripherals in the translation unit are at different addresses.
Further, there is no ability to detect when object files built for different
chips are linked together: the code will simply use whatever addresses were
compiled into the object file or library.

The primary negative impact of adding the registers as global symbol is the
potential collisions with identifiers used in code that does not reference
the TI registers.  Names like MAC, MPY, and P1IV might legitimately be used
in other ways.

In an ideal world, I'd like a solution with the following features:

R1 The address associated with a register should remain unresolved until the
   final (non-relocating) link phase;

R2 Any references to registers that are not defined in the final link phase
   should produce a link-time error;

R3 The symbols associated with the TI registers should not be placed in the
   global symbol space.

------------------------------
R1 can be solved by converting the register definition to a declaration that
does not include its location:

  extern volatile unsigned int P1IN;

The location of the register can be provided at the final link phase by
using a chip-specific linker script with text such as:

  PROVIDES(P1IN = 0x0020);

[ A benefit of this is that, if an error in address is ultimately found, or a
  new chip needs to be supported, an updated value can be provided at link
  time using the --defsym option to ld, as with:

    msp430-gcc -o main.exe main.c -Wl,--defsym=P1IN=0x0200

  A cost of this is that users who put such definitions in their build
  scripts are likely to forget they have done so and destabilize future
  builds.]

For assembly files, one need merely avoid declare the symbol without
providing a value:

  .global P1IN

R2 is naturally satisfied with this approach, since the linker will complain
about unresolved global symbols.

This approach does not satisfy R3.

--------------------
R3 can be solved by keeping the corresponding symbols from the global
namespace:

  static volatile unsigned int P1IN asm("0x0020");

As noted, the assembly declarations already satisfy R3.  However, this
approach does not satisfy R1.

--------------------
A more complicated approach satisfies R1 and R3.  This approach separates
the real symbol used to define the register location from the commonly used
name defined by TI.  See http://gcc.gnu.org/ml/gcc/2005-10/msg00235.html

In C, this is done with:

  static volatile unsigned int P1IN __attribute__((weakref("__P1IN")));

In assembly, the code would be:

  .weakref P1IN, __P1IN

And in the ld script one would use:

  PROVIDE(__P1IN = 0x0020);

This is oh-so-close.  The vendor name P1IN is a local symbol.  The global
symbol names begin with the double underscore, and are not in the user's
namespace.  The addresses are not provided until the final link stage, and
can be overridden at the command line in that situation.  R1 and R3 are
satisfied.

However, R2 is not satisfied.  The semantics of weakref is that P1IN
resolves to __P1IN if the latter is defined, but to zero if it is not.
Consequently, a zero address will be used in any code that references a
register not defined in the linker script.

--------------------

The final approach reverts back to the original, existing approach, but uses
a global symbol instead of an address:

  extern volatile unsigned int P1IN asm("__P1IN");

With this approach, no symbol P1IN appears in the object file; all
references are to the global symbol __P1IN.  (Making the declaration static
instead of extern would declare __P1IN as a local symbol.)

This satisfies R1, R2, and R3.

========================================

Overall conclusions:

R1 ensures that object files are consistent.  R2 ensures that the build
process provides all information required by the application.  R3 supports
those few applications where the vendor register names should not be global
symbols.

The current intent is to proceed with the last solution.  Register
declarations in C (C++) will be:

  extern volatile unsigned int P1IN asm("__P1IN");

Register declarations in asm will be empty, resulting in undefined global
references.

The linker script values will be unqualified:

  __P1IN = 0x0020;

disallowing build-time overrides in favor of instead using a replacement
linker script.
------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
http://p.sf.net/sfu/rim-devcon-copy2
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to