Arduino / compilers on uC

It had the effect of scaring me! Who knows what havoc it might wreak changing assumptions throughout all their libraries & packages! :-)

I'm pretty sure I don't want to re-define uint8_t to boolean--that would set my program back to the error condition. Plus we already know that 'bool' is broken in my context--I used up one of my AVR's

10,000 lifetimes to confirm that for you.

I appreciate the tips, but I'm satisfied I've solved the instant problem. I've got hardware to get working, that's my main task.

Yes, there's a lot of that going on. It's charming on the one hand, and terrifying on the other. ;-)

Thanks again, James Arthur

Reply to
dagmargoodboat
Loading thread data ...

That's a major objective of libraries and environments in general.

When I wanted to design something very simple where I had control of power consumption, I looked at and decided to avoid Arduino and similar systems.

I strongly suspected, based on experiences *decades* ago, that I would end up spending too much time discovering and circumventing the environments' unstated assumptions.

So: plus ca change, plus c'est la meme chose!

Beginners are *always* going to be hackers; it goes with the territory. If you try and force "good development practices" on them, you will put them off.

The decent ones will hack, become aware of the limitations of what they have done, and find ways to do better in the future.

The other ones can't be saved by *any* technology, as exemplified by the obvious generalisation of "You can write FORTRAN in any language"

Reply to
Tom Gardner

From what I can make out, precisely nobody does that now.

Hell's teeth, even *30* years ago too many didn't have a clue about what a compiler emitted. I had a standard interview question: given int foo; float baz; char bat = foo(baz, bar); what *kind* of instructions would you expect a processor to execute. Too many couldn't describe push/jsr/pop instructions.

Nowadays I've seen people developing soft realtime telecom systems only dimly recall FSMs are something you have in compilers :(

Reply to
Tom Gardner

Quite possibly, but starting from C/C++ makes it easy to be broken.

Consider how many subtle traps are outlined in in the Frequently Questioned Answers

formatting link

IMNSHO, C/C++ is a very bad starting point for a beginner - because C/C++ is so insanely complex that even its *designers* didn't realise what they had created! "Discovered" is the accurate frightening word in "Historically TMP is something of an accident; it was discovered during the process of standardizing the C++ language that its template system happens to be Turing-complete"

formatting link

Reply to
Tom Gardner

I did it once, forget how, but this seems to cover the technique:

formatting link

You can also add compiler options in a config file; look for a file in your Arduino install whose pathname ends in .../hardware/arduino/avr/platform.txt

Ok, well, I'm surprised. That would not easily happen through normal gcc development processes, but I suppose that the Arduino team are pretty slipshod in many other ways, so...

Clifford Heath.

Reply to
Clifford Heath

I wasn't suggesting that. You blamed the digitalWrite problem on the compiler, and I'm showing that it's the Arduino API you should be blaming, that's all.

The above C fragments should be hidden as C++ inlined template functions, which would make them beautifully clean yet still just a single opcode.

The compiler is not doing that. The designers of the Arduino API did that. It would be just as bad if they did it in assembly code.

Only the naive users use those layers, and those who know but who don't need to care.

Again, this is primarily the Arduino API, not the compiler.

Yes, you can, see my other message.

Swings, roundabouts. If you use libraries built by careless incompetent amateurs, you pay the price.

Yes. But the same goals could have been achieved without writing so much rubbish code.

I expect to get back to Arduino code soon, and that will mean finishing my C++ template library that handles port pins properly, among other things. I'll make it public when I'm happy with it.

Clifford Heath.

Reply to
Clifford Heath

I would have a hard time describing the call sequence when foo is declared as an integer and used as a function. ??? Was that supposed to be int bar; ?

--

Rick C
Reply to
rickman

Likewise. My DL11 debugger for the HC11 had a "talker" which fitted into the 256 bytes of RAM that were universally available; including the stack, variables, and room for all registers during a breakpoint. Or you could use that to put the talker in EEPROM, of course.

I had a version of the talker written in C++ at one point, still in

256 bytes... and we're talking more than 20 years ago...

The whole system was developed using a single bare chip that I bought with a copy of the "pink book" - I did everything else. That's why I'm a little scornful of people who weren't even born then, now being proud of their successes in the comparatively cushy Arduino environment.

32 *kilo-*bytes - we would have put the compiler in that :)

Clifford Heath.

Reply to
Clifford Heath

How is the type of U (and in particular, U.dat.flg) defined? I assume it is "boolean", since this explains the effects you are seeing.

The Arduino makes "boolean" a typedef of "bool", which is a standard C++ type. "true" and "false" are built into C++, and are not Arduino-defined. (Personally, I really dislike the way Arduino tried to "hide" or "simplify" C++.)

If the compiler knows that something is a boolean type, then it can assume that it can only ever be 1 (true) or 0 (false). Anything else is undefined behaviour. So if you have declared U.dat.flg to be "boolean" and put 0xff in it, you have lied to the compiler.

When the compiler sees "w = (U.dat.flg) ? true : false;", it /knows/ that U.dat.flg is already either 1 or 0 - because you have told it so, in your declaration of the type of U.dat.flg. If it is 1 (true), then w should be set to true - if it is 0 (false), then w should be set to false. Thus the statement can be simplified to "w = U.dat.flg".

Similar reasoning gives you the rest of your results.

The answer is to declare U.dat.flg as "uint8_t", since it can hold any value in that range.

Reply to
David Brown

There are two responses I can give: 1) I would expect a candidate to comment on those flaws 2) oh, picky picky picky

I'm not going to say which is more appropriate :)

Reply to
Tom Gardner

