We Have Met the Enemy and He Is PowerPoint

This the headline to the central story in today’s New York Times. The story is about the overuse of PowerPoint by the US military, especially in Afghanistan. It centers around a particular PowerPoint slide (shown below) attempting to portray the complexity of US strategy in the region.

The article discusses that a Brig. Gen. H. R. McMaster banned PowerPoint presentations when he led the successful effort to secure the northern Iraq city of Tal Afar.

Leading on from this,  you may be aware, that next weeks UK event the Embedded Masterclass has also banned PowerPoint from its technical presentations. To quote from the website:

This year we have asked the presenters of the 40 min Technical Presentations to ‘abandon Power Point’ . Instead they will have a white board, a flip chart and hand-outs and of course – their wit and charm ! We want to bring a bit of life back into these kinds of events and raise the standards. We are hoping this will lead to a better and more inter-active presentation. It is already causing the presenters to think more carefully about what they intend to present and how it will be structured.

I understand the sentiment, but I’m sorry but No; PowerPoint is just a tool. Banning (or abandoning) PowerPoint is not addressing the root problem.

For anyone who wants to do a professional job of presenting then there are great reference materials out there (e.g. Presentation Zen, silde:ology, beyond bullet points, etc.).

In reality many poor presentations are due to a lack of a proper review process prior to the event(admittedly some people just can’t present). All presentations should be backed up by a hand-out technical paper and not just a print-out of the slides (eliminating the need for lots of technical detail on a slides). Finally, being someone who has to regularly present  5 days of detailed technical training on embedded systems, white boards and flip charts just aren’t big enough for a large audience (unless you can write REALLY BIG).

To combat this problem of free form notes to a large audience, at Feabhas we have been using a really cool tool called PaperShow to augment the slides. Ideally we’d use two projectors, but this isn’t typically practical. Alternatively you could go back to the “good old days” on OHPs, foils and pens.

As I’ll be at the Cambridge event (as we’re running an Embedded Linux training class) I’m really interested in how it actually works and my concerns will hopefully be proven wrong. Hopefully see you there…

Posted in General, training | 3 Comments

Embedded Systems Conference – Silicon Valley

As I’m sure you’re well aware, the ash cloud from the Eyjafjallajokull volcano (which began erupting in mid-March) pretty much brought much of European airspace to a standstill over last weekend and into this week. Now that UK airspace has been reopened, it appears I can resume plans for my visit to the Embedded Systems Conference in San Jose next week.

The sessions I’m directly involved with are:

Examining ARM’s Cortex Microcontroller Software Interface Standard – CMSIS
Date/Time: Tuesday (April 27, 2010)   3:15pm — 4:15pm
In this session I shall be examining ARM’s Cortex Microcontroller Software Interface Standard (CMSIS –  typically pronounced C-M-Sis) . CMSIS aims to provide a framework of reusable components for software developers, silicon and compiler vendors to utilize. Aspects such a power-up boot management and interrupt control have been abstracted and defined by ARM for their Cortex-M family of microcontroller cores. I’ll spend time explaining the CMSIS framework, examining the code from a compiler and chip perspective, and finish off by discussing the pros and cons I see in such an approach.

Understanding Mutual Exclusion: The Semaphores vs. the Mutex
Date/Time: Wednesday (April 28, 2010)   12:00pm — 12:50pm
Location (room): ESC Theater 2
This presentation is based around much of the material in some of my previous postings (see RTOS related blog postings ). One of the things I like about ESC events is that some of the sessions are free. So if you happen to be attending just the exhibition, then you can still attend this session.

The State of Embedded
Date/Time: Wednesday (April 28, 2010)   4:00pm — 4:50pm
Location (room): ESC Theater 1
Finally, I have been invited to participate in an informal session along with Jack Ganssle and Dan Saks (moderated by Rich Nass of Embedded.com and EE Times) to discuss some of the latest trends in embedded systems. We did a similar session at ESC UK back October 2009, which was very well received. It shall be interested to see how being the token European with a US audience differs from the UK event. This is also a free session.

If you’re at the event look me up and say hello.

Posted in General, training | Tagged , , , , , | Leave a comment

Why is technical training so hard to get funding for?

Over many years of delivering technical training to the embedded systems sector, two questions have always bothered me:

  • Why, when the economy gets difficult, are training budgets one of the first things to get cut?
  • Why do delegates, who have waited months (sometimes years) to attend training, get pulled off mid-course?

Even though a myriad of articles tell us why businesses should invest in training during an economical downturn (Why Invest in Training During an Economical Downturn?) funding for training is very hard to come by. So why does this happen?

