[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;
#endif
_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
address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [avr-libc-dev] better representation of registers and bits,
Ned Konz <=