No assembly is needed - the compiler can generate optimal code from that source.

You are blaming the wrong thing - and therefore will not make progress.

It is /not/ the compiler that is doing this mapping - it is the Arduino API. This is designed to be simple for hobby users trying to make an LED turn on and off when you press a switch - efficiency is almost irrelevant to the Arduino tool designers.

If you are looking for efficient code, don't use Arduino.

That is what /Arduino/ users get.

If you want efficient code, just use "normal" AVR development tools. The easiest is to get the AVR Studio package from Atmel, which includes an IDE, debugger, and an installation of avr-gcc (the same compiler as used with Arduino, but without the Arduino layers). For Linux, you can get a package of avr-gcc from Atmel (including libraries, headers, etc.) and use Eclipse and Linux-based avr debugger tools.

On the AVR, you'll find a certain amount of function calls to support language features that the hardware cannot do directly. Depending on the AVR core, you might have a function call for a simple multiply - you certainly will for division, for floating point, and many other things.

But most of what you see here is the Arduino layers of functions and abstractions. These are not written very efficiently - indeed, there are lot of extra nested function calls that could be avoided by a simple template library.

If you want control, drop Arduino and use the AVR and avr-gcc directly.

The Arduino IDE is designed to be easy to use and friendly, not efficient or flexible. I am not convinced by it - I think it hides and restricts too much. But that's the way it is - you choose to use it or not.

(I used to write assembly for the AVRs, but it is a long time since I've done so - the compiler is excellent, and it is far more efficient to write good C or C++ code than assembly.)

It's great for hobby use - it is useless for serious work. But it is fine for programmers to start off sloppy, and then learn to write code properly later. My generation learned to program as kids in Basic with gotos, but that didn't hinder us from learning about structured programming later.

Reply to
David Brown

The error, I think (I'm hoping James will confirm it), was in his declaration of the type of U.dat.flg.

The numerical representation of signed integers is implementation defined - the bitwise operators are fully defined. But that's a minor detail - usually you only want to apply these operators to unsigned data, and typically to the fixed size types like uint8_t.

Reply to
David Brown

It's in the file Arduino.h, line 125

I don't know if you have easy access to such headers from the Arduino IDE, or if it is one of the things that the IDE hides to be "helpful" or "user-friendly".

Reply to
David Brown

It appears to be fixed by #include in the Arduino.h header, rather than incorrectly and confusingly trying to make "boolean" an "uint8_t" in C and "bool" in C++.

It would appear from this issue that Arduino originally used uint8_t for "boolean" even in C++, which is daft.

Reply to
David Brown

In an interview once I was asked how many multipliers were used in a CIC filter. I had to think for a moment to make myself believe I wasn't messing this up before I said, I didn't know there were any multipliers in one. I must have had a funny look on my face because the interviewer looked rather sheepish and said, yes, they don't use multipliers, in fact that is the main reason they are used. I felt I had embarrassed him somehow. Maybe he didn't have many candidates who didn't screw that one up.

As to your example, I find it confusing because there are different ways this could be correct, some requiring more than one error. But if this was intentional on and interview question I would not put it past an interviewer to do throw multiple mistakes in.

I should have said, "There won't be any instructions generated by the compiler." Then I would just side step the issue of exactly what was wrong with the code perhaps.

--

Rick C
Reply to
rickman

And that would be an interesting response, because it hints that a candidate had used an optimising compiler in anger, or even just liked to assure themselves that they understood what was happening "under the hood".

I could probably have an interesting conversation with such a candidate :)

Reply to
Tom Gardner

They don't have to be familiar with optimising compilers (not that there are many compilers that /don't/ optimise). They just need to be familiar with compilers that require valid C code in order to generate assembly instructions instead of error messages. The code, as given, cannot possibly compile - thus no instructions would be generated.

Reply to
David Brown

'boolean', 'bool', or 'uint8_t', as explained in detail above.

It's not my job to guarantee that Atmel/Microchip pre-initialize the EEPROM to please gcc.

But I'd tried to compensate by immediately directly writing '0' or '1' to the variable, and other operations that should've brought it to a legal condition. The compiler doesn't follow those instructions, instead either optimizing the operations out entirely, or only toggling the lsb.

Which is what the compiler did, and, in its wisdom, wouldn't allow me to write 'true' or 'false' to properly initialize a boolean.

Already done & described in posts above.

Cheers, James Arthur

Reply to
dagmargoodboat

[...]

Here's the problem--in the 'boolean' case, the compiler has optimized out my assignment of 'true' or 'false' entirely, and has reasoned that it can simply directly load the original, illegally 0xff-valued U.dat.flg into (word) w (=R15:R14):

The compiler thus defeats my instructions to substitute 'true' or 'false' for whatever odd value U.dat.flg happened to inherit from the EEPROM.

If I reverse the positions of 'true' and 'false' in that statement creating a toggle--the original code--the compiler only toggles the lsb, leaving me with w = 0xff, or 0xfe, both still illegal values.

By contrast with type 'uint8_t', the compiler generates an actual 0x1, then conditionally assigns that, or 0x0, as the result of the expression:

Cheers, James Arthur

Reply to
dagmargoodboat

that is how Bools operate,

0 = False, any other value is true...

Compilers may use what ever value they wish to set a bool to TRUE, but for better background control, the value

1 is usually the value used when directly assigning a bool.

Maybe Type casting your variable to a BYTE, and doing the bitwise operations will yield the results you are looking for.

Back in the day, we used to use return values for both bools and value. If the return was false than it's false, otherwise if it's true then the same value is also used for some sort of condition information.

Reply to
M Philbrook

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.