In reality there are only two types of training:

  • Must-do
  • Everything-else

Continue reading

Posted in General, training | Tagged , , | Leave a comment

Close but no cigar…

After not too much of a learning curve we’ve migrated the website to support wordpress and the associated tools (SQL, PHP, etc.). After checking everything was fine and giving the go ahead for the “go live” for some reason it’s lost the links to all the diagrams from the posts! So I’ll be retrofitting the diagrams over the next week.

First impressions, WordPress is a wonderful leap forward from blogger.

Next post: reflections from embedded world 2010.

Posted in General | Leave a comment

The Psychology of Everyday Things

On my recent trip to e mbedded world in Nuremberg, the lift (elevator) system in the hotel only had a single button to call the lift car.

This caused various problems as there was no ability to select direction of travel. My room wasn’t on the top floor, so when the doors opened I had no idea whether I was going to take a trip to a higher floor even though I wanted to go down to breakfast. To make matters worse the indication panel above the door didn’t reflect the subsequent direction of travel only the current direction.

So for example I was on the 4th floor and the lift, coming from the ground level, would arrive and be announced with an arrow pointing upwards. You would get in not knowing whether or not the lift was actually terminating at your floor or stopping just to continue upwards.

This annoyed me as it was just poor design. At times like this I’m always taken back to a book recommended to me by my father, called “The Psychology of Everyday Things” by Donald Norman.
Even though it is quite dated now it is still a good read (e.g. it explains why poor designcauses us to try and pull doors that need pushing).
I noticed the book has subsequently been renamed to “The Design of Everyday Things“.
Now I’ve of got that off my chest I can get back to understanding wordpress!
Posted in Design Issues | Tagged , , , | 3 Comments

Blogger.com to discontinue support for FTP

Unfortunately Google (via blogger.com) have announced that as of the 26th March 2010 they will discontinue support for FTP uploads from blogger accounts. Current the Feabhas blog is created and managed from blogger but uploaded to our Feabhas server. So having really just got my head around blogging it’s got to be all change. We have a number of posts to publish (including my trip report to embedded world 2010), but I plan to hold off until we have resolved the best route forward (ideally wordpress) . I’m hoping it has no impact on the atom feed, but only time will tell. Watch this space…

Posted in General | 3 Comments

Artisan – Aonix merger

Late last month the merger of Artisan and Aonix was announced. This is yet another interesting move in the supply of tools to the embedded systems community.

The tool market has seen a number of significant changes over the last year. It started just over a year ago with the acquisition of Telelogic by IBM.  At that time Telelogic were starting to become the dominant player in the embedded design tool market (predominately UML), based primarily around their Rhapsody tool (which of course came in to their stable from their acquisition of I-Logix back in 2006).  A lot of people, me included, were concerned that Telelogic would be swallowed up into IBM and loose their focus and support for the embedded community.

Much of this concern was based on IBM’s previous acquisition of Rational back in 2003.  At that time Rational were certainly a player in the embedded UML market, but slowly fewer and fewer resources were given over, and no real investment to tools such as Rational Rose Real-Time. Sure enough, within a year the Telelogic name has disappeared to be replaced by IBM Rational. As an embedded developer you would be hard pressed to find what support IBM offer unless you know what to look for (try, for example, typing “embedded” into the IBM search box, you won’t find much of use to the embedded developer).

This has meant that a void has been developing for anyone looking to use UML in real-time embedded projects. Obviously there are a number of generic tools around, such as Enterprise Architect from Sparx Systems and MaigicDraw from Magic Draw, but neither is focused on to real-time embedded projects.

The merger of Artisan and Aonix makes a lot of sense to both companies. First, for Artisan it gives them a much better presence in the US and thus better positioned to exploit the void left by Telelogic. Also Aonix’s strength has historically been around safety-related software systems, which aligns with where Artisan has been having success.  The merger may also help Artisan address some of the areas they have been perceived as weak in compared to Telelogic, most notability code generation and simulation. Finally, if the code generation is addressed, then it may prove a good platform for gaining acceptance of Aonix’s really interesting, but still relatively niche, Java PERC offering.

So expect to see the name Atego much more in 2010.
Posted in Industry Analysis | Tagged , , , , | 2 Comments

Declarations and Definitions in C

 

Please Note: This post is focusing on pre-C99. The reason being is that it is aimed at the embedded C programmer who tends to be working with pre-C99 based cross-compilers. Also I have split it into two as it became my larger, due to feedback, than first anticipated.

