• Advertisement
Sign in to follow this  

MCU - Threads changing global state

This topic is 1428 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm programming a micro controller using C. There is a case when the voltage levels of the circuit become unstable and sink below a predefined threshold (for example when the device is unplugged). When this happens, an external interrupt is triggered to inform the micro controller about it, upon which all I/O modules need to immediately shut down.

 

I'd also like to have a function for polling if a power failure occurred.

 

What is the best way of doing this? Up until now I've always used a global variable to keep track of states, like in the following code:

// NOTE: bools are not supported
static volatile char power_failure = 1;

/*-------------------------------------------------------*/
void enable_sub_circuits( void )
{    /* configures modules and other things like that */
    if( successful )
        power_failure = 0;
}

/*-------------------------------------------------------*/
void disable_sub_circuits( void )
{
    power_failure = 1;
    /* shuts down all modules */
}

/*-------------------------------------------------------*/
char is_power_failure( void )
{
    return power_failure;
}

/*-------------------------------------------------------*/
void _ISR _INT0Interrupt( void )
{
    disable_sub_circuits();
}

_INT0Interrupt is triggered when the power failure occurs, and can be considered to be on a separate "thread", for those who aren't sure what an interrupt is.

 

Is this an acceptable way of doing this? The reason why I ask is, I've never really worked with threads before in my life, and since I've been learning about them recently, I've started to question my methods when handling interrupts on micro controllers.

Share this post


Link to post
Share on other sites
Advertisement

Interrupts and threading have a ... complex relationship, even on the most widely popular CPUs. On a microcontroller all bets are off, because the way the interrupt mechanism is implemented in silicon might have different semantics than you expect from, say, a thread running on an x86-compatible CPU. You also have to keep in mind that you have no OS between you to manage scheduling and transitions between execution contexts cleanly.

 

Your idea might work, depending on how the chip is built; but you have one critical flaw: if you're low on voltage, you can't guarantee that the MCU is even going to be able to tick over, let alone power anything beyond the watchdog interrupt. So you can write all kinds of code to poll on that variable and it has no promise that it will ever even get to run.

Share this post


Link to post
Share on other sites
Like Apoch said rather well you do have a major issue. In the mcu world you are interfacing with the transistors directly not a OS. If you hit power failure your code will not trigger. One of to things happens on power failure. If at really low power as in partial failure the chip is going to brownout. At total failure the chip is going to turn completely off so there is no longer a clock at all. In the case of brownout you need to trigger a interrupt to wake it up but if you are still in partial failure it will just brownout again. In the case of total failure once power is restored the chip is reset. In either case you will not be able to execute any instructions because you have no clock or a clock which only has enough omph to recognize the wake me up interrupt. There really is no way to oh shit save state unless it happen before the clock goes away.

You also have to note a interrupt is not a thread in any way shape or form. It is a full diversion. A micro can not multitask as it is a single core that processes liniarly. When a interrupt happens everything stops on the chip till it is processed. Minus the clock. So if in a interrupt and another interrupt happens you will miss the second one entirely it is not qeued up to happen next just skipped. Edited by blewisjr

Share this post


Link to post
Share on other sites

The voltage source being monitored is a 12V source, and triggers the power failure when it goes below 11.2V. The micro controller is powered by 3.3V from a step-down converter, which gets its power from the 12V source.

 

I have a guaranteed ~50ms before the 12V source is low enough for the 3.3V source to begin failing, which is more than enough time to perform the necessary shutdowns. This has been measured and proven. There's really not much to do in the shutdown routine other than disable all ports and write a few bytes to an internal flash.

 

You also have to note a interrupt is not a thread in any way shape or form. It is a full diversion. A micro can not multitask as it is a single core that processes liniarly. When a interrupt happens everything stops on the chip till it is processed. Minus the clock. So if in a interrupt and another interrupt happens you will miss the second one entirely it is not qeued up to happen next just skipped. 

 

Correct, yes.

 

@all

I can confirm that the code does what it is intended to do, thanks for the input. I take it the code is acceptable?

Share this post


Link to post
Share on other sites
On a single core cpu, you know that there is nothing happening during execution, so you don't have all the pitfalls of multi-threading on a multi-core CPU. You can rely on sequential consistency. Interrupts are not in the language standard, so you're not in violation when you rely on their hardware specific properties like that. You do need volatile, because from the point of view of the rest of the program, your interrupt handler is an external event, but you don't need threading primitives.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement