[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] better representation of registers and bits

From: Ned Konz
Subject: [avr-libc-dev] better representation of registers and bits
Date: Thu, 6 Apr 2006 15:05:34 -0700

I've been thinking some more about this, and it seems to me that we could make it easier to deal with the registers/bits problems, provide for better support of C++, and make debugging easier as well.

There are a couple of problems I'm trying to solve:

* The knowledge of the register and bit number names die with the preprocessor. The compiler doesn't know those names, and they aren't available to the debugger.

* Because the register and bit names are actually #defined, it makes it very difficult to give these objects distinct identities in C++, or to even define them differently in different namespaces (text substitution is very brute-force).

* The bit definitions aren't related in any way to the register definitions. This makes it impossible to make a safe definition of I/ O bits in C++.

Attached is a tarball with a Perl script, a Makefile, and the results of the Perl script when run on avr/iom128.h .

What the script does is this:

* breaks the IO space and literal address out of the SFR definitions, making it possible to define them elsewhere
* breaks out the literal bit numbers out of the bit number definitions
* writes a separate file with these captured constants (which would be defined per-processor).

This would allow for avr/sfr_defs.h to have definitions for all the possible registers (regardless of their addresses); this set doesn't change very often.

For C or assembly language, these register definitions look like (in my example):

/* External Interrupt MaSK register */
#define EIMSK _SFR##_space_of_EIMSK(_address_of_EIMSK)

/* External Interrupt Control Register B */
#define EICRB _SFR##_space_of_EICRB(_address_of_EICRB)

/* RAM Page Z select register */
#define RAMPZ _SFR##_space_of_RAMPZ(_address_of_RAMPZ)

That is, they're generic (processor-independent), relying on the _space_of_* and _address_of_* constants to be defined elsewhere (in this case, it would be in the avr/iom128.h file, but I didn't change the structure, so you'll see them in the iom128_defs.h file).

In the per-processor files (like avr/iom128.h) these constants would be defined:

#define  _address_of_EIMSK  0x39
#define  _space_of__EIMSK  IO8

So the expanded version of the EIMSK definition reads the same as it does now:

#define EIMSK _SFR_IO8(0x39)

The bit definitions look like this:

/* Port E Data Register - PORTE */
#define PE7 _BITNUM(_owner_of_bit_PE7,_bitNumber_of_PE7)
#define PE6 _BITNUM(_owner_of_bit_PE6,_bitNumber_of_PE6)
#define PE5 _BITNUM(_owner_of_bit_PE5,_bitNumber_of_PE5)
#define PE4 _BITNUM(_owner_of_bit_PE4,_bitNumber_of_PE4)
#define PE3 _BITNUM(_owner_of_bit_PE3,_bitNumber_of_PE3)

Which get expanded with per-processor definitions that look like this:

#define    _owner_of_bit_PE3  PORTE
#define    _bit_number_of_PE7  7

What is expanded with a macro that looks like this (for C or assembly language):

#define _BITNUM(owner,bitnumber) bitnumber

As a result, the definitions in C and in assembly language end up being identical to what they are now.

In C++, though we can have alternate definitions for C++ that don't have to be changed for every processor (i.e. not separately maintained). The generated register declarations in the sfr_defs file would look like this:

#if !defined(_SFR_DECLARE)
#define _SFR_DECLARE(name,space,address) extern REG##space<address> name;

    _SFR_DECLARE(ACSR, _space_of_ACSR, _address_of_ACSR)
    _SFR_DECLARE(ADC, _space_of_ADC, _address_of_ADC)

which would expand to:

extern REGIO8<_address_of_ACSR> ACSR;

A similar scheme is used for bit numbers.

_BIT_DECLARE(TXEN, _owner_of_bit_TXEN, _bitNumber_of_TXEN)

Ned Konz
MetaMagix embedded consulting

reply via email to

[Prev in Thread] Current Thread [Next in Thread]