Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-24 Thread Royce Pereira
Hi,
On Wed, 22 Nov 2006 23:14:21 +0530, kitts [EMAIL PROTECTED] wrote:

 On Wednesday 22 November 2006 05:57 IST, David Kelly wrote:
 Some MCU families (believe HC12 is one) have a separate register for  
 reading the port's actual input/external value, and another for  
 reading output latches containing the value last written. A bitfield  
 works fine on the output latch register.

 Is this not how it is with the AVR as well? We write into the PORTx register
 but read pin states from the PINx registers.

Sometimes it is required to read the PORT(latch) contents too, in output 
mode,to check the status of the output, or to modify only some port bits, 
without changing the others. The PINx register is read when the bit is an input.

--Royce.


-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-22 Thread David Brown

Keith Gudger wrote:

Below is a program which illustrates the following issue:

When using AVR ports, I would like to define them with bit-wise
structures.  This way I can easily access individual bits (or groups of
bits).  e.g.:

typedef struct port_reg {
unsigned bit0:1   ;
unsigned bit1:1   ;
unsigned unused:6 ;
} PORT_REG;

However, I cannot assign the 8 bit port value directly to a structure
defined this way.  Here is the code and the gcc error:

PORT_REG *pLED_DIR = (PORT_REG *)0x37 ; /// LED Port DIR REG PORT B
*pLED_DIR = (PORT_REG) 0x03 ;

main.c:27: error: conversion to non-scalar type requested

I can fix this problem by introducing a union:

typedef union {
PORT_REG port_bits ;
uint8_t  byte ;
} PORT_UNION ;

   PORT_UNION *pLED_DIR = (PORT_UNION *)0x37 ; /// LED Port DIR REG PORT B
   PORT_UNION *pLED_OUT = (PORT_UNION *)0x38 ; /// LED Port Output PORT B
   pLED_DIR-byte = 0x3 ;

But I would rather not have the union.  Is there any other way around
this?  Thanks.

Keith



Gcc supports anonymous unions as an extension, which can be used unless 
you have specified stricter standards compliance (i.e., it works with 
-std=gcc99, but not -std=c99):


typedef union {
struct {
unsigned bit0:1   ;
unsigned bit1:1   ;
unsigned unused:6 ;
};
unsigned char raw;
} PORT_REG;


PORT_REG *pLED_DIR = (PORT_REG *)0x37 ; /// LED Port DIR REG PORT B

void foo(void) {
pLED_DIR-raw = 0x03 ;
}

void bar(void) {
pLED_DIR-bit1 = 1;
}


You want to make sure you don't have any name conflicts between the 
union parts.


Of course, your generated code will be very much more efficient if you 
use the port address directly (named in a macro), rather than via a pointer.




#define LED_DIR (*(PORT_REG *)0x37)

void foo2(void) {
LED_DIR.raw = 0x03 ;
}

void bar2(void) {
LED_DIR.bit1 = 1;
}



mvh.,

David


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-22 Thread kitts
On Wednesday 22 November 2006 05:57 IST, David Kelly wrote:
 Some MCU families (believe HC12 is one) have a separate register for  
 reading the port's actual input/external value, and another for  
 reading output latches containing the value last written. A bitfield  
 works fine on the output latch register.

Is this not how it is with the AVR as well? We write into the PORTx register 
but read pin states from the PINx registers.
-- 
Cheers!
kitts


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-22 Thread David Gay

On 11/21/06, Eric Weddington [EMAIL PROTECTED] wrote:

Hi Keith

[Long time, no hear. ;-)]

Comments below.

 -Original Message-
 From:
 [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]
 org] On Behalf Of Keith Gudger
 Sent: Tuesday, November 21, 2006 11:41 AM
 To: avr-gcc-list@nongnu.org
 Subject: [avr-gcc-list] Bit-wise structure and unions

 Below is a program which illustrates the following issue:

snip

 But I would rather not have the union.  Is there any other way around
 this?  Thanks.


Unfortunately, no. The union would be the standard solution.