On the surface declarations and definitions in C are pretty straight-forward; but once we start introducing the concepts of scope, storage-duration, linkage and namespace life is not so simple.

 

Program Objects (Variables)

Let’s start with a general rule for variables:
  1. if the statement has an “=” it’s a definition?
  2. otherwise, if it has “extern” and no “=” it’s a declaration?
  3. otherwise it’s a tentative-definition that may become a declaration or a actual-definition

Object Definitions

 

Simply put, a definition allocates storage (memory) e.g.
int ev = 20; /* definition – reserves enough memory to hold an int */
Let’s assume from here-on that an int occupies 32-bits.

 

Object Declaration

 

A declaration gives meaning to an identifier; that is, it defines the type information of the identifier. This allows the compiler to generate correct object code to access the variable based its size (i.e. the number of bytes to read or write).

 

Usage

 

When compiling a source file, a variable must be declared before it is used or it will result in a compiler error.

int main(void)
{
   ev = 10; /* fails to compile as ev has not been declared */
   return 0;
}
int ev = 20; /* definition – allocates 32-bits */
Importantly, an object declaration does not reserve memory. e.g.
extern int ev; /* declaration – no memory reserved but defines sizeof(ev) */
int main(void)
{
   ev = 10; /* okay to use ev as declared, knows to read (say) 32-bits; k = 20 */
   return 0;
}
 int ev = 20; /* definition – memory reserved here and initialised */
Key point 1:
If no declaration is encountered before the definition, then the definition acts as an implicit declaration.
int ev = 20; /* definition and implicit-declaration: reserves memory */
int main(void) 
{
   ev = 10; /* okay to use ev as declared (implicitly) */ 
   return 0; 
}
Key point 2:
In a compiled source file there may be only one definition for an identifier, but there may be multiple declarations (as long as they agree).
extern int ev; /* 1st declaration */
extern int ev; /* 2nd declaration */

 

int main(void) { ev = 10; /* okay to use ev as declared */ return 0; } int ev = 20; /* definition */
In the examples so far, all definitions have included an initialisation and all declarations have used the “extern” keyword. But there is one further concept we need to examine and that is the concept of a tentative definition (this only applies to variables defined outside of functions – more on that later). Take, for example, the following program snippet:

int ev = 20; /* actual definition    */
int td;      /* tentative definition */
int main(void) { ... return 0; }
With a tentative definition, the following rule applies:

If an actual definition is found later in the source file, then the tentative definition just acts as a declaration. If the end of the source file is reached and no actual definition is found, then the tentative definition acts as an actual definition (and implicit declaration) with an initialisation of 0 (zero).

int ev; /* tentative definition becomes declaration */
int td; /* tentative definition become actual definition initialised to 0 */
int main(void)
{
   ...
   return 0;
}

int ev = 20; /* actual definition */
I’d like to address two more syntactical items before we move on. First, It is perfectly legal to write:
 extern int ev = 20; /* actual-definition */
  

I’m sure someone can (and will) tell me why this is useful, but in my 25 years of doing C I’ve never had need to use it. I my view anyone found doing this should be made to sit in the corner wearing a hat with a big ‘D’ on it!Feabhas - Declarations and Definitions in C

Second, it is highly unusual (so unusual that I’ve never seen it used), but the following is also legal syntax:
 extern int(ev);
 int(ev);
 int(ev) = 20;
Before we start looking at such items as scope and linkage let’s address function declarations and definitions.

Functions

Function declarations and definitions are in many ways simpler than variables. A function definition includes the function’s body. e.g.

void f(int p) /* definition and implicit-declaration */
{
   ...
}

int main(void)
{
   f(10); /* okay to call f as declared */
   return 0;
}

A function’s declaration (typically called its prototype) makes the compiler aware there is a valid function with this identifier. e.g.

void f(int p); /* declaration */

int main(void)
{
   f(10); /* okay to call f as declared */
   return 0;
}

void f(int p) /* definition */
{
   // ...
}
On the call to the function “f” in main, the declaration enables the compiler to construct the correct call frame based on three things:
  1. the validity of the identifier
  2. the storage required to pass any parameters (by stack or register)
  3. the storage required for any return information
At the call, the names of function parameters, if any, are irrelevant (to the compiler), so can be omitted from the declaration, e.g. void f(int); /* declaration */
Also it is not illegal to have parameter names that differ from the declaration and the definition (but obviously very bad practice).

Before we move on, there are two problem areas we need to cover. First, let’s look at the following snippet:

int main()
{
   f(20); /* call f with no declaration */
   return 0;
}

