avr-libc-dev
[Top][All Lists]
Advanced

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

Re: [avr-libc-dev] A sugestion for avr-libc


From: E. Weddington
Subject: Re: [avr-libc-dev] A sugestion for avr-libc
Date: Fri, 22 Aug 2003 18:44:50 GMT

> First of all I'd like to thank the developers of avr-
libc, you've done a
> fantastic job thus far.
> 
> I haven't been using avr-libc for all that long now 
(about 2 months) but
> one
> of the more useful features that appears to be missing is 
the ability to
> assign and test individual bits in IO registers. Ie 
PA0=1; or if (DDRA
> == 1)
> 
> Whilst some of this functionality is provided by current 
releases using
> the
> sbi, and cbi functions, I believe adding the capability 
to read and
> write
> bits without requiring the use of these instructions 
would enhance
> avr-libc.
> 
> I have attached a cut down IO header (myIO.h) and a 
simple test program
> (main.c) that demonstrate how this functionality would be 
implemented
> into
> the current avr-libc and used in programs.
> 
> I think you'll agree that it provides a much simpler 
means of accessing
> bits
> in the IO registers than the current mechanisms. This 
method of access
> also
> seems to be relatively common across other 
compilers/libraries I have
> come
> across (Mitsubishi M16C, some 8051 compilers etc).
> 
> I have found avr-libc useful so if the general concessus 
is that this
> would
> be a useful addition I am happy enough to implement it. I 
would however
> like
> to make sure that I am not duplicating someone else's 
effort, if someone
> else out there is already working on this I would like to 
offer them my
> assistance.
> 
> P.S. Could anyone replying to this email please send me a 
copy
> (craig_AT_student.usyd.edu.au) as I'm having some 
difficulty joining the
> mailing list.
> 
> Regards
> 
> Craig Rodgers


Thanks for your submission.

However, there are some issues with this method that you're 
probably not aware about.

1. There are already capabilites within the C language to 
test and assign individual bits within a byte. See more 
below.

2. The sbi and cbi macros are deprecated and no longer used.

3. Modeling a byte as a bitfield has limitations and 
inefficiencies. Namely, a bitfield is declared as an int, 
which is 16 bits, and not an unsigned char. Also, when you 
use the bitfield model, you are limited to assigning only 
to members of the bitfield structure, whether this is a 
single bit, or multiple sequential bits. Using the C 
language capabilites gives the programmer much more freedom.

4. In the C language one assigns and tests bits using bit 
operators, the assign operator, and the concept of bit 
masks:

PORTC |= 0x01;  // Set bit 0 only.
PORTC &= ~0x01; // Clear bit 0 only.
PORTC ^= 0x01;  // Toggle bit 0 only.
PORTC & 0x01;  // Test bit 0 only.
PORTC |= 0x80; // Set bit 7 only.

Now we can introduce macros to make this easier to read. 
The _BV() macro in avr-libc takes a number as the argument 
and converts it to the appropriate bit mask. (The BV stands 
for Bit Value). The _BV() macro is defined as:

#define _BV(x)   (1 << x)

this allows:

PORTC |= _BV(0);  // Set bit 0 only.
PORTC &= _BV(1);  // Clear bit 1 only.
PORTC ^= _BV(7);  // Toggle bit 7 only.

This can be further enhanced with the defines found in the 
processor header files:

// For atmega128
#include <avr/io.h>
UCSR0B |= _BV(TXEN0);  // Set bit 3 in UCSR0B only.

Using bit operators, one can do multiple, non-contiguous 
bits at a time:

PORTC |= (_BV(0) | _BV(2) | _BV(7));  // Set bits 0,2,7
PORTC &= ~(_BV(1) | _BV(2) | _BV(6));  // Clear bits 1,2,6
PORTC ^= (_BV(5) | _BV(3));   // Toggle bits 3,5

For more readability, you can define these macros:
#define bit_set(v,m)    ((v) |= (m))
#define bit_clear(v,m)  ((v) &= ~(m))
#define bit_toggle(v,m) ((v) ^= (m))
#define bit_test(v, m)  ((v) & (m))

bit_set(PORTC, _BV(0));
bit_clear(PORTC, _BV(3) | _BV(5));

// Check if transmit is complete
if(bit_test(UCSR0A, _BV(TXC0)))
{
    // Send data.
}

Better still, with the last example, you can make it even 
more readable with an additional macro layer:

#define usart0_transmit_complete() \
    bit_test(UCSR0A, _BV(TXC0)

That way you can write:

if(usart0_transmit_complete())
{
    // Send data.
}

and this hides the implementation in header files which can 
be easily changed if you're using USART1 instead of USART0 
(on the mega128) or if you moving to a different type of 
processor altogether.

Also take a look at the various assembly output of these 
macros (be sure to optimizations on). It's really quite 
instructive.

So, in the end, bitfields are really not a good model of 
the processors registers and actions that can be done on 
their bits.

Eric






reply via email to

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