Ok, I take that back but only slightly. Why use bit fields at all? They are
inherently non-portable between compilers (if they work, then you're lucky).
Inherently, bit fields are tied to an int, which on the avr port is a 16-bit
type. We're lucky in that you can get GCC to put them into an unsigned char.
But again, that's compiler dependent.


Actually a platform ABI for C normally specifies such things precisely
to avoid same-platform different-C-compiler portability problems
(there's way more things than just bitfields that are not specified by
the C standard, so such an ABI spec is a necessity). FWIW, avr-gcc
packs bitfields into bytes. The size of int or the type used to
declare the bitfield don't affect this packing (*). Whether this
matches what IAR C is doing is another question...

David Gay
*: If you're curious, avr-gcc doesn't define the magic
PCC_BITFIELD_TYPE_MATTERS flag in its configuration.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-22 Thread Ned Konz

Keith Gudger wrote:

Below is a program which illustrates the following issue:

When using AVR ports, I would like to define them with bit-wise
structures.  This way I can easily access individual bits (or groups of
bits).  e.g.:

typedef struct port_reg {
unsigned bit0:1   ;
unsigned bit1:1   ;
unsigned unused:6 ;
} PORT_REG;

However, I cannot assign the 8 bit port value directly to a structure
defined this way.  Here is the code and the gcc error:

PORT_REG *pLED_DIR = (PORT_REG *)0x37 ; /// LED Port DIR REG PORT B
*pLED_DIR = (PORT_REG) 0x03 ;

main.c:27: error: conversion to non-scalar type requested

I can fix this problem by introducing a union:

typedef union {
PORT_REG port_bits ;
uint8_t  byte ;
} PORT_UNION ;

   PORT_UNION *pLED_DIR = (PORT_UNION *)0x37 ; /// LED Port DIR REG PORT B
   PORT_UNION *pLED_OUT = (PORT_UNION *)0x38 ; /// LED Port Output PORT B
   pLED_DIR-byte = 0x3 ;

But I would rather not have the union.  Is there any other way around
this?  Thanks.


I made a script that took a chunk of text copied from the Atmel PDFs 
(before they stupidly made it impossible to copy text from them!) and 
wrote such definitions.


[ BTW: PLEASE email Atmel and complain about the non-copyability of text 
in recent datasheet PDFs. This makes their datasheets (and hence 
processors) less usable. ]


I tried to support both the old-style (bit numbers and shifts) as well 
as bitfield-style.


That is, you can do these kinds of things (see header code below):

UDR1 = 0xCC;// assign whole byte register
UDR10 = 1;  // assign a single bit
UBRR1 = 0xFC;   // assign 12 bits at once
UDR1 = _BV(bitUDR10) | _BV(bitUDR11);   // use shifted bit numbers
UDR1 = (1  bitUDR10) | (1  bitUDR11); // use shifted bit numbers

Perhaps some of the ideas I used might be useful for you.


I started with a text file that looked something like this (copied from 
the SFR definitions in the AT90CAN128 PDF file):


(0xCE) UDR1 UDR17 UDR16 UDR15 UDR14 UDR13 UDR12 UDR11 UDR10 page 189
(0xCD) UBRR1H - - - - UBRR111 UBRR110 UBRR19 UBRR18 page 193
(0xCC) UBRR1L UBRR17 UBRR16 UBRR15 UBRR14 UBRR13 UBRR12 UBRR11 UBRR10 
page 193

(0xCB) Reserved
(0xCA) UCSR1C - UMSEL1 UPM11 UPM10 USBS1 UCSZ11 UCSZ10 UCPOL1 page 192
(0xC9) UCSR1B RXCIE1 TXCIE1 UDRIE1 RXEN1 TXEN1 UCSZ12 RXB81 TXB81 page 191
(0xC8) UCSR1A RXC1 TXC1 UDRE1 FE1 DOR1 UPE1 U2X1 MPCM1 page 189



Here's a chunk of such a header, showing both 8-bit (UDR1) and 16-bit 
(UBRR1H/L) usage:


/* UDR1 ($CE) (page 189) */
typedef union UDR1_t {
  uint8_t asByte;
  struct {
uint8_t bUDR10 :1;
uint8_t bUDR11 :1;
uint8_t bUDR12 :1;
uint8_t bUDR13 :1;
uint8_t bUDR14 :1;
uint8_t bUDR15 :1;
uint8_t bUDR16 :1;
uint8_t bUDR17 :1;
  } b;
} UDR1_t;
#define UDR1_sfr (*(volatile UDR1_t *) (0xCE))
#define UDR1 UDR1_sfr.asByte /* entire register */
/* single bits */
#define UDR10 UDR1_sfr.b.bUDR10
#define UDR11 UDR1_sfr.b.bUDR11
#define UDR12 UDR1_sfr.b.bUDR12
#define UDR13 UDR1_sfr.b.bUDR13
#define UDR14 UDR1_sfr.b.bUDR14
#define UDR15 UDR1_sfr.b.bUDR15
#define UDR16 UDR1_sfr.b.bUDR16
#define UDR17 UDR1_sfr.b.bUDR17
/* bit numbers */
#define bitUDR10 0
#define bitUDR11 1
#define bitUDR12 2
#define bitUDR13 3
#define bitUDR14 4
#define bitUDR15 5
#define bitUDR16 6
#define bitUDR17 7

/* UBRR1L ($CC) (page 193) */
typedef union UBRR1L_t {
  uint8_t asByte;
  struct {
uint8_t bUBRR10 :1;
uint8_t bUBRR11 :1;
uint8_t bUBRR12 :1;
uint8_t bUBRR13 :1;
uint8_t bUBRR14 :1;
uint8_t bUBRR15 :1;
uint8_t bUBRR16 :1;
uint8_t bUBRR17 :1;
  } b;
} UBRR1L_t;
#define UBRR1L_sfr (*(volatile UBRR1L_t *) (0xCC))
#define UBRR1L UBRR1L_sfr.asByte /* entire register */
/* single bits */
#define UBRR10 UBRR1L_sfr.b.bUBRR10
#define UBRR11 UBRR1L_sfr.b.bUBRR11
#define UBRR12 UBRR1L_sfr.b.bUBRR12
#define UBRR13 UBRR1L_sfr.b.bUBRR13
#define UBRR14 UBRR1L_sfr.b.bUBRR14
#define UBRR15 UBRR1L_sfr.b.bUBRR15
#define UBRR16 UBRR1L_sfr.b.bUBRR16
#define UBRR17 UBRR1L_sfr.b.bUBRR17
/* bit numbers */
#define bitUBRR10 0
#define bitUBRR11 1
#define bitUBRR12 2
#define bitUBRR13 3
#define bitUBRR14 4
#define bitUBRR15 5
#define bitUBRR16 6
#define bitUBRR17 7

/* UBRR1H ($CD) (page 193) */
typedef union UBRR1H_t {
  uint8_t asByte;
  struct {
uint8_t bUBRR18 :1;
uint8_t bUBRR19 :1;
uint8_t bUBRR110 :1;
uint8_t bUBRR111 :1;
uint8_t bReserved4 :1;
uint8_t bReserved5 :1;
uint8_t bReserved6 :1;
uint8_t bReserved7 :1;
  } b;
  struct {
uint8_t fUBRR1H :4;
uint8_t :1; /* Reserved4 */
uint8_t :1; /* Reserved5 */
uint8_t :1; /* Reserved6 */
uint8_t :1; /* Reserved7 */
  } f;
} UBRR1H_t;
#define UBRR1H_sfr (*(volatile UBRR1H_t *) (0xCD))
#define UBRR1H UBRR1H_sfr.asByte /* entire register */
/* single bits */
#define UBRR18 UBRR1H_sfr.b.bUBRR18
#define UBRR19 UBRR1H_sfr.b.bUBRR19
#define UBRR110 UBRR1H_sfr.b.bUBRR110
#define UBRR111 UBRR1H_sfr.b.bUBRR111
/* bit numbers */
#define 

Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-22 Thread Joerg Wunsch
Ned Konz [EMAIL PROTECTED] wrote:

 I made a script that took a chunk of text copied from the Atmel PDFs
 (before they stupidly made it impossible to copy text from them!)
 and wrote such definitions.

Well, you can always use a third-party tool to circumvent the
restriction.  This was the outcome of some discussion in
avrfreaks.net.  It appears Atmel's lawyers believe they have to
protect their intellectual property that way. :-(

However, for your purpose, all the information could be extracted
from the XML files as well.

-- 
cheers, Jorg   .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-22 Thread David Brown

David Gay wrote:

On 11/21/06, Eric Weddington [EMAIL PROTECTED] wrote:

Hi Keith

[Long time, no hear. ;-)]

Comments below.

 -Original Message-
 From:
 [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]
 org] On Behalf Of Keith Gudger
 Sent: Tuesday, November 21, 2006 11:41 AM
 To: avr-gcc-list@nongnu.org
 Subject: [avr-gcc-list] Bit-wise structure and unions

 Below is a program which illustrates the following issue:

