Go here to sign up for The Embedded Muse.
The Embedded Muse Logo The Embedded Muse
Issue Number 479, December 4, 2023
Copyright 2023 The Ganssle Group

Editor: Jack Ganssle, jack@ganssle.com

   Jack Ganssle, Editor of The Embedded Muse

You may redistribute this newsletter for non-commercial purposes. For commercial use contact jack@ganssle.com. To subscribe or unsubscribe go here or drop Jack an email.

Editor's Notes

SEGGER embOS Ultra Cycle-resolution accurate RTOS

Tip for sending me email: My email filters are super aggressive and I no longer look at the spam mailbox. If you include the phrase "embedded" in the subject line your email will wend its weighty way to me.

Quotes and Thoughts

"The secret of getting ahead is getting started. The secret of getting started is breaking your complex, overwhelming tasks into small manageable tasks, and then starting on the first one." Mark Twain.

Tools and Tips

Please submit clever ideas or thoughts about tools, techniques and resources you love or hate. Here are the tool reviews submitted in the past.

On C Sequence Points

While it’s easy to brush C off as a super-assembly language it's actually quite rich, expressive and has some dark holes that elude too many developers. Indeed, the C99 standard is over 500 pages long, is rather cryptic, and reading it is a sure cure for the worst case of insomnia.

Consider the following:

a =  ++b + ++c;

What does it do?

No one knows. The C standard leaves the details up to the compiler writer. It does define the notion of "sequence points," which are nodes where, as the standard states, "At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place."

The standard lists where sequence points will occur. Note that there are no sequence points within the assignment statement listed above. Whether the result is the sum of the two variables in their incremented or non-incremented states (or with variable a or b incremented and the other not) is entirely undefined.

Common software standards emphasize this ambiguity. MISRA Rule 12.13 states: "The increment (++) and decrement (--) operators should not be mixed with other operators in an expression."  But the explanatory text says "The use of increment and decrement operators in combination with other arithmetic operators is not recommended..."

The assignment operator is not an arithmetic operator (it’s defined, logically, as an "assignment operator" in the C standard). So MISRA apparently permits:

a[i++]  = i;

...even though the result is undefined, as cryptically noted in the C99 standard: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored."

As a footnote in the standard notes, this means:


results in unspecified behavior, though of course the logically-equivalent operation:


is just fine.

CERT rule EXP30-C is much stronger than the MISRA rule: "Do not depend on order of evaluation between sequence points." In fact, the standard lets compilers evaluate parts of an expression with all of the discipline of sailors at a bar on shore leave. It says "The order in which subexpressions are evaluated and the order in which side effects take place, except as specified for the function-call (), &&, ||, ?:, and comma operators" is unspecified.

Many developers think that precedence rules determine which part of an expression gets evaluated first, but that's not necessarily the case. In the expression

fa() + fb() * fc()

it's perfectly acceptable for the compiler to evaluate fa() first. And adding even a Lisp-like swarm of parenthesis doesn't change anything. We have to rely on the rules of sequence points if evaluation order is important. There's a fantastic description of this issue here: http://www.eskimo.com/~scs/readings/precvsooe.960725.html.

CERT's software standard explicitly addresses sequence point issues in macros. Rule PRE12-C says: "Do not define unsafe macros." An example given is:

#define  ABS(x) (((x) < 0) ? –(x) : (x))


m = ABS(++n);

Which will expand to:

m =  (((++n) < 0) ? -(++n) : (++n));

And that clearly has no sequence points so its behavior is unpredictable.

The logical AND (&&) operator does specify a sequence point, but it, and the logical OR, have another twist. The standard reads: "Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to 0, the second operand is not evaluated." (There’s a similar statement for logical OR.)

That means code like:

