[Top][All Lists]

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

[avr-libc-dev] Re: What Happened to the sbi() and cbi() Macros????

From: E. Weddington
Subject: [avr-libc-dev] Re: What Happened to the sbi() and cbi() Macros????
Date: Sun, 30 Jan 2005 23:25:13 -0700
User-agent: Mozilla Thunderbird 1.0 (Windows/20041206)

Bruce D. Lightner wrote:

E. Weddington wrote:

Erik Walthinsen wrote:

E. Weddington wrote:

They've been deprecated for a long time. They were finally removed in the 1.2.x series. They're gone for good.

I still have not figured out what the logic is behind removing two of the most useful macros possible on a machine where ALL IO is preformed by setting and clearing bits.

Please, enlighten me.

Go look at the implementation of the sbi and cbi macros and you'll see why. ;-)

I just looked at the file "sfr_defs.h" where sbi() and cbi() macros are defined and I don't see what the problem is, nor do I see anything humorous about the code or the situation...

Eric, please enlighten me! Exactly why were the "sbi() and cbi() macros removed?!!

Are *all* the "input/output" macros gone (e.g., bit_is_set(), bit_is_clear(), inb(), inw(), outb(), outw()...)?

AFAIK, bit_is_set, bit_is_clear are both still in. But sbi, cbi, inb, inw, outb, outw, outp, inp are all gone now.

If you need someone to "maintain" the file "sfr_defs.h", then I'm sure you can find lot's of volunteers...like me!

I've followed the "avr-gcc" mailing list every day for many years and I don't remember *any* inquiries, surveys, or votes regarding this recent "improvement" to avr-gcc, namely removing "depricated" I/O marcos.

Well, the problem is that it's not the avr-gcc list is where this stuff is usually discussed, it's the *avr-libc-dev* list.

So, please enlighten us as to why these macros cannot remain in the library. I for one am ready listen to reason, but please also think long and hard about what removing them does to many of us long time end-users of avr-gcc. And don't get me wrong, we folks that make daily use of the wonderful things that the maintainers of "avr-gcc" and it's libraries have created truly do appreciate your hard work! And, we thank you!!

However, as the comments in the "sfr_defs.h" source code say regarding the "missing" macros, they are included for...

  "For backwards compatibility"

I personally have created well over 100 "avr-gcc" projects that make use of one or more now "depricated" I/O macros. I have hundreds of thousands of AVR-based devices in the field that use avr-gcc source code that references these macros. Responsibility for supporting that installed base resets with me.

Although I, like most(?) others make less and less use of "depricated" macros for new code, I do not want to be forced to revisit perfectly fine, field-proven, debugged and tested avr-gcc code just because a macro was "depricated" and I (or one of my customers) has decided to (or has been forced to) upgrade the "avr-gcc" toolset. I don't know about you, but I know that "fixing" working source code is an invitation for new bugs. And, bugs cost time to fix, and time is money...to anyone but a hobbyist.

Does anyone else want to comment?  Am I overreacting?

Sure. I definitely understand, especially from a commercial point of view.

It was discussed on avr-libc-dev a while ago. These macros were deprecated and have been that way for a while. Yes, it was even in the documentation that they were deprecated.

Victoria Welch wrote:

E. Weddington wrote:
Go look at the implementation of the sbi and cbi macros
and you'll see why. ;-)
Perhaps some of us just use the sbi/cbi macros (quite successfully, I might add) and have been since we started using the avr-gcc toolchain.

Personally, I take that comment as elitist, arrogant, patronizing and insulting to those of use the language and are not low level gurus.
LOL! Geez, all I said was to go look at how they were implemented. The source code is available to all. It certainly had nothing to do with me being arrogant and elitist. It had more to do with me not having enough time to explain it; I assumed that by looking at how they were implemented, the reason for removal would become self-evident.

I'm certainly not against having a non-confrontational discussion about this, so let's revisit the subject. To this end, I've included Joerg Wunsch in the CC list as he's also now co-maintaining avr-libc and I've also cross-posted this to the avr-libc-dev list, where it really belongs.


From what I remember, is that avr-libc was originally using macros to do IO, such as outb(), inb(), outp() and inp(). These were originally modeled after the Linux environment. It was pointed out that this was not really necessary, and not typical in an embedded environment. Most cross-compilers would define registers and use "direct access" to write and read from them, for example:

PORTA = 0x01;
PORTB |= 0x02;
PORTC &= ~0x04;
var = PIND;

This was adopted as what should be used, so outb(), inb(), outp(), and inp() were deprecated. In fact, the later versions of those macros were implemented as the "direct access" show above.

cbi() and sbi() were similarly implemented, and it was thought instead of having a somewhat "redundant" macros was rather pointless, and they too were deprecated.

Now before anybody gets up in arms about this, I just want to point out, that these macros were labeled as deprecated in the avr-libc user manual for some time. There are many open source projects where items that are deprecated in one or two releases, are removed in later releases, for example: gcc, gdb, binutils, etc.

There were many instances where Joerg or I would point out to users that all of these macros were deprecated and should not be used. And we pointed this out on the avr-gcc list and at AVR Freaks.

We are certainly not unwilling to listen, but honestly, we never got any feedback from people who wanted to keep it. What were we supposed to do?

Now, on moving forward...

Bruce, for "legacy" code that must require cbi() and sbi(), would it be reasonable to patch your own version of avr-libc to provide these macros? The implemenations are not that hard.

As to the idea that these were very useful macros, then I have a counter-proposal:

I would like to create an API that can be used to operate on bits. I propose that this would be a new header, <avr/bit.h>. In this header, would be macros that would set, clear, toggle, read, and test bits in a variable. These macros would also be defined to work on variables of size 8 bit, 16 bit and 32 bit. For example:
#include <inttypes.h>
#define bit_set_8(var, mask)   ((var) |= (uint8_t)(mask))
#define bit_clear_8(var, mask)   ((var) &= (uint8_t)~(mask))
#define bit_toggle_8(var, mask)   ((var) ^= (uint8_t)(mask))
#define bit_read_8(var, mask)   ((var) & (uint8_t)(mask))

#define bit_set_16(var, mask)   ((var) |= (uint16_t)(mask))
#define bit_clear_16(var, mask)   ((var) &= (uint16_t)~(mask))
#define bit_toggle_16(var, mask)   ((var) ^= (uint16_t)(mask))
#define bit_read_16(var, mask)   ((var) & (uint16_t)(mask))

// 32 bit versions here

// Shorter named versions for the common operation.
#define bit_set(var, mask)   bit_set_8(var, mask)
#define bit_clear(var, mask) bit_clear_8(var, mask)
#define bit_toggle(var, mask) bit_toggle_8(var, mask)
#define bit_read(var, mask) bit_read_8(var, mask)

There are several reasons why I think this would be useful:
- Doing bit operations with the C language bit operators is confusing to most newbies. This usually has to be explained again and again. These macros make it easier for newbies. - It's makes it easier to read what operation is happening rather than trying to remember the bit operations themselves. - The typecasts are in there to workaround the C language Standard of promoting the operands of bit operaters to ints, which are 16 bits for the AVR (see the avr-libc FAQ for more discussion of this). If these macros are used, then users don't have to remember to do the typecasts, which should, in theory, help with the size of their code.

I would also like to propose two other macros for this file:

#define BIT(x)   (1 << (x))
#define LONGBIT(x)   ((uint32_t)1 << (x))

Yes, the BIT() macro is the same as _BV(). The _BV() macro is confusing in two ways: one has to remember that "BV" stands for Bit Value. The name BIT is slightly more descriptive. And _BV() has a leading underscore, which technically is supposed to be reserved for the "implementation" according to the C Standard (in this case the library). Having to type out the underscore is annoying. I feel that it's easier to just write out "BIT".

The LONGBIT macro is needed to provide a conversion from a bit number to a 32-bit mask.

Personally, I don't care whether the macro names are upper or lower case. I'm fine with bit() and longbit() too.

I feel that it is important that the bit macros supply a bit "mask" and not just a bit number because a bit mask is more flexible in defining non-contiguous bits to operate on. This means that one can do this:

bit_set(PORTD, BIT(0) | BIT(2) | BIT(4) | BIT(7));
bit_clear(PORTG, BIT(1) | BIT(6));
bit_toggle(PORTE, BIT(5) | BIT(3));
bit_read(PORTF, BIT(7));

Would this proposal be useful?

Comments welcome.


reply via email to

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