"|=" Is not RMW

Go To Last Post
72 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In another thread, kabasan wrote:
"|=" Is not RMW

 

https://www.avrfreaks.net/commen...

How can it not be RMW (ie, Read-Modify-Write) ?

 

Surely, it has to be:

  • Read the original value;
  • Modify - by applying the OR operation;
  • Write the result

 

kabasan wrote:
it can be called "read set write"

But the 'set' operation is a modification - so it is Read-Modify-Write

 

See: https://www.avrfreaks.net/commen...

And: https://www.avrfreaks.net/commen...

This topic has a solution.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 2, 2022 - 10:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


awneil wrote:

How can it not be RMW (ie, Read-Modify-Write) ?

 

David Prentice and others agreed some years ago:

https://www.avrfreaks.net/commen...

That whole thread is tangentially related, even though the topic is a bit different.  Note the side issue of which AVR generation is the target. :)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

This thread brings back a memory of something similar. Let me find it ...

 

Here we go: https://www.avrfreaks.net/comment/2983041#comment-2983041

 

It was about avr-gcc generating wrong code for this statement. You would expect it to toggle ALL high pins; except that it doesn't.

PINB |= (1<<PB1);   //can use PIN to toggle

 

Last Edited: Sat. Jan 22, 2022 - 01:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
avr-gcc generating wrong (sic) code 

Ah yes, that has been noted that GCC will spot a single-bit change in a RMW statement to a bit-addressable location, and "optimise" that as just a write to the single bit.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm lazy so haven't read linked threads but I guess one could argue that if the compiler boils it down to an atomic SBI/CBI that it's not necessarily an RMW but that kind of depends on what the logic that implements the opcode is actually doing. Does it really make a 1 bit access or is it reading 8, modifying 1, writing 8? 

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

It would be nice if "C" could add more finesse here, so the result could be assured & less compiler dependent

 

Like   PORTA |-rmw= (1<< PA1_FAST) | (1<< PA2_CAR) 

 

So in this example (maybe not the most favorable implementation), the oring of the 2 port bits would be restricted (-rmw) to not using rmw.

In this case, it would use two sbi operations, or whatever the processor offered up to do so.

If the request was not possible, it would flag an error.

 

Maybe the next rev of C will take care of clearing up some of these shortcomings

I'd bet there is a list kept somewhere of pending improvements & proposals.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Jan 22, 2022 - 05:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
How can it not be RMW (ie, Read-Modify-Write) ?

 

All compound assignment operations are RMW. The topic (and the accompaninyng confusion) might be linked to the discussion of the matter with regard to deprecation of compound assignment operations on `volatile` objects and deprecation of `volatile` in general. The initial problem with compund assignments is that their RMW nature is not too obvious in the source code, but still unavoidable on most hardware platforms.

 

See for more details:

 

https://stackoverflow.com/questi...

