David Kelly wrote:
> On Thu, Mar 22, 2007 at 08:44:08PM -0000, kernels_nz wrote:
>> The huge advantage of using the shift and mask method is that it makes
>> pre-written code completely portable to any other AVR micro with the
>> same names for bits, and generally when two AVR micros have the same
>> peripherals, they also use the same bit-names, but not necessarily in
>> the same bit position.
>
> If someone was interested enough to do the work there is no reason why
> each and every register could not be defined as structs with bitfields.
> Codewarrior does exactly that. Makes for some *huge* .h files.
>
> If one were determined to do such a thing I think a script should be
> written to make structs out of register definitions. This way new CPUs
> and new CPU families could be added relatively painlessly with minimum
> opportunities for human error.
I already did this; my script works from text copied from the PDF data
sheets. Admittedly, the XML files are probably more authoritative and
easier to parse. Plus, Atmel stupidly changed their PDF files to
disallow copying of text to the clipboard (!) so you have to run the PDF
through something other than Adobe Reader to get the text.
> But (reaching for an example which might not exactly apply) if one
> wanted to know of the TX register had 1) just completed or 2) was empty,
> then the masking solution allows one to kill two birds with one stone.
So I provided both methods.
For each single bit or contiguous multiple bit field I made a bitfield
definition.
I also provide numeric definitions for bit numbers.
For each 8-bit register I also provided an asByte byte-wide definition.
For each 9-to-16-bit wide register I also provide an asWord
two-byte-wide definition.
I also provide definitions for each of the bits, using names from the
datasheet.
So, using my headers, your example test for tx completed or empty could
be written:
if (TXC0 || UDRE0)
/* do stuff */
or:
if (UCSR0B & ((1 << bitTXC0) | (1 << bitUDRE0)))
/* do stuff */
and the generated code would look like this:
12:test2.c **** if (TXC0 || UDRE0)
315 0008 5E99 sbic 43-0x20,6
316 000a 08C0 rjmp .L2
319 000c 5D99 sbic 43-0x20,5
320 000e 06C0 rjmp .L2
*** /* do stuff */
332 .L2
or this (somewhat more efficient):
15:test2.c *** if (UCSR0B & ((1 << bitTXC0) | (1 << bitUDRE0)))
324 0010 8AB1 in r24,42-0x20
325 0012 8076 andi r24,lo8(96)
326 0014 31F0 breq .L5
*** /* do stuff */
338 .L5
Here's an excerpt from the generated Atmega128 header file (yes, my
script also generates Doxygen documentation directives):
/*! \addtogroup UCSR0B
* \brief UCSR0B ($2A) (page 190)
* \see PROCESSOR_PDF_URL#page=190
* @{
*/
typedef union UCSR0B_t {
/*! \cond REG_DETAILS */
uint8_t asByte;
struct {
uint8_t bTXB80 :1;
uint8_t bRXB80 :1;
uint8_t bUCSZ02 :1;
uint8_t bTXEN0 :1;
uint8_t bRXEN0 :1;
uint8_t bUDRIE0 :1;
uint8_t bTXCIE0 :1;
uint8_t bRXCIE0 :1;
} b;
/*! \endcond REG_DETAILS */
} UCSR0B_t;
#define UCSR0B_sfr (*(volatile UCSR0B_t *) (0x2A))
#define UCSR0B UCSR0B_sfr.asByte /*entire register*/
/* single bits */
#define TXB80 UCSR0B_sfr.b.bTXB80 /*!< Bit 0 of UCSR0B \sa bitTXB800
\hideinitializer */
#define RXB80 UCSR0B_sfr.b.bRXB80 /*!< Bit 1 of UCSR0B \sa bitRXB801
\hideinitializer */
#define UCSZ02 UCSR0B_sfr.b.bUCSZ02 /*!< Bit 2 of UCSR0B \sa bitUCSZ022
\hideinitializer */
#define TXEN0 UCSR0B_sfr.b.bTXEN0 /*!< Bit 3 of UCSR0B \sa bitTXEN03
\hideinitializer */
#define RXEN0 UCSR0B_sfr.b.bRXEN0 /*!< Bit 4 of UCSR0B \sa bitRXEN04
\hideinitializer */
#define UDRIE0 UCSR0B_sfr.b.bUDRIE0 /*!< Bit 5 of UCSR0B \sa bitUDRIE05
\hideinitializer */
#define TXCIE0 UCSR0B_sfr.b.bTXCIE0 /*!< Bit 6 of UCSR0B \sa bitTXCIE06
\hideinitializer */
#define RXCIE0 UCSR0B_sfr.b.bRXCIE0 /*!< Bit 7 of UCSR0B \sa bitRXCIE07
\hideinitializer */
/* bit numbers */
#define bitTXB80 0 /*!< bit number of TXB80*/
#define bitRXB80 1 /*!< bit number of RXB80*/
#define bitUCSZ02 2 /*!< bit number of UCSZ02*/
#define bitTXEN0 3 /*!< bit number of TXEN0*/
#define bitRXEN0 4 /*!< bit number of RXEN0*/
#define bitUDRIE0 5 /*!< bit number of UDRIE0*/
#define bitTXCIE0 6 /*!< bit number of TXCIE0*/
#define bitRXCIE0 7 /*!< bit number of RXCIE0*/
/*! @} */
/*! \addtogroup UCSR0A
* \brief UCSR0A ($2B) (page 189)
* \see PROCESSOR_PDF_URL#page=189
* @{
*/
typedef union UCSR0A_t {
/*! \cond REG_DETAILS */
uint8_t asByte;
struct {
uint8_t bMPCM0 :1;
uint8_t bU2X0 :1;
uint8_t bUPE0 :1;
uint8_t bDOR0 :1;
uint8_t bFE0 :1;
uint8_t bUDRE0 :1;
uint8_t bTXC0 :1;
uint8_t bRXC0 :1;
} b;
/*! \endcond REG_DETAILS */
} UCSR0A_t;
#define UCSR0A_sfr (*(volatile UCSR0A_t *) (0x2B))
#define UCSR0A UCSR0A_sfr.asByte /*entire register*/
/* single bits */
#define MPCM0 UCSR0A_sfr.b.bMPCM0 /*!< Bit 0 of UCSR0A \sa bitMPCM00
\hideinitializer */
#define U2X0 UCSR0A_sfr.b.bU2X0 /*!< Bit 1 of UCSR0A \sa bitU2X01
\hideinitializer */
#define UPE0 UCSR0A_sfr.b.bUPE0 /*!< Bit 2 of UCSR0A \sa bitUPE02
\hideinitializer */
#define DOR0 UCSR0A_sfr.b.bDOR0 /*!< Bit 3 of UCSR0A \sa bitDOR03
\hideinitializer */
#define FE0 UCSR0A_sfr.b.bFE0 /*!< Bit 4 of UCSR0A \sa bitFE04
\hideinitializer */
#define UDRE0 UCSR0A_sfr.b.bUDRE0 /*!< Bit 5 of UCSR0A \sa bitUDRE05
\hideinitializer */
#define TXC0 UCSR0A_sfr.b.bTXC0 /*!< Bit 6 of UCSR0A \sa bitTXC06
\hideinitializer */
#define RXC0 UCSR0A_sfr.b.bRXC0 /*!< Bit 7 of UCSR0A \sa bitRXC07
\hideinitializer */
/* bit numbers */
#define bitMPCM0 0 /*!< bit number of MPCM0*/
#define bitU2X0 1 /*!< bit number of U2X0*/
#define bitUPE0 2 /*!< bit number of UPE0*/
#define bitDOR0 3 /*!< bit number of DOR0*/
#define bitFE0 4 /*!< bit number of FE0*/
#define bitUDRE0 5 /*!< bit number of UDRE0*/
#define bitTXC0 6 /*!< bit number of TXC0*/
#define bitRXC0 7 /*!< bit number of RXC0*/
/*! @} */
--
Ned Konz
ned@bike-nomad.com
http://bike-nomad.comMessage
Re: [AVR-Chat] Re: Some C help please !
2007-03-23 by Ned Konz
Attachments
- No local attachments were found for this message.