This is the mail archive of the crossgcc@cygnus.com mailing list for the crossgcc project.


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

Re: Accessing fixed addresses


John Breen wrote:
> 
> What is the best way to define fixed memory locations in C, such as
> hardware device registers?

In our system, we have a header file `chipio.h' containing the following
macros:

  #if defined(CHIPIO_CPP)
    #define IoPort(type, name) volatile type
name                         \
                             __attribute__ ((section (".io"))) = { 0 }
  #else
    #define IoPort(type, name) extern volatile type name
  #endif

  #define IoByte(name) IoPort(char, name)
  #define IoWord(name) IoPort(unsigned int, name)
  typedef const int IoMask;

followed by a lot of declarations like

  IoByte(porta);                  // parallel port a data
  IoByte(portb);                  // parallel port b data
   IoMask smodn   = 0x80;         //   special modes
   IoMask modb    = 0x40;         //   mode b

and so forth.  For things like serial ports, we create structures:

  struct sciport
  {
    int scbd;                     // sci baud rate
    char sccr1;                   // sci control 1
    char sccr2;                   // sci control 2
    char scsr1;                   // sci status 1
    char scsr2;                   // sci status 1
    char scdrh;                   // data register high
    char scdrl;                   // data register low
  };

  IoPort(sciport, sci0);          // sci port 0
  IoPort(sciport, sci1);          // sci port 1

Another file, `chipio.cpp', does 

  #define CHIPIO_CPP
  #include "chipio.h"

which generates the definitions of all of the I/O variables.  The
construct
`__attribute__ ((section (".io"))) = { 0 }' is a GCC extension which
allows us to force these variables into their own section which is then
placed at the correct address with the linker.

I/O driver modules then include chipio.h without defining CHIPIO_CPP,
thus they get declarations of the variables, rather than definitions. 
The compiler, however, knows that these variables are at fixed addresses
and generates direct references to them.

This scheme has worked reasonably well for us, as long as the processor
can use byte-addressed, memory-mapped I/O.  Separate I/O spaces and
unusual data bus configurations in some of our target machines are
forcing us to consider to other techniques.  

I would be interested in hearing about approaches to portable I/O
addressing other people may have developed. In a nutshell, the question
is: how can one write an single I/O driver (for say, an 8250 UART) which
can be built for any I/O scheme, including separate I/O spaces, 8-bit
devices attached to 32-bit data busses, and so forth.

Regards,

David Querbach
_______________________________________________
New CrossGCC FAQ: http://www.objsw.com/CrossGCC
_______________________________________________
To remove yourself from the crossgcc list, send
mail to crossgcc-request@cygnus.com with the
text 'unsubscribe' (without the quotes) in the
body of the message.