embedded software boot camp

Using volatile to achieve persistence!

Sunday, January 11th, 2009 by Nigel Jones

Once in a while the real world and the arcane world of language standards collide, resulting in surprising results. To see what I mean, read on …

Many of the products I design incorporate a Bootstrap Loader, so that the application firmware may be updated in the field. In most cases, the bootstrap loader is a completely different program to the main application. Despite this, I find it useful for the main application to pass information to the bootstrap loader and vice versa. Thus the question arises, how best to do this? Well in the processor family I am using, although it is technically possible to store information in Flash, EEPROM or RAM, by far the easiest and most secure way of doing it is to place the information into EEPROM. Furthermore, in order to enter the bootstrap loader it is highly desirable to force a reset of the processor by allowing the watchdog timer to time out.

Thus, the code to enter the bootstrap loader looks something like this:

__eeprom uint8_t msg_for_bootloader;

...

msg_for_bootloader = 0x42;

...

for(;;)
{
 /* Wait for watchdog to generate a reset and force entry in to the bootstrap loader */
}

Well, on the face of it, there is not much wrong with this code. However, if one turns on the optimizer, then the compiler examines the code, decides that no code may be executed beyond the infinite loop and thus concludes that the write to msg_for_bootloader is pointless, and promptly optimizes it away. (For a discussion on this topic, see my posting here)

Now you will note that msg_for_bootloader was qualified with __eeprom. This is a compiler extension that allows one to inform the compiler that the variable msg_for_bootloader resides in a special memory space and to be treated accordingly. Now I know that the compiler knows enough about the EEPROM space to generate the correct coding sequences such that reads and writes are performed correctly. However, in my naivete, I also assumed that the compiler knew something about the properties of EEPROM, such that it would realize writing to EEPROM without ostensibly reading it again is intrinsically useful in many applications.

Well it does not. Furthermore, on balance I think the compiler writer’s got it right and the error was completely mine.

So what to do? Well, declaring msg_for_bootloader as volatile fixes the problem. Thus my code now looks like this:

__eeprom volatile uint8_t msg_for_bootloader;

...

msg_for_bootloader = 0x42;

...

for(;;)
{
 /* Wait for watchdog to generate a reset and force entry in to the bootstrap loader */
}

Thus I ended up in the rather bizarre situation of having to declare a variable as volatile in order to make it persistent!

Although I can appreciate the wry irony of this situation, I think it points to a larger problem. The fact is that we are all (ok, most of us) programming in a language (C) that was not designed for use in embedded systems. Indeed, when C was written, I’m not sure EEPROM even existed. As a result, the compiler vendors have added extensions to the C standard in an effort to overcome its shortcomings for embedded systems, while still desperately striving to achieve “full compliance with the standard”. Despite this, I find myself all too frequently falling into traps such as this one. What we really need is a language explicitly designed for embedded systems. It isn’t going to happen, but it doesn’t stop me wishing for it.

Home

Tags:

6 Responses to “Using volatile to achieve persistence!”

  1. Engineer says:

    Are you suggesting that even if we turn off optimization, we still need the volatile qualifier ? If so what other cases would demand that ?Fahmi MEGDICHE

  2. Nigel Jones says:

    Turning off the optimizer in order to achieve some end is usually a very bad idea. Indeed I can think of only one case where I've found this to be necessary (when one is generating the code access sequence necessary to disable watchdogs or perform similar guarded operations).Anyway, to answer your question. Would turning off the optimizer solve this problem – probably. However as soon as you added or subtracted code, or updated your compiler you'd run the risk of the code no longer working.As to what other cases would require this. That's an interesting question to which I don't have the answer. I guess this is part of what makes embedded systems challenging!

  3. Fahmi MEGDICHE says:

    "However as soon as you added or subtracted code, or updated your compiler you'd run the risk of the code no longer working."What does this infer ?

  4. Nigel Jones says:

    Well compiler code generators are funny animals. In my experience you can sometimes make a fairly simply change to code – and have the compiler generate a substantially different set of op codes. Thus if you have something that currently works by relying upon the code generator working a certain way, then you have a maintenance nightmare. Far better to make your requirements explicitly known (by in this case using volatile) rather than relying upon turning off the optimizer and hoping that it works.

  5. Fahmi MEGDICHE says:

    I got the point, and to endorse it, gcc for Coldfire is generating two different code for the below listings:======== Listing 1 ========ptr_sram = &SRAM_ADDRESS_BASE[TAB_MIFARE_CRYPTED_OFFSET];for (i = 0; i < MAX_SECT_MIFARE/10; i++){ ptr_sram += (i * CRYPTED_DATA_LENGTH);} ======== Listing 2 ========for (i = 0; i < MAX_SECT_MIFARE/10; i++){ ptr_sram = &SRAM_ADDRESS_BASE[TAB_MIFARE_CRYPTED_OFFSET + (i * CRYPTED_DATA_LENGTH)];}Listing 2 works while Listing 1 is a disaster (w/ and w/o optimization). So I take the opportunity and recall you about whether gcc is a decent compiler

  6. Ashleigh says:

    Perhaps what all this means is that “volatile” is really the wrong name for the keyword.

    It should perhaps be called “do_exactly_like_code_shows_it_done_and_dont_get_clever” but you can imagine that’s a little long to type. [And even then its not really a good description of how volatile should work.]

Leave a Reply

You must be logged in to post a comment.