snip

 But I would rather not have the union.  Is there any other way around
 this?  Thanks.


Unfortunately, no. The union would be the standard solution.

Ok, I take that back but only slightly. Why use bit fields at all? 
They are
inherently non-portable between compilers (if they work, then you're 
lucky).
Inherently, bit fields are tied to an int, which on the avr port is a 
16-bit
type. We're lucky in that you can get GCC to put them into an unsigned 
char.

But again, that's compiler dependent.


Actually a platform ABI for C normally specifies such things precisely
to avoid same-platform different-C-compiler portability problems
(there's way more things than just bitfields that are not specified by
the C standard, so such an ABI spec is a necessity). FWIW, avr-gcc
packs bitfields into bytes. The size of int or the type used to
declare the bitfield don't affect this packing (*). Whether this
matches what IAR C is doing is another question...



The ABI for a platform specifies a number of things, such as the size of 
datatypes and the calling conventions.  Unfortunately, it does not 
specify bitfields very well - in particular, the ordering of the bits is 
not well defined, nor are any alignment requirements, and nor (IIRC) is 
the signedness of the bitfields.  For example, consider the struct 
defined as:


struct { unsigned char a : 1; int b : 2 };

It is not well defined whether the container for a takes the space of 
a whole int or just a byte, whether b is aligned to the next int 
alignment or is packed in with a, and whether the whole structure 
takes a single byte, an int size, or two int sizes.


