sbi and cbi...

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

:roll: Whi in the hell deleted sbi and cbi in the latest WinAVR??? how were they previously defined and where, please?
Thankz , daqq

There are pointy haired bald people.
Time flies when you have a bad prescaler selected.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you could define it in assembler

Vince

I speak french easily than english.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who: guys from avr-libc
Why: not a clue
How:

//Returns a bit mask for the macro's setBit,
//clearBit and getBit
#define  BIT(x) (0x01 << (x))
//Set's a bit in a SFR
#define  setBit(p,m) ((p) |= BIT((m)))
//Clears a bit in a SFR
#define  clearBit(p,m) ((p) &= ~BIT((m)))
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who: me
Why: because we always said we'd do so -- this has been discussed ad nauseum

Btw., your BIT macro is identical to avr-libc's _BV macro.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't need sbi and cbi. They have always been awkward interfaces to what should be a very simple C construct. It has been possible for quite some time to use the work directly using standard techniques.

Why would you continue to use something as mind-twisting as

sbi(PORTX, PINXy);

When what you really mean is,

PORTX |= (1<<PINXy);
// or
PORTX |= _BV(PINXy);

If you've got an extensively tested codebase that was written and verified to work on an antique version of avr-libc, then you may well be better off continuing to compile that project using the antuque compiler now. Unless you're prepared to completely re-validate every aspect of the code. Because you never know... it might have been written to work around other known idosynchrocies of the older software, which may yield mixed results in newer versions.

If you're writing new code from scratch, then there can be no logical reason to want to continue to use cbi(), sbi(), etc. Direct C-like assignment is so much cleaner.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
Who: me
Why: because we always said we'd do so -- this has been discussed ad nauseum

Btw., your BIT macro is identical to avr-libc's _BV macro.

Yeah I know, but if I start writing my own macro's I might as wel do it totally independantly of avr-libc. Just if _BV ever gets chaged or something...

lfmorrison:
I disagree. Using the C way can be quite confusing, and it is very easy to read over it when debugging. For example, if you use a macro like sbi, you KNOW when you see it, a bit is set in a register. But you can easily mistake setting a bit, and setting several bits when you use PORTB |= ...
At least I made that mistake a few times...

Just my opinion though :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not go one step further and make pin manipulation easier with with something like this?

PORTB.5 = PINB.4;

Sure the sbi,cbi crap looks like outportb inportb.. why we needed that complexity is silly.. but why we have to master binary to do simple one pin manipulations is rather odd too!

PORTX |= (1<<PINXy); //URGH!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dmayo2 wrote:
PORTB.5 = PINB.4;

Just an FYI... bit names must follow the same rules as any other label/symbol name. That is they must start with a non numeric character. So while PORTB.5 is not valid C, PORTB.Bit5 is. It should be noted that a certain AVR compiler does break the "C" rule, and use the PORTB.5 format.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So while PORTB.5 is not valid C, PORTB.Bit5 is

-- ok

So how can we add something useful like that in AVRGCC?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dmayo2 wrote:
So how can we add something useful like that in AVRGCC?

See this thread.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> For example, if you use a macro like sbi, you KNOW when you see it,
> a bit is set in a register.

Oh, curious, what the heck makes you so certain about that?