if ((  i == num) && (( j++) > 0){code};

...will not always increment variable j.

CERT warns developers about this sort of code via rule EXP-02-C: "Be aware of the short-circuit behavior of the logical AND and OR operators."

Obviously developers have to be very aware of these sorts of issues to develop reliable code. But there’s another issue:some companies ask sequence point questions on tests for prospective employees.

Few applicants get the answers right.

A Code Port

A reader who wishes to remain anonymous writes:

I have worked on the port of a very old code base which was in use in the aerospace industry for some decades. The code was so old that no one deeply understood it. It was of course subject to the usual V model certification process, every aspect of development requiring documentation.

This code certainly suffered from code rot, and there was no way that the redesign could just be a "port". Many problems had been there since the first release. Some were "features" which I would not have expected in any professional product.

For instance, use of C source files with NO associated headers - the referenced functions declared as prototypes in the OTHER sources where they were used (I was even surprised that this compiled without problems). It works, but it completely breaks up the idea of modularity in a C based design. Caused no issues with certification apparently but a real no-no in my book.

Another was the absence of any real thought to error handling or assert behaviour, even with prototype hardware on the table, and a general dearth of asserts in the code. Many other aspects of the design seemed overcomplicated. I won't list them.

One big human problem was that the anticipated cost of (re)documenting the project led to to resistance to carrying out structural change. It was just supposed to be a "port", right? Understandable, but goes AGAINST the principle of "keeping the house clean as we go".  My perspective was and is - get the design right first, then document it. (On a fresh project I would always start by documenting BEFORE coding and maintaining the docs as we go, but in this situation that could not happen of course.)

This was my first involvement in aerospace, which has a great record of safety. But in terms of code quality and practice, I had seen better. It made me ask myself questions about the tradeoffs associated with these heavy requirements for documentation, and if the model could be improved. Perhaps it causes a lot of focus and effort to go on things which make improvements to software quality harder or more expensive. Of course many will (perhaps rightly) say that we were not doing the documentation process very well. I don't pretend to know the answer to this, but I know it is a problem. I am curious about the perspectives of you and your readership.

More on Low-Power Design

In response to last issue's article on battery-operated systems, Josh wrote:

I don’t know if you have ever seen the Energizer Ultra Lithium batteries, but they are pretty amazing. They come in AA form factor, you can buy them everywhere, they are relatively cheap, they are specified to have a 25-year shelf life, and the IR is basically flat across most of the discharge…

We have shipped thousands of units using these batteries over the past 7 years and so far have not seen a single battery-related problem. After running for 7 years with a 5uA constant current draw, these batteries do not show any material decrease in output voltage (~1.75V).

Data sheet here…

John Taylor wrote:

One of my first tasks starting at a new company was to deal with RFID tracking tags that ran off of lithium primary cells that were only using about 35% of the available capacity due to brown outs that increased in line with the increasing ESR as the battery discharged.  At the 65% level, they would get into a reset and repeat death spiral.  Our tag life was supposed to exceed 5 years but we were only getting under 2.

I ended up using a 100uF ceramic (100uF, 10V, X5R) down selected from about 10 options at the time (2008).  I went with the highest voltage (As far away from our Vbat of 3V) that I could get to maximize the inter-plate dielectric spacing.  The temperature performance was measured by using a FET probe looking at the voltage drop with a 1M series resistor from a 3V source with periodic sampling of production parts and sampling of fielded tags over the years.  The way we measured the battery life remaining was to cut them open and measure the thickness of the lithium metal.

The main take away?  Not all capacitors are created equal so trust but verify!

Failure of the Week

Steven Stewart asked Alexa a question:

And this is from Chris Gates:

Have you submitted a Failure of the Week? I'm getting a ton of these and yours was added to the queue.

This Week's Cool Product

Microsoft is placing the ThreadX RTOS and all the middleware into open source under the Eclipse Foundation stewardship.  Here is the Microsoft announcement:


An group named RTOSX has been formed dedicated to support current ThreadX customers as well as those that will take the open source version in the future. Here is our PR on the subsidiary:


You can get find some more details here:   rtosx.com

Note: This section is about something I personally find cool, interesting or important and want to pass along to readers. It is not influenced by vendors.


Let me know if you’re hiring embedded engineers. No recruiters please, and I reserve the right to edit ads to fit the format and intent of this newsletter. Please keep it to 100 words. There is no charge for a job ad.


Joke For The Week

These jokes are archived here.

Contrary to popular belief, you don't become a geek because you're smarter than everyone else. You become a geek because your social skills are retarded. While you're off administering a Linux system, the rest of us are necking. So the tech support folk can be as snide as they want. The minute the clock strikes 5, we win.

About The Embedded Muse

The Embedded Muse is Jack Ganssle's newsletter. Send complaints, comments, and contributions to me at jack@ganssle.com.

The Embedded Muse is supported by The Ganssle Group, whose mission is to help embedded folks get better products to market faster.