void f(int i) /* definition and implicit-declaration */
{
   // ...
}

Here we are trying to call a function that hasn’t been declared. As probably expected, this code fails to compile, but not for the reason you probably assume. Earlier I stated that an identifier must be declared before being used otherwise you get a compiler error. Unfortunately this only applies to variables and not functions!

With functions, if no declaration is found before its first call, the compiler creates an implicit declaration. As it cannot determine the return type, then it assumes an int return type. So for the call
f(20);
the complier assumes a declaration of
int f();
The compiler error will actually occur at the definition of function “f” due to the implicit-declaration and definition not agreeing (as the definition is void f()). The parts being compared are officially called the function designator. As the two designators don’t match the compiler will generate an error of the form:

error: ‘f’ : redefinition; different basic types

If we change f’s return type to int, then this code will compile quite happily.

int main(void)
{
   f(20); /* call f implicit-designator of int f() */
   return 0;
}

int f(int i) /* definition’s designator matches implicit-designator */
{
   // ...
}
Why int as the return type? This is historical baggage. In the original specification of C by Kernighan & Ritche it states, regarding function return types:
If the return type is omitted, int is assumed.

This baggage is still evident today, as the following code should compile successfully:


int main()
{
   f(20); /* call f implicit-designator of int f() */
   return 0;
}

f(int i) /* definition’s designator has implicit return type of int */
{
   // ...
}
Horrible? Yes (and it’s going to get worse) but all it not lost – any modern compiler worth its salt will issue a warning similar to:

warning: 'f' undefined; assuming extern returning int

Never ignore this warning. Some compilers (such as IAR) allow a non-standard extension requiring function prototypes. Note that C++ also requires prototypes, thus closing this loophole.

Can it get worse? Oh yes, much worse.

There is a very common mistake that C programmers assume that an empty parameter list means the same as void in the parameter list. Unfortunately, in some cases it does and in others it doesn’t.

With a function definition, then empty parameter list is the same as void.

void f()       /* definition and implicit-decln of void f(void) */
{
   // ...
}

int main()
{
   f(20);       /* error as call doesn’t match decln */
   return 0;
}
However (and here it comes) for declarations this isn’t the case.
void f();      /* declaration */
void f(void);  /* prototype-declaration – not the same as above */
If a declaration has a parameter list (including void) then it becomes a prototype-declaration. The empty list in a function declarator specifies that no information about the number or types of the parameters is supplied. This has a horrible implication; take for example the following code:

void f(); /* declaration */

 

int main(void)

 

{

 

f(20); /* okay to call f as declared */

 

return 0;

 

}

 

void f(int i) /* definition */

 

{

 

// ...

 

}
This is perfectly legal C code, which will compile and run quite happily. The standard states that the number and types of arguments are not compared with those of the parameters in a function definition that does not include a function prototype (I know, I know, but please don’t shoot the messenger). Simply put, if there is an empty parameter list the compiler assumes that arguments to the call are correct, e.g.

void f(); /* declaration */

 

int main(void)

 

{

 

f(20); /* okay to call f as declared!!! */

 

return 0;

 

}

 

void f(void) /* definition */

 

{

 

// ...

 

}
So what happens above? Well the standard states that if the number of arguments does not agree with the number of parameters, the behaviour is undefined. In many cases with embedded systems, this actually won’t cause a major problem. Many modern microcontroller architectures (e.g. ARM) arguments are passed in registers. Only once the compiler starts using the stack to pass arguments will problems ensue.

Guideline: For all function always supply a function-prototype.

So hopefully that lays the groundwork of declarations and definitions we can now start addressing the concepts of scope, storage-duration, linkage and namespace.

Afternote:


void f()      /* definition and implicit-decln of void f(void) */
{
   // ...
}

int main(void)
{
   f(20);       /* error a call doesn’t match decln */
   return 0;
}
Microsoft compiler bug – this code should fail to compile. Microsoft compiles, whereas both IAR and Keil fail.
Posted in C/C++ Programming | Tagged , , , , | 3 Comments

Unscrambling C Declarations

Note: Based on some feedback I should clarify that this does not cover C99 syntax

Even though the C programming language has been around since the late 1960’s, many programmers still have trouble understanding how C declarations are formed. This is not unsurprising due to the complexity that can arise when mixing pointer, array and function-pointer declarations.

