C bit field structures for microcontroller multitasking

So you’re getting better at programming microcontrollers and now you want to do several things at once? You know better than that, microcontrollers are only capable of processing one thing at a time. But if you’re clever with your coding you can achieve something that behaves as if several things are going on at once. The most common way to do this is to set a flag using an interrupt, then use the main loop to check for that flag. [S1axter] posted a tutorial on this topic where he uses bit field structures to help simplify time sensitive events.

We think [S1axter] did a fantastic job of explaining this moderately difficult topic clearly and quickly. In the video after the break he begins by explaining what a bit field is and how it is defined. Basically you’re using a C structure to track a flag using just one bit of storage. This way the flag is either set or not. We suggest you pay careful attention to how he declares the structures as volatile, so you don’t have unexpected behavior when you try it yourself.

Comments

  1. redneckJoe says:

    Booooo, me cannot see!!
    It says private video!!

  2. Brad says:

    Yup. Private.

  3. s1axter says:

    Fixed

  4. Daid says:

    Volatile, it can be useful. But with warnings: http://lwn.net/Articles/233482/

    For larger systems volatile fails to account for a lot of situations. For microcontrollers it works most of the times. Still, your compiler is allowed to re-order instructions without changing the functionality of that function. (this can be a real problem if it happens to you!)

    • WIll says:

      I’m very curious to know more about the warnings because the link itself didn’t provide enough background/context for me to understand what it was referring to.

      I use volatile a LOT with microcontrollers because I do not know of any other way to keep the compilers from optimizing out reads of a variable that is shared between main code and an interrupt.

      As an example:

      volatile uint8_t flag;

      void isr()
      {
      flag = 1;
      }

      void main()
      {
      flag = 0;
      while (!flag);
      //more code ...
      }

      With most of my compilers, the while loop would never terminate if I didn’t include the volatile keyword as the optimizer would skip re-reading the flag variable and assume its value hadn’t changed. I understand that volatile and atomic are two VERY different things and that data consistency is not guaranteed on successive reads of a volatile variable (which is kind of the point…) but I don’t understand what that has to do with the stuff Linus was upset about.

      Forgive my ignorance, I’m mostly self-taught but I am trying to improve my understanding.

      • Yes, link did go over my head also. But read this: http://www.mjmwired.net/kernel/Documentation/memory-barriers.txt and Linus starts to make some sense.

      • JA12 says:

        @Will

        http://lwn.net/Articles/233479/

        “C programmers have often taken volatile to mean that the variable could be changed outside of the current thread of execution; as a result, they are sometimes tempted to use it in kernel code when shared data structures are being used.”

        One possible reason for that could be that in interpreted languages like Java and C#, volatile is different in that it’s atomic and thread safe (and should be called something else).
        In C/C++: defaults as a bug.

        There’s also good note in the comments:
        “One other use for volatile is when communicating with interrupt/NMI handlers running on the same CPU. In this case, all the accesses are on the same CPU, so CPU reordering is irrelevant — CPUs see their own accesses in order. The only requirement is that the compiler avoid optimizations that re-order the code.”

      • Daid says:

        Sorry, I forgot to link the memory barriers doc. Which is quite important in this case.

        Volatile does 1 thing, it instructs the compiler to do every read/write from memory instead of keeping values in registers. However, it does not force the compiler to keep the code where you want it.

        For example, if you fill some kind of data structure in a function, and then set the “data ready” flag, the data ready flag write might be moved above the filling of the data (because it could optimize better). I’ve actually had this happen to me once with -O3 in gcc.

        There are also problems with cache with multi-cpu systems. But that’s outside the scope of microcontrollers.

  5. Tintin says:

    Bitfields are great to make your source code even more readable. But as far as I remember I don’t use them especially with small 8-bits microcontrollers like the tiny13 as it seems like gcc uses lots of ressources even with the best optimization options. I might have missed something at that time but I remember seeing my source code increasing like if gcc was allocating one byte for each 1 or 2 bits bitfields I was using. Anyone’s seen something similar?

  6. Dan says:

    Gotta be careful with setting bits from any code that can be interrupted.

    If your instruction set supports 1-bit atomic writes, use them! Make sure your compiler is optimizing in that direction.

    If you can’t, and you are interrupted in the middle of writing to that register, you can corrupt it easily.

  7. asdf says:

    The numer one tip for C bitfields is “don’t use them”. Their implementation is completely up to the compiler, and without examining the generated code you have no idea what you’re getting. Manually shifting and masking will almost always produce better code.

    Never ever use bitfields to access hardware registers.

    • drew says:

      Why never use bitfields if the compiler supports them in the manner that you desire? The C30 compiler for Microchip 16bit micros expand bitfield structures down to 2 asm instructions, (dereference then set/clear).

      An argument about portability is valid for x86/ARM based systems however when designing software for dedicated hardware why not leverage the compiler to easy the development?

      Desktop/application models don’t necessarily translate verbatim into the micro world.

      • Dan says:

        Indeed. All the Microchip stuff uses bitfields pretty extensively, particularly with hardware registers.

      • Charles P. Lamb says:

        If that is a supported feature of the compiler that is no problem. But if that is just the way the compiler happens to handle them it could change with any compiler release.

      • Steve says:

        Why never use bitfields to access hardware? First you have to really know the rules to know when to break them :-) Also, for it to be a “rule” to _never_ use them, keep in mind that “all absolute statements are never always correct”. When ever I see the words always, never, etc, I wonder what “except for” was left out.
        – Steve

  8. Mike says:

    Yeah, bit-fields = bad for embedded programming. I recommend everyone read this:

    http://faq.programmerworld.net/programming/Best-Questions-for-Embedded-Programmers.htm

    #10 especially (since it relates to this topic)

  9. psmay says:

    I’d point out that bitfields aren’t essential to this methodology; they just save a little space versus using a whole byte for a boolean. It would be trivial to rewrite the example using bool (or _Bool or the platform equivalent). It would be crucial to use volatile in any case and, as mentioned above, to know how your compiler treats volatile for the data type you choose.

    The methodology demonstrated is conceptually similar to setTimeout() in JavaScript. I think a library for cooperative multitasking and/or coroutines would be pretty valuable, but perhaps a lot more intense than many will get with microcontrollers.

  10. Mike says:

    For those on 8-bit AVR, there are some bit-addressable registers which are pretty much made for this sort of thing e.g. GPIOR0.

    With a little care, you don’t need to muck around trying to make the writes atomic by disabling interrupts or such so you can get a really compact fast event system going.

  11. Steve-O-Rama says:

    Is it my PC, or is the narration very faint and noisy? :/ The introduction music was plenty loud, and then it just trails off into whisper-land.

  12. jc says:

    Woooow you can use structures in C – what a HUGE freaking suprise. This is getting increasingly ridiculous.

    • Nova says:

      It’s more a guide to using easy to use variables in space constricted systems that often require you to work out one bit value frequently. less so for pc code and by the comments more problematic there.

  13. xorpunk says:

    single core x86 processors are also only capable at one thing at a time..that’s why OS kernels implement time shares..

    I’m with the others on the humor behind this being treated as news..

  14. I use these two techniques to achieve doing multiple things.

    Simple task manager:

    http://www.mculabs.com/snippets/ptask.html

    And time slicing:

    http://www.mculabs.com/snippets/slice.html

  15. Drone says:

    The small AVR’s have a GPIO register for this.

  16. torwag says:

    wonder that the Parallax Propeller guys did not make a statement about the article introduction

    “You know better than that, microcontrollers are only capable of processing one thing at a time”

    Well they could do 8 things at a time without much headache :)

    • WIll says:

      Well if you really want to nitpick, even a humble MCU does a lot more than one thing at a time… Oh, you meant more than one of YOUR things at a time! :p

      Seriously though, just because the ALU has only one path through doesn’t mean that the hardware state machines controlling ADCs, UARTs, I2C, CAN, SPI, DAC, PWM, interrupt monitors, etc. don’t all run in parallel and to forget that fact can be just as deadly as any of the “volatile” mistakes. It is pure snobbery to think that only running one user defined software thread at a time is all that matters. Let’s give the hardware guys some credit. :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 93,791 other followers