After all, the old sbi macro had been defined for more than two years
as a simple C bit manipulation, which guaranteed quite nothing but the
prerequisites for a valid bit manipulation. You could apply that as
well to any memory location (including one pointing to a CPU register,
i.e. one below 0x20), and in fact, for the extended IO register
address space, it *is* a memory read/modify/write cycle anyway,
always. (It's even for the standard IO register range beyond what the
native SBI instruction could handle.) This was the major reason to
remove the macro -- people `trusted' it to generate an SBI instruction
where it often doesn't (and cannot).

Just get used to it, »foo |= bar;« *is* the C way. Generations of C
programmers have been coding their hardware register access using it
before you.

> But you can easily mistake setting a bit, and setting several bits
> when you use PORTB |= ...

That could even be a feature. :-) Occasionally, setting multiple bits
in one operation is really what you are for, and people writing half a
dozen of sbi() macros for that were actually one of the reasons to
eventually get done with that old macro.

No, sorry, I don't buy that argument. C (and any other language) is
full of things that aren't fool-proof, and it basically requires the
programmer not to be a fool in order to get something useful.

If you need macros, rather go the additional step further, and produce
a simple hardware abstraction layer. So instead of using that crude
sbi() way where you don't know what you've been doing half a year
later, abstract it like:

#define LEDPORT PORTB
#define LED_ON(ledno) do { LEDPORT &= ~(1 << (ledno)); } while(0)
#define LED_OFF(ledno) do { LEDPORT |= (1 << (ledno)); } while(0)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Going back to assembler for a bit, I also seem to recall a note somewhere about using SBI/CBI in a flags register with caution, possibly indicating that it's implemented as a RMW operation on the full register internally anyways. Though my memory could be failing me here. So I don't really see the advantage of SBI/CBI anyways, when ORI is just as efficient, and it can set more bits simultaneously.

Needless to say, I agree fully with the reasoning for pulling out the SBI/CBI macros.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
So I don't really see the advantage of SBI/CBI anyways,

I really (Really!) didn't want to revive this debate, but I guess that's happened already.
There are 1.5 advantages to SBI:

1) [1.0] It's interrupt-safe.
2) [0.5] On some AVRs, it can manipulate a bit independent of the other bits in the register.

In order to use these, of course, you need an sbi() macro Guaranteed to generate an SBI
instruction.

I do, however, accept the "maintenance and documentation headache" argument; I agree
that it isn't the best general way of setting a bit; and I definitely agree that there's no value
to an sbi() macro which just does a "|=" (may or may not generate an SBI).

And it's easy enough to write one's own for those (admittedly unusual) instances where it's
important.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Both good points.. as I said my memory could be failing me on that one. :)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
in fact, for the extended IO register address space, it *is* a memory read/modify/write cycle anyway, always. (It's even for the standard IO register range beyond what the native SBI instruction could handle.) This was the major reason to remove the macro -- people `trusted' it to generate an SBI instruction where it often doesn't (and cannot).

My believe is that optimization should use sbi and cbi where it is possible. Programmers responsibility is to use &=, |=, ^=... when it is necessary for bit manipulation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
t's implemented as a RMW operation on the full register

That's why (2) is only 0.5 of an advantage -- it's only available on some AVRs (Tiny13
is one, but I can't recite the others and it's not trivial to find out).

Personally, I'm curious whether history will ultimately see that single-bit-RMW as a
feature or a hazard. Not that it's a bad idea -- it's a Great idea -- but I wonder how much
legacy code there is out there which implicitly/unwittingly depends on the byte-wide
RMW (I've seen some of it wander through this Forum), and will break subtly -- probably
dependent on optimization level -- if moved to an AVR that does bit-wide RMW. But I'm
drifting OT now.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
Who: me
Why: because we always said we'd do so -- this has been discussed ad nauseum

And to be pedantic:
Who: me too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dmayo2 wrote:
Why not go one step further and make pin manipulation easier with with something like this?

PORTB.5 = PINB.4;

Sure the sbi,cbi crap looks like outportb inportb.. why we needed that complexity is silly.. but why we have to master binary to do simple one pin manipulations is rather odd too!

PORTX |= (1<<PINXy); //URGH!

Here is the canonical tutorial here on AVR Freaks on how to manipulate bits in C:
https://www.avrfreaks.net/index.p...

If you happen to get Circuit Cellar magazine, you can also see a slightly more extensive article about it in the July 2005 issue that just came out.

And get used to mastering binary and hexadecimal and bit manipulation; they are your basic tools to do embedded systems programming.

Eric

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am a heavy user of sbi()/cbi() and discovered with dismay that these macros had been removed.

The technical arguments for not using them sound fine, but I personally don't care. Why?
Because I use sbi()/cbi() purely for making my code easier to read.

I am a casual AVRGCC user, I don't program other stuff in C, am not a trained programmer, and use C for no other reason than AVRGCC.

I find the C standard bit manipulation very hard to read.

If the macros were not causing any grief to those people using the technically correct C use, why could they have have not been left alone for dumb-arse casual non propeller heads like me?

The solution of just removing it because it is not technically correct sounds like a typical engineering decision to me. (no offense guys as I was an engineer too - but I now work in product management and only then do you really appreciate the different mindset used in engineering).

Okay - granted it is an engineering tool, but there is nothing wrong in making engineering tools easier to use, providing those that want to use technical correctness can still do so.

My solution was to copy the macros from an old version of AVRGCC into the new version. Hopefully this works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try my "extentions" library from https://www.avrfreaks.net/index.p... for your old projects that require the CBI/SBI/OutP, etc commands. It also has the PortA.B1 style additions as shown elsewhere in this thread.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!