In this posting we shall look at some complex declarations to try and understand them by considering how they are formed. The intent is not so you can go off and write wonderfully complex declarations, but more hopefully you may actually be able to understand someone else’s code. Finally we shall look at how most complex declarations can be easily simplified.
Here I’m going to focus on object declarations/definitions rather than functions. Also, in this posting I’m not going to examine structure, union or enumeration specifies. They’ll keep for another day.
How to read a declaration
Very simple ones (specifically those not involving “[]” or “()“) can be read from right-to-left, e.g.
int x
where ‘x’ is an (identifier for an) integer. However, this approach starts to break down very quickly, e.g.
int a[10]
Therefore a more sophisticated approach is needed for complex declarations because of precedence and associativity rules that apply to the differing symbols in the declaration.

Before building a rule-set there are a number of things we can exclude:
  1. A function cannot return a function – () foo()
  2. A function cannot return an array – [] foo ()
  3. An array cannot hold functions – foo[]()
Let’s start with some simple examples:
int x         x is an integer
This can give us:
Rule 1: Read from left to right looking for an identifier.
So ignore types (int, char, etc.), qualifiers (e.g. const, volatile) and the symbols ‘()’,'[]’ and ‘*’ until you find the first unique identifier. This is the identifier for the declaration.
Building on this, once the identifier is found we look for either array or function notation, e.g.
int a[10]            x is an array of (ten) integers
void x(int y)    x is a function that takes an integer parameter (y) and returns nothing (void)

Rule 2:    look right from the identifier for postfix operators () or []. If [] then it is an array, else if () then it is a function.

Next we introduce pointer notation:
int * x      x is a pointer to an integer

Rule 3:    look left for prefix pointer asterisk ‘*’. If found the identifier is a pointer.

Finally we can introduce type qualifiers (const / volatile), e.g.
const int x     x is an integer constant

Rule 4:    If a const and/or volatile is next to a type specifier (int, long, etc.) it applies to that specifier