"Deprecating volatile" (http://www.open-std.org/jtc1/sc2...), and "3.6.2. Compound assignment" in particular

 

and a subsequent counter-proposal:

"De-deprecating volatile compound operations" [in embedded world] (http://www.open-std.org/jtc1/sc2...)

 

 

Dessine-moi un mouton

Last Edited: Sat. Jan 22, 2022 - 05:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
I'd bet there is a list kept somewhere of pending improvements & proposals.
C - Project status and milestones

"Dare to be naïve." - Buckminster Fuller

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

No one is complaining about the C language.   |= and &=~ are perfectly legal.

They work just fine on regular memory.

 

The only "problem" is when you have a mixture of regular and Write-to-clear-interrupt-flag bits in an SFR e.g. USISR

 

It is syntactically wrong to use |= to clear a single interrupt flag.   You are supposed to use =

It just happens that AVR compilers generate the SBI instruction and this happens to only affect a single bit.

If you use = the compiler generates the OUT instruction (which is twice as fast as SBI on a traditional AVR)

 

Oh,  in practice you always know the correct value to assign to USISR e.g. which flags to clear and what value for USICNT.

Likewise,  you know the correct value for ADCSRA or TWCR

 

I don't think that you need any "new" directive for the language.

It is just a question of writing syntactically correct statements.

 

It is a bit like Uncle Bob complaining about the need for volatile because his compiler was less aggressive than other compilers.

My view was that it was syntactically correct.   And one day in the future Bob's compiler might take the gloves off.

 

It is unwise to rely on something because it happens to work.

 

David.

Last Edited: Sat. Jan 22, 2022 - 05:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think that you need any "new" directive for the language.

PORTB |= (1<< PB4_LED)

PORTA |= (1<< PA1_FAST) | (1<< PA2_CAR)

Looking here It is ambiguous as to whether you will get r-m-w, or whether you will get only writes (sbi instructions)

--------------

 

PORTB |-rmw= (1<< PB4_LED)

PORTA |-rmw= (1<< PA1_FAST) | (1<< PA2_CAR)

Now it becomes clear, the ambiguity is removed

You will not get any rmw, it is being expressly prohibited That is the key difference.

In this case, it will result in 3 sbi instructions being generated

If it cannot be accomplished, you will get an error.

 

PORTB |= (1<< PB4_LED)

This is independent of whether you are trying to clear a flag by writing a 1 to it.

Here, you can simply ensure an sbi is used 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Jan 22, 2022 - 06:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

PORTB |= (1<< PB4_LED)

PORTA |= (1<< PA1_FAST) | (1<< PA2_CAR)

seems pretty clear to me.   Neither PORTB nor PORTA are Write-to-clear-interrupt-flag  SFRs.

 

So PORTB will get SBI and PORTA will get IN, ORI, OUT.   i.e. 2-cycles for PORTB and 3-cycles for PORTA.

 

Those are "traditional AVR" statements.   So you are not going to have any 1-cycle SBI solutions.

 

Two separate SBI will upset the timing sequence.  If the author requires a specific timing,  she would write two specific PORTA statements.

If she wants both bits to be set at the same time she would expect IN, ORI, OUT.

 

My comments in #9 are directly related to "Write 1 to clear interrupt flag" style of SFR.

Nothing to do with regular PORTx, DDRx registers where you will almost always use |=

 

David.

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

avrcandies wrote:

I don't think that you need any "new" directive for the language.

PORTB |= (1<< PB4_LED)

PORTA |= (1<< PA1_FAST) | (1<< PA2_CAR)

Looking here It is ambiguous as to whether you will get r-m-w, or whether you will get only writes (sbi instructions)

--------------

 

PORTB |-rmw= (1<< PB4_LED)

PORTA |-rmw= (1<< PA1_FAST) | (1<< PA2_CAR)

Now it becomes clear, the ambiguity is removed

You will not get any rmw, it is being expressly prohibited That is the key difference.

In this case, it will result in 3 sbi instructions being generated

If it cannot be accomplished, you will get an error.

 

PORTB |= (1<< PB4_LED)

This is independent of whether you are trying to clear a flag by writing a 1 to it.

Here, you can simply ensure an sbi is used 

Before you go off espousing changes to a 50-year-old language, perhaps you can digest the content of the thread that I linked to.  Than, if you have something new to present, do it with reference to the "prior art".  Or shall I quote all the pertinent sections of that 5-year-old thread here?  Will you then even read and consider them?

 

In particular:

avrcandies wrote:
PORTA |= (1<< PA1_FAST) | (1<< PA2_CAR)

>>You<<, the author of the code, have instructed the compiler to take the contents of a volatile location, apply some values to that content, and return the new contents to its volatile house.  Now, if you use SBI then one of the bits will be set before another.  Wasn't it you participating in the recent thread on dead time, and trying to draw a distinction between non-overlapping and its synonym?  Surely, then you are ABHORRED at the thought of two SBIs.  In fact, ANY SBI when working with a volatile location.

 

Or are you again setting yourself up as the final authority and sit ex cathedra regardless of the facts?

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Before you go off espousing changes to a 50-year-old language

Sorry about your brownout.  There are always some improvements coming along, surely we can't suggest nothing will change in 50 years?

Surely, then you are ABHORRED at the thought of two SBIs.

No not at all, this gives the ability to specify that they are desired, as was expressly mentioned.

 

Will you then even read and consider them?

I most certainly did...most of the discussion is a severe case of hand-wrangling and wincing that there is ambiguity & something should be done, for example from the link you mentioned:

  •  C doesn't know anything about registers, which is a major deficiency for low level programming. Even volatile doesn't really have the semantics we need,  there is a lot dependent on the implementation.
  •  At least, there needs to be formal attributes and semantics defined for things like register access, RMW behavior, memory barriers, instruction ordering etc.

Granted, this is a poster's opinion, but expresses the flavor of many.

 

Nothing therein shows how a request today (demand?) to prevent rmw is made (other than the particular compiler decides jumping in to help).  

Now, if you use SBI then one of the bits will be set before another. 

That is certainly a good observation--it is presumed fine, since the desire & intention was to use 2 (or in the simpler case, 1).  For 2 bits, it should default to form them in the given order, or include an option to specify otherwise. 

regardless of the facts ​​​​​​​

While some hypothetical suggestions have been put forth, most everything noted in the links are based on observed results.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

avrcandies wrote:

That is certainly a good observation--it is presumed fine, since the desire & intention was to use 2 (or in the simpler case, 1).  For 2 bits, it should default to form them in the given order, or include an option to specify otherwise.

 

Seriously,   the semantics of volatile mean that you can specify the order of execution.   You say what you want.   The Compiler and Optimiser will make the best decisions (within the rules of the language)

 

We are talking about USISR, TWCR, ADCSRA, WDCSR, UCSRnA, SPSR.   Hardly a massive number of special cases.   In practice several of these get interrupt flags cleared by read / write of the associated DATA register.

 

But it is not difficult to just write the statements correctly in the first place.

 

David.

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

 the semantics of volatile mean that you can specify the order of execution.

Well of course, but here some ordering of two bits must either be assumed (default) or possibly specified

If you give

  PORTA |= (1<<PA2) | (1<<PA1)

You say that the following (case A) is guaranteed to be generated by an AVR compiler?

sbi PORTA, 2

sbi PORTA, 1

 

and will avoid creating Case B:

in r20, PORTA

ori r20, 0x06

out PORTA, r20

 

I get and agree with what you are saying regarding the resetting of IRQ bits & their "strangeness"

 

I'm simply saying if something like the -rmw were an option of some sort you'd automatically know that case B becomes prohibited. 

Do you feel that would not be effective for what I presented?

The upgrade is a tradeoff, of how much work it takes to implement vs benefit, as well as considering any unintended problems such an upgrade may introduce.

It would certainly be simpler to have as a compiler option--that is a possibility.

the compiler generates the OUT instruction (which is twice as fast as SBI on a traditional AVR)

In terms of ports, out is certainly fast, but usually requires other instructions to first read the port, fiddle with the bits, then out.

sbi would have an edge for 1 bit, or 2 bits on xmegas (& newer?) avrs.

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Jan 22, 2022 - 10:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

  •  At least, there needs to be formal attributes and semantics defined for things like register access, RMW behavior, memory barriers, instruction ordering etc.

In Embedded C are changes to C99 for CPU and I/O registers, RMW, and address spaces; instruction ordering may be implementation defined.

TR 18037: Embedded C | Project status and milestones

 

"Dare to be naïve." - Buckminster Fuller

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

Or all of you nuts could just write assembler to start with.  devil  S.

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

Isn't this how avr-gcc used to work?

If you said "PORTB |= 4;", you would have gotten LD/OR/ST.  If you wanted an SBI, you would have used the "SBI(PORTB, 4);" function provided by avr-libc (presumably implemented via inline assembler.)

At some point (quite a LONG TIME ago) they made the optimizer smart enough to turn the single-bit set (with constants) into an SBI, and deprecated the SBI macro in favor of "more standard-looking C."

 

Compilers are supposed to be pretty hardware independent, and I doubt that the compiler authors are likely to implement anything like the suggested "|-rmw=" operator that has been suggested.

(There is nothing like that in the "embedded C" spec gchapman linked.)

 

(It's all becoming obsolete, anyway, with 32bit RISC chips and their separate set/clear/write registers for IO.  What did you expect  "myport |-rmw= mybits;" to do in the case where avoiding rmw was impossible?  (eg myport is non-constant))

 

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

Scroungre wrote:

Or all of you nuts could just write assembler to start with.  devil  S.

 

That's the easy way. Just build a processor core to your taste and take it from there... cheeky

 

Neil

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

AndreyT wrote:
All compound assignment operations are RMW.

Indeed - as far as the C language semantics are concerned.

 

I think the confusion comes from the specific GCC optimisation that it can (will ?) spot a single-bit update on a bit-addressable register written in the RMW idiom ('|=', '&=') and implement that a single-bit write (SBI, CBI) ?

 

I guess the closest standard C idiom to specify a single-bit operation would be a bitfield?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

AndreyT wrote:
All compound assignment operations are RMW.

Indeed - as far as the C language semantics are concerned.

 

I think the confusion comes from the specific GCC optimisation that it can (will ?) spot a single-bit update on a bit-addressable register written in the RMW idiom ('|=', '&=') and implement that a single-bit write (SBI, CBI) ?

 

Exactly. The math says ORing with 1 always gives 1, while ANDing with zero always gives zero. So replacing a RMW whose result is independent from the starting value by a simple write operation may seem a great idea: you optimize at least 3 instructions into a single one (RMW -> W).

And it usually is.

The problems arise when one or both of the read and modify ops that were removed had some hardware level side effect(s) the programmer was expecting to happen, based on what the C standard says.

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

barnacle wrote:

Scroungre wrote:

 

Or all of you nuts could just write assembler to start with.  devil  S.

 

That's the easy way. Just build a processor core to your taste and take it from there... cheeky

 

Neil

 

That's what this guy's up to:

 

https://arstechnica.com/informat...

 

(To be fair, it might be awhile before he gets an LED to go blinky, though, and my parents' garage never looked like that!)  S.

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

#22 and previous, will you stop ASM noise, please. It is a serious C-talk.

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

Looks like they may be taking my suggestion, at least using their own flavor (#16):

 

Inherent processor-architecture based address spaces are implementation-defined and provided by the compiler for that processor architecture and as such will be available to all applications normally supported by the processor. Examples include accesses to various native data spaces, or data spaces where write and read operations are not symmetrical.

 

I/O register definition for intrinsic or user defined address spaces Input/Output registers may be located within any of the address spaces: either intrinsic address spaces or new address spaces defined by addressmod as part of an application. The _Access modifier provides a means to extend the information associated with the declaration. The _Access modifier has three optional arguments that further may be used to define the access to the variables declared by declaration; these arguments are defined as follows: - access method defines the hardware based access restrictions typically found on Input/Output registers, and is one of read_write, read, write, or read_modify_write; the default is full access (read_modify_write);

Before you go off espousing changes to a 50-year-old language

They do update it slooowly, as they should.  It's actually good to know they are investigating potential changes, not necessarily this one in particular, but overall---to keep honing and improving aspects that have previously been implemented as "workarounds." 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. Jan 23, 2022 - 05:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

grohote wrote:

#22 and previous, will you stop ASM noise, please. It is a serious C-talk.

 

And if you read the posts there is a lot of discussion about SBI/CBI STS and such ....All of which are ASM operators, so this 'noise' as you put it is in actuality part of the discussion.

 

Keep in mind that when you compile a C program for a microcontroller, the compiler puts out an LST file of the program in ASM.

 

 

Jim

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

True, it is all about ASM at the end, but implying that "ASM does not have such problems" is not constructive, rather a distraction.

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

It is, however, also a useful suggestion.  If you don't like what the compiler does, write some inline assembler. 

 

Problem solved without trying to change features in a 50-yr. old language, and without having to change the compiler, either.  S.

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

My two cents:

Regardless of the C standard,

when an SBI or a CBI has essentially the same effect as the corresponding RMW,

the compiler has my blessing to generate an SBI or a CBI

In other cases, it does not.

 

That said, getting a desired SBI or CBI should not be hard.

Macros that expand to a line of inline assembly would be good enough.

 

Some statements the compiler should reject altogether:

PINB |= 2;

The compiler is unlikely to generate assembly that accomplishes the assignment.

If it did, the author of the statement would likely be astonished and annoyed.

Moderation in all things. -- ancient proverb

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

and is one of read_write, read, write, or read_modify_write; the default is full access (read_modify_write);

That sounded interesting until the types weren't actually defined any further, and "rmw" was specified as the default (normal case.)  (What's the difference betwee read_write and read_modify_write ??)  I don't see how any of them would guarantee atomicity or non-disruption of other bits/bytes of the same register.

 

Generating a single sbi/cbit instruction is relatively easy.  Having a single C statement generate multiple sbi/cbi instructions is so full of issues that I don't ever see it happening.

 

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

What is wrong with "PINB |= 2"?

Edit: Never mind, I think I understand what you meant.

Last Edited: Mon. Jan 24, 2022 - 02:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

ezharkov wrote:
What is wrong with "PINB |= 2"?

Edit: Never mind, I think I understand what you meant.

For completeness:

 

https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

 

So what the programmer likely required with 

PINB |= 2

is to toggle PB1 - by writing a 1 to PINB.1

 

But, if an RMW is actually performed, that statement will actually:

  1. Read the whole PINB register - all 8 bits;
  2. Set bit 1 in whatever was read;
  3. Write the whole result back to PINB - all 8 bits.

 

So, if any other bits in PINB were at 1, those pins will also get toggled - which is probable not what the programmer intended.

 

EDIT

 

However, if the programmer really did want a RMW for some reason, but the compiler just did a CBI/SBI instead - then that wouldn't have the effect that the programmer intended...

 

+ some typos

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Jan 24, 2022 - 10:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


awneil wrote:

However, if the programmer really did want a RMW for some reason, but the compiler just did a CBI/SBI instead - then that wouldn't have the effect that the programmer intended...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Does any of this really matter?

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

Brian Fairchild wrote:
Does any of this really matter?
+1 ;-)

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

Brian Fairchild wrote:
Does any of this really matter?

Look at the number of posts criticising use of "|=" vs "|" - clearly people do think it matters!

 

EDIT

 

That should, of course, be  "|=" vs "="

 

blush

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Jan 24, 2022 - 02:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No,  they criticise the use of |= vs =

 

It is important that you use the appropriate statement for the particular operation.

 

I have yet to see some hardware feature that you can't control efficiently with regular C e.g. avr-gcc

(apart from the use of the Carry flag)

 

David.

Last Edited: Mon. Jan 24, 2022 - 02:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
No,  they criticise the use of |= vs =

blush

 

david.prentice wrote:
It is important that you use the appropriate statement for the particular operation.

Indeed - so if the compiler actually implements an "=" (assignment) when the coder wrote "|=" (RMW), that can get confusing ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

Does any of this really matter?

 

Only if your bored and want to get into a debate?

 

awneil wrote:
Look at the number of posts criticising use of "|=" vs "|" - clearly people do think it matters!

 

To each their own?  I suppose  if it bothers you THAT much, move on to something else that meets your specifications?

 

I can remember when I moved from ASM to C and this tutorial was strongly suggested to me:

 

https://www.avrfreaks.net/forum/...

 

Deans first example of setting a bit - or bits as the case may be:

To set bit 0 in foo and then store the result back into foo:

foo = foo | 0x01;

The OR operation is used between the variable that we want to change and a constant which is called a BIT MASK or simply the MASK. The mask is used to identify the bit that we want changed.

Remember that we write the constants in hexadecimal because it's shorter than writing it in binary. It is assumed that the reader knows how to convert back and forth between hex and binary. ;-)

Usually, though the statement is made shorter in real programming practice to take advantage of C's compound assignment:

foo |= 0x01;

This is equivalent to the statement above.

 

TO play fair, I looked at my second source....SmileyMicros C programming for micocontrollers, and in my skimming through the pages, I only found one mention of using '|=' on page 61 in Table 6.

I cannot scan/post the table, but the table lists the operators like |=, +=, &= etc., and Smiley writes about these:

This provides a short cut way to write an expression.

 

 

Does any of this mean anything?  Probably not.  Again, if one does not approve of '|=' or its family members, then find another post to participate in.  Kind of like 4 way junctions.

 

Back under the rock I go.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
if one does not approve of '|='

As David said, it's not a case of approving of anything - it's understanding the difference, and choosing the appropriate one in each particular case.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
Deans first example of setting a bit ...

Note that any [let's call it] generic use isn't the topic here.  Rather, it is when foo is volatile, in particular an AVR volatile I/O location.  See

https://www.avrfreaks.net/forum/...

and other links in the early responses in this thread to start the rehash.

 

A related "problem" case is when the AVR I/O location in question contains I/O event flags that are cleared by writing a 1.  And even more complicated when such IFs are intermingled with other non-IF bits in the same I/O register.

 

I won't bother doing a lot of quoting from the link above.  Read the OP, and then go to

skeeve wrote:

On PORTx, DDRx, GPIOx and some other registers,

one can argue sensibly about whether generating an SBI instruction for an |= violates the volatile rules.

I've done so.

To summarize my position: It does, but the compiler should do it anyway.

On PINx and interrupt flag bits, there is only one sensible position:

The compiler is wrong.

I'm not convinced that *any* assignment to any of those registers is valid C.

 

...and then see the further discussion.  Pay also attention to what the C standard about volatile.  And then count the angels on the head of the pin.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
I won't bother doing a lot of quoting from the link above.  Read the OP, and then go to

 

I red the OP in the link you posted.  And thats a good point.  My question to your point is this.  If "|=" is a RMW, then since your are OR'ing, does it matter much if you work on one bit, or multiples?  

 

Meaning....

 

We have an I/O thingie  could be anything-ie.  Its current contents are 0b00011000.  I want to set bits 7 and 0, and leave the others alone.

 

thingie |= (1<<7) | (1<<0);

Based on what I see on page 54 of Smiley's book 'thingie' should now be 0b10011001 thus leaving the other bits alone.  So why the fuss?  I admit I am not as good as pretty much everyone in this thread on programming so my apologies if I red as dense.

 

With regards to the dot extension that CV uses, I prefer it.  Easy to read.  But then again Studio uses the dot extension for XMEGA and the newer devices.  Evolution?

 

theusch wrote:
And then count the angels on the head of the pin.

The picture renders too small on my desktop...Cannot red teh text.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
With regards to the dot extension that CV uses, I prefer it.  Easy to read.  But then again Studio uses the dot extension for XMEGA and the newer devices.  Evolution?

The CV one is an actual extension - not a standard language thing - whereas the dot used by the XMEGA et al headers is standard C (so not specific to Studio or GCC)

 

See: https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Jan 24, 2022 - 04:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
Does any of this really matter?
Quote:
Yes.

Using PINB |= 2 to generate an SBI instruction is not rare.

Whether one gets it can depend on the optimization level.

 

According to C, "access" is implementation-defined.

That means the the definition is supposed to be documented.

Do any of the AVR compilers come with such documentation?

Is the definition allowed to change with optimization level?

Moderation in all things. -- ancient proverb

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

Should the compiler translate PINB = 2 into an SBI instruction?

Moderation in all things. -- ancient proverb

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

I would guess that PINB =2  PINB |= 2 will actually do what the punter wants.   i.e. toggle the PORTB.1 pin and ignore all the other pins.

 

Semantically,  it should read all of the output latches and flip every bit that happens to be set.

And I doubt if that is what the punter intended.

 

Yes,  I suppose that the avr-gcc compiler could spot that PINB was a "special type of SFR" and issue a warning.

But should it also warn about all the SFRs that contain interrupt flags ?

 

Surely we should just accept that some SFRs are not normal RW memory.

And that it is our responsibility to use the appropriate statements.

 

I would get very irritated if we start to get superfluous warnings.   Or if the Compiler changes or it tries to be too clever.

 

David.

 

Edit.   My apologies.   I could have sworn that I originally wrote |= but apparently not !!

Last Edited: Tue. Jan 25, 2022 - 05:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
we should just accept that some SFRs are not normal RW memory.

Absolutely.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One reason to allow an option (such as -rmw, or perhaps some other finesse control) is that there is then no doubt the result can be controlled as desired (such as preventing rmw).

Presently is it slightly a guessing game as to what will happen (though not really guessing, since you could deep dive into the compiler documentation, assuming this is notated)

On the compiler side, it has to guess--is the user ok with rmw or not.  It generally does (and should) choose rmw, but it does not always.

So if you hand someone a screenshot of your C code and ask them what will be the result ..they can't say with certainty. 

Perhaps that is the status quo & fine for now, but from the link posted, it appears they are at least starting to consider a variety of such matters and ways to improve them.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

jgmdesign wrote:
If "|=" is a RMW, then since your are OR'ing, does it matter much if you work on one bit, or multiples?  

That is kind of the point of the philosophical discussion, to me.  Of course you are TELLING the compiler to explicitly do a RMW.  Now, when the compiler optimizes it on an AVR target to an SBI, it is NOT doing the RMW.  That is the question I raised in the OP in the linked thread.  I cannot really disagree with skeeve that [paraphrasing] yeah, it may not be exactly right but our AVR toolchains should probably work that way. Further the C standard of that era says to me that this "volatile" keyword has some implementational leeway.

 

jgmdesign wrote:
So why the fuss? 

Because your thingie >>is<< an I/O location so it is volatile.  Tell how you implement your two-bit change in machine language. [two bits of change means you get a quarter back, right?]  IN-OR-OUT right?  So a RMW. :) Anyway, an interrupt can hit after the IN and the OUT louses up your thingie.  And if you do an SBI-SBI  then your bridge has shoot-through, right?

 

In the end it is just one of the things to always be careful of.  I've had a couple of introduced I/O races in seemingly innocent code, and they were a bitch to find.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

jgmdesign wrote:
The picture renders too small on my desktop...Cannot red teh text.

From Wikipedia, the free encyclopedia

Jump to navigation Jump to search

"How many angels can dance on the head of a pin?" (alternatively "How many angels can stand on the point of a pin?"[1]) is a reductio ad absurdum challenge to medieval scholasticism in general, and its angelology in particular, as represented by figures such as Duns Scotus and Thomas Aquinas.

 

In modern usage, the term has lost its theological context and is used as a metaphor for wasting time debating topics of no practical value, or questions whose answers hold no intellectual consequence, while more urgent concerns accumulate.[1][4]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Mon. Jan 24, 2022 - 06:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ho Ho: This is fun:

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$ avr-gcc --version
avr-gcc.exe (AVR_8_bit_GNU_Toolchain_3.6.2_1778) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$ cat freak.c
#include <avr/io.h>
void foo (void) {
    PINB |= 0x02;
}

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$ avr-gcc -Og -mmcu=atmega328 -S -c freak.c

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$ tail freak.S
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        in r24,0x3
        ori r24,lo8(2)
        out 0x3,r24
        ret
        .size   foo, .-foo
        .ident  "GCC: (AVR_8_bit_GNU_Toolchain_3.6.2_1778) 5.4.0"

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$ avr-gcc -Os -mmcu=atmega328p -S -c freak.c

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$ tail freak.S
        .type   foo, @function
foo:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        sbi 0x3,1
        ret
        .size   foo, .-foo
        .ident  "GCC: (AVR_8_bit_GNU_Toolchain_3.6.2_1778) 5.4.0"

Nigel@PC-NOR-23F1 MINGW64 ~/Project/Freaks
$

 Well I'd never have thought -Og versus -Os would make such a difference.

 

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

Yes, it does.   I noticed that recently.   AS4.xx used to use -Os.  AS7.0 used to use -O1.  AS7.0 defaults to -Og nowadays.    (AS7.0 defaults to -Os for Release, -Og for Debug)

Last Edited: Mon. Jan 24, 2022 - 09:41 PM

Pages