Secondly, it is not defined whether the bitfields are allocated from the 
LSB first or the MSB first.  On most little-endian target-compiler 
combinations, it is LSB first, on big-endian target-compiler 
combinations, there is more variance (the m68k gcc port starts with the 
MSB).  It is not even guaranteed to be consistent - MSVC++ famously 
changed the ordering between two versions of their compilers.


All in all, bitfields are strictly non-portable, not even between 
different compilers for the same target or different targets for the 
same compiler.


Having said that, two of the main uses for bitfields are for internal 
software structures such as packed flags (saving space), where alignment 
and ordering is of little concern, and for matching to hardware, where 
portability is of little concern.  I find them convenient sometimes, and 
gcc handles them well, but make sure you check the assembly to find out 
exactly how your compiler handles its bitfields.




David Gay
*: If you're curious, avr-gcc doesn't define the magic
PCC_BITFIELD_TYPE_MATTERS flag in its configuration.





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Bit-wise structure and unions

2006-11-21 Thread David Kelly

On Tue, Nov 21, 2006 at 01:31:13PM -0700, Eric Weddington wrote:


You should really use the C language bitwise operators (|, , ~, ^,
, ) and use bit masks to manipulate the bits that you want.

The bit-wise operators have one advantage over using the bit-field
structure. Using bit-wise operators you can operate on multiple,
*non-contiguous* bits simultaneously within a variable. You can't do
that with bit-field structures.


I agree with Eric. I'll typically define STATUS_LED_m and  
STATUS_LED_p and write STATUS_LED_p |= STATUS_LED_m or variations  
thereof. The generated code won't be any smaller with a bitfield.  
Eric makes a good point that one can smack multiple bits with one  
punch this way, not only for smaller code but because often one  
desires all outputs to change at the same time, not several clock  
cycles apart.


One other point is that I/O registers often return the value on the  
pin, not the value previously written. Doubt one wants a read-modify- 
write instruction to read an incorrect value as will happen if the  
pin is overloaded. In this case is best to have a copy of the port's  
intended value laying around in RAM, so one more define for  
STATUS_LED_r and write STATUS_LED_p = (STATUS_LED_r |= STATUS_LED_m);


Think that will evaluate correctly without parenthesis, but they help  
when reading.


Some MCU families (believe HC12 is one) have a separate register for  
reading the port's actual input/external value, and another for  
reading output latches containing the value last written. A bitfield  
works fine on the output latch register.


--
David Kelly N4HHE, [EMAIL PROTECTED]

Whom computers would destroy, they must first drive mad.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list