So that gives us a preliminary set of 4 rules.
These hold for the following declarations:
int const x      x is a constant integer (This is identical to the previous declaration. This is part of the confusing syntax of the C programming language, but Rule 4 still applies).
const int * x      x is a pointer to a constant integer. Rule 3 followed by Rule 4
int const * x       x is a pointer to a constant integer (as above – still confused?)
int * x[10]          x is an array of pointers to integers ( Rule 2, Rule 3)
int * x(void     x is a function that returns a pointer to an integer (Rule 2, Rule 3)
int **x                 x is a pointer to a pointer to an integer (Rule 3, Rule 3)

So far so good? Pretty straight forward? Maybe not the pointer- to-a-pointer, but we still need to add two further rules. The first affects Rule 4. What if we have a const that is not next to the type? as in:
int * const x
Here we need a new rule, which we’ll call Rule 4b (with our previous Rule 4 becoming 4a):   

Rule 4b: if a const and/or volatile is not next to a type then it applies to the pointer asterisk on its immediate left

int * const x      x is a constant pointer to an integer (this means the pointer address is constant)
Combining 4a and 4b gives us:
int const * const x     x is a constant pointer to a constant integer
We have one final rule required to force precedence. For example we’ve already seen that int * x(void)declares x as a function that returns a pointer to an integer (Rule 2, Rule 3). But what if I wanted to declare a pointer to a function that returns an integer?
The syntax is as follows:
int (*x)(void)    x is a pointer to a function that returns an integer
This gives our final rule, which becomes a new Rule 2 and pushes everything down by one:

Rule 2: If the identifier is within parentheses, then evaluate inside the parentheses first

This rule is required because when we have  *x() then the function parentheses always win. Thus:
void (*x)(int y)     x is a pointer to a function that takes an integer (y) as a parameter and returns void
Rule Summary
  • Rule 1: Read from left to right looking for an identifier
  • Rule 2: If the identifier is within parentheses, then evaluate inside the parentheses first
  • Rule 3:    look right for postfix operators ( ) or [ ]. If [] then it is an array, else if () then it is a function.
  • Rule 4:    look left for prefix pointer asterisk ‘*’. If found the identifier is a pointer.
  • Rule 5a: If a const and/or volatile is next to a type specifier (int, long, etc.) it applies to that specifier
  • Rule 5b: if a const and/or volatile is not next to a type then it applies to the pointer asterisk on its immediate left
Complex Declarations
This core set that should decode C program object declarations. Let’s put it to the test on a couple of horrible declarations. First can you work out:
void (*fpa[10])(int)
Have a go before I break it down…
Okay, let’s decompose this:
Rule 1: From left to right find identifier, this gives us fpa
Rule 2: (*fpa[]) parentheses win, so evaluate inside the parentheses     
Rule 3: fpa[10]  postfix [] wins; fpa is a ten element array ($ now represents fpa[10])
Rule 4:    *$    prefix * wins; fpa is an array of pointers. Now we’ve evaluated inside the parentheses we step outside.
Rule 3: $() postfix, () wins fpa is an array of pointers to functions
Rule 2: void $(int   parentheses; fpa is an array of pointers to functions each taking an integer parameter and returning void
So the identifier fpa represents an array of ten pointers to functions each of which takes an integer as a parameter and returns void. Phew…
Okay one last one to try, go to the C standard library and look at the declarations in <signal.h> and you should see:
 void (*signal(int sig, void(*func)(int)))(int);
If you can decode this then I’m really impressed!

Let’s apply our rule-set to this:
First, as always is rule 1; signal is the identifier. signal is in parentheses, so based on Rule 2 we must evaluate that first. If we match parenthesis then we get:
(*signal(int sig, void(*func)(int)))
Which we can temporarily simplify (by ignoring the function parameters) to:
(*signal())       
Based on Rule 3, then signal is a function that returns a pointer. The question is a pointer to what?  Using the simplification we can work out the return type as:
void (* signal() )(int)
which becomes
void (*$)(int)
which means the function signal returns a pointer to a function that has an integer parameter and returns void.
So let’s return to the parameters, this gives us:
signal(int sig, void(*func)(int))
So signal takes two parameters
int sigsig is an integer
void(*func)(int) –  func is a pointer to a function that has an integer parameter and returns void.
To summarise:
  • signal is a function
  • that returns a pointer to a function that has an integer parameter and returns void
  • and takes two parameters of
  • an integer, and
  • a pointer to a function that has an integer parameter and returns void
It doesn’t get much worse that this (and remember this example comes from the standard library, which is shameful!).
How to avoid complexity in declarations
Avoid by design, as far as possible. If this fails, divide and conquer remembering that typedef is your friend.  A typedef declaration does not introduce a new type, only a synonym for the type specified. For example:
typedef  int  MILES;
MILES  m;   /* m is of type int */
typedef int*  int_ptr;
int_ptr  ip;  /* ip is of type integer pointer int* */
Used well typedef’s makes life easier. For example:
typedef void (*FuncPtr)(int);
FuncPtr is a typedef for a pointer to any function which takes an integer parameter and returns void.
In the “signal” example, both function pointers are of this type, so using the typedef, the declaration
void (*signal(int sig, void(*func)(int)))(int)
becomes
FuncPtr signal(int sig, FuncPtr)
and our previous declaration of:
void (*fpa[10])(int)
becomes
FuncPtr  fpa[10]
After that I need to find a dark room to lie down in.
Decoding Rule-set
Rule 1:  Read from left to right looking for an identifier
Rule 2:  If the identifier is with parentheses, then evaluate inside the parentheses first
Rule 3:   look right for postfix operators ( ) or [ ]. If [] then it is an array, else if () then it is a function.
Rule 4:   look left for prefix pointer asterisk ‘*’. If found the identifier is a pointer.
Rule 5a: If a const and/or volatile is next to a type specifier (int, long, etc.) it applies to that specifier
Rule 5b: if a const and/or volatile is not next to a type then it applies to the pointer asterisk on its immediate left

Also check out https://www.cdecl.org/ (thanks @FrankSansC)

Posted in C/C++ Programming | Tagged , | 6 Comments

Task Synchronisation – Part 2: Multiple Tasks and RTOS APIs

First off, apologies for the delay in this follow up to the previous post Task Synchronisation, it has been a mad couple off weeks with a combination of vacation and work.
In the previous post I looked at the foundation of task synchronization demonstrating there are a range of synchronisation models (bilateral/unilateral, persistent/non-persistent, etc.). In this post I shall look at multi-task synchronisation and then investigate specific RTOS APIs.
MULTIPLE TASKS WAITING
So far we have only dealt with the simple case of two task synchronisation. We now address the case where multiple tasks are waiting at the synchronisation point:

We now have two tasks, Task2 and Task3 blocked waiting on the SO. Task1 now reaches the synchronisation point and signals the event. Again we could have the case of bilateral and unilateral sync, though typically Task1 doesn’t block if no other task is waiting (unilateral model).
The first question is: how many of the waiting tasks synchronise? All the waiting tasks, or only the first one? (And how do we define which task is the first one?).
In many systems we need the ability to broadcast a condition to all waiting tasks (defined as one-to-many or 1:M synchronisation). This is often referred to as a “Barrier”. Barriers many be non-persistent (only those waiting at that time get readied; subsequent tasks block), or persistent (all tasks continue past sync point until the synchronisation is removed with a manual reset).
Alternatively, only one waiting task is allowed past the synchronisation point, the rest remaining blocked. With single task synchronisation there must be a policy regarding which task is synchronised. For a real-time system this is normally based on ordering the waiting queue by task priority. However, as matter of choice, most RTOSs will support queuing based on arrival order (FIFO).
MULTIPLE CONDITION SYNCHRONISATION
In the design of real-time systems it is common for a task to synchronise on a number of different conditions. This many involve a conjunction (AND) or disjunction (OR) of events. For example, a motor fault condition may be specified as:
  • low oil pressure AND > 30sec after start-up
Or a gas system nanoautomate alarm condition as:
  • Isobutane present in outlet line OR
  • Isobutane present in front flush OR
  • Isobutane present in rear flush
RTOS SYNCHRONISATION OBJECTS
Given the array of synchronisation requirements and options how do modern RTOS support synchronisation? The majority of RTOSs support the following:
  • Event Flags / Event Flag Groups
  • Semaphores as Signals

The Semaphore as a Signal is not to be confused with C standard library signals or UNIX signals. A signal is, according to the UNIX terminology, a notification sent to a process that will interrupt that process. In order to catch a signal a process must have a signal handler. This is similar to the behaviour of a software interrupts.

EVENT FLAGS
Typically an Event Flag is implemented as a Manual-reset, Persistent, Unilateral synchronisation object. It is by far the simplest idea and mechanism, and is best suited to one-to-many (1:M) or many-to-one (1:M) synchronisation. An API may consist of the following calls:

  • Set – sets the flag, readying any waiting tasks; can be called from an ISR
  • Clear – clears the flag, if the flag is cleared then any arriving task is blocked
  • Wait – non-consuming pend on a flag
However, event flags are normally bound together to form Event Flag Groups (EFG). Having support for groups of flags allows task the wait either conjunctively or disjunctively . A typical implementation will bind an event flag group to a word in memory (e.g. 32 bits = 32 flags). To support groups, the API is extended to include a further argument, and the wait includes the specification of conjunctive or disjunctive synchronisation.
  • Set(group, bitmask)
  • Clear(group, bitmask)
  • Wait(group, bitmask, AND_OR, timeout)

RTOSs differ in the implementation of Event Flag Groups, with some only supporting M:1 synchronisation and not supporting 1:M or M:M synchronisation. In this case each event flag group is bound to a specific task (i.e. EFGs cannot stand as independent resources), altering the API to:

  • Set(task_id, bitmask)
  • Clear(task_id, bitmask)
  • Wait( bitmask, AND_OR, timeout, &events;)
ISSUES WITH EVENT FLAGS

A surprising number of RTOSs do not support the concept of Event Flags, thus no support for any form of disjunctive or conjunctive synchronisation. The usual argument for not supporting them is that it can be difficult (if not impossible) to make timing deterministic (especially disjunction). Timing typically takes an O(N) form where N is the number of waiting tasks.

In addition, I am not aware of any that support event flag groups being able to do combination logic; e.g. A or B or (C and D).

Some examples of event flag support from commercial RTOSs are:

  • >VxWorks
    • 32 events in an event field
    • Each task has its own events field that can be filled by having tasks and/or ISRs sending events to the task.
  • ThreadX
    • 32 event flags in a group
    • Each event flag group is a public resource
  • Nucleus PLUS
    • 32 event flags in a group
    • Each event flag group is a public resource
  • uC/OS-III
    • 8, 16 or 32 event flags in a group (compile time configured)
    • Each event flag group is a public resource
SEMAPHORE AS SIGNALS
The generic concept of a signal is for synchronisation between two tasks, with a simple API of:
  • signal
  • wait – timeout option
However, the term ‘signal’ is now more commonly used in the context of C and UNIX programming, where it refers to an asynchronous communication mechanism.
Most RTOSs, then, do not support the concept of a signal directly, instead directing the programmer to use the semaphore as a synchronisation object (the Semaphore as a Signal pattern). When using a semaphore as a signal, the SO takes the form of an Auto-reset Persistent Unilateral synchronisation object.
The semaphore was originally designed for support mutual exclusion in multi-tasking systems and pretty much all modern RTOSs support the semaphore.This is thoroughly covered in a previous posting (Mutex vs. Semaphore).
The fact that semaphores do not check the releaser of the semaphore was actually the taker allows the semaphore to be used for unidirectional synchronization. This works by creating the semaphore with a count of zero. When the semaphore count is zero, any task waiting (‘pending’ in our example) will block. When a signal is sent (SemPost), the count is incremented by one. If a task is waiting, it will consume the count token and continue (decrementing the count back to zero). If there is more than one task waiting, then only the first will be signalled – the others remaining blocked (either by priority or FIFO ordering).
Note that the Pend and Post calls are not used as a pair in the same task. In the example, assuming Thread1 calls the OSSemPend function it will block. When Thread2 later calls the OSSemPost function then the unilateral synchronization takes place and both task are ready to run (with the higher priority task actually running).

The Semaphore as a Signal pattern is regularly used to synchronise tasks with ISRs triggered by external events.  This mechanism is favoured since the ISR will never block when posting to the semaphore (thus avoiding the potential to ‘stall’ the system).

An RTOS may support counting semaphores (where the count increments each time it is signalled) and/or binary semaphores (where the count is either zero or one – signalled or unsignalled).  The choice of semaphore can have important implications for the behaviour of the application.

If we have sporadic interrupts, then the ISR may signal the semaphore multiple times before the task waits on it. Does the application need to know only that the event has occurred, or does it need to know the actual number of times an event has occurred? Either is valid, depending on the system requirements. Note that most RTOSs use the counting semaphore as a signal and thus will count the number of events.

Unfortunately using the semaphore as synchronization primitive can be problematic in that it makes debugging harder and increase the potential to miss “accidental release” type problems, as an OSSemPost on its own (i.e. not paired with a OSSemPend) is considered legal code.

As an example, VxWorks does not support signals, but does support both the binary semaphore and the counting semaphore. Either can be used for synchronisation if created EMPTY (0). The following calls can be used by tasks to use the semaphore as a synchronisation object.

  • semGive()
    • Binary – giving a “full” semaphore has no effect
    • Counting – increments count by one
  • semTake()
    • will block if count is zero
  • semFlush()
    • all waiting tasks are unblocked; semaphore left at zero
The semFlush is interesting, in that it allows all waiting tasks past the synchronisation point, thus supporting a 1:M barrier synchronisation.
BILATERAL SYNCHRONIZATION
As already stated, one limitation of bilateral synchronisation (aka the Rendezvous) is that it cannot be used for ISR to task synchronisation . Because of this, bilateral synchronisation is rarely supported by commercial RTOSs. Notable, though, is the ITRON Project, which creates standards for real-time operating systems used in embedded systems (µITRON4.0 Specification). Like the Ada programming language it supports the concept of the Rendezvous for bilateral synchronisation (it actually uses the term Rendezvous Ports).

For those RTOSs that don’t support Bilateral Synchronization, this can be simulated/implemented using a pair of semaphores.

Irrespective of which task reaches the synchronisation point first it will have to wait until the other task to arrives.
MUTUAL EXCLUSION AND SYNCHRONISATION
So far we have considered general synchronisation between two or more tasks. There is one further synchronisation use case we need to examine. Take, for example, the C code for a simple stack shown below. These routines use the variable count to keep track of the stack size. If the stack is empty then pop returns STACK_EMPTY and the caller must check for and take appropriate error handling actions.

Suppose that we do not want to return STACK_EMPTY, but want to wait (synchronise) for the stack to contain data. Since the waiting task owns the mutex no other task will be able to enter the critical region and push an element onto the stack. Thus the waiting task could never be signalled the stack is no longer empty – a deadlock.

A Condition Variable is used in conjunction with mutexes to implement synchronisation for certain conditions to become true (e.g. the stack becoming not empty). A condition variable (also called a condition object), therefore is a unilateral, auto-reset, non-counting, synchronisation object.

SUMMARY
When designing software for embedded systems that is relying on a particular Real-Time Operating System, it is essential to understand that the behaviour of synchronisation primitives differ from RTOS to RTOS. Many questions need answering such as:

  • Does the RTOS support only unilateral synchronisation, or does it include primitives for bilateral synchronisation?
  • If multiple tasks are waiting then how many are readied?
    • If only one, then how is it selected (priority / FIFO)?
  • Is the signal persistent or non-persistent?
  • Is the synchronisation object manual-reset or auto-reset?
  • Does the RTOS support multiple event Conjunction and/or Disjunction?
Finally, where mutual exclusion is required (as in most systems) does the RTOS support the concept of condition objects?

In summary, note that many RTOSs are very weak in terms of supporting different types of synchronisation, most relying on using the counting semaphore as a general synchronisation object.

Posted in RTOS | Tagged , , , , , | 1 Comment