How to shutdown the microcontroller

acehigh1971 wrote on Thursday, August 03, 2006:

Suppose I’m using the OS in an application that sometimes must go in a low power state, switching off the main oscillator.
Can I use the vTaskSuspendAll, or do I have to stop the kernel real time processing, using vTaskEndScheduler?
Note that when the oscillator is off, I wake up only by some external interrupt, and I surely have to perform some OS activities.
Any help is appreciated.

nobody wrote on Friday, August 04, 2006:

You Can use a LowPowerConsumption Mcu to deal with all the things when ManMcu is PowerDown.

jwestmoreland wrote on Friday, August 04, 2006:

Hello Ace,

As the previous poster stated - a low power MCU will definitely help and may even make it somewhat easy.

Since the MSP430 was built with this in mind - I’m going to answer the question assuming you’re using the MSP430:

The MSP430 has multiple low power modes - the most interesting in this case being LPM3 and LPM4 - low power mode 3 and low power mode 4 respectively.

The MSP430 can have 2 external clocks and has an internal DCO.  Note the newer architectures in the works have even more possible combinations - but let’s say we’re using a '1611 with a watch xtal on ACLK and an 8MHZ xtal on MCLK.

In LPM3 - MCLK is off - but ACLK stays on - as well as RAM and the SFR’s (special function registers) - so your RTC functions can still run.
TI states current consumption in this mode averages 0.8 uA.

In LPM4 - everything is off - only RAM and the SFR’s are retained - current consumption averages 0.1 uA.

You can set an external I/O to respond to an interrupt in which you exit LPM.  When the ISR is executed the SR is popped from the stack and bits in the SR can be modified in the ISR to put the processor back into ‘normal run mode’ so to speak.

Putting the processor into LPM and exiting LPM are fairly straightforward with the MSP430.  In LPM3 -
you can even keep your RTC (tick) running.  Since entering and exiting these modes automatically take care of the processor ‘housekeeping’ - I don’t think you’ll have to do anything special
regarding the RTOS.  You may have to be careful how the SR (Status Register) is handled depending on how you enter LPM - I suppose.

John W.

acehigh1971 wrote on Friday, August 04, 2006:

Thanks for the answers.
Unfortunately the only way I have to achieve the current consumption goal is to stop the main and only oscillator, in my microcotroller (Freescale MAC71xx).
The control unit wakes up by means of external interrupts, that make the oscillator start again.

My idea was to stop the OS (by deleting all the tasks, and stopping the scheduler), stopping the RTI tick, activating the proper irqs and then switching off the osc. When happens the wakeup,I started everything from the beginning (for example using this moment to reinitialize the heap).

It makes sense to me to delete the tasks before going to sleep since every wake up is a new era for the task (variables which are to be saved are defined as globals).
But if I delete the tasks, I probably go into the problem of heap fragmentation, isn’t it? (heap_2.c) So I wanted to stop the scheduler to be able to reinitialize the heap, but no microcontroller port has implemented the vTaskEndScheduler() function, so I think that nobody uses this approach.
Do you see something bad with this approach?

I would only need a way to correctly return from vTaskEndScheduler to the next instruction after vTaskStartScheduler…

acehigh1971 wrote on Friday, August 04, 2006:

Oopss: I meant:
I would only need a way to correctly return from vPortEndScheduler to the next istruction after the call to xPortStartScheduler…

nobody wrote on Friday, August 04, 2006:

There is the function vTaskCleanUpResources() in tasks.c.

An alternative faster approach would be to define your own function in tasks.c that firstly disables interrupts, then memset()'s all the static variables at the top of tasks.c to 0 (as if the cstartup code had just run).  Do the same for th heap, then use an oldfashioned goto or lngjmp to the place you want to restart from.

nobody wrote on Friday, August 04, 2006:

Take a look at the PC and Flashlite 186 ports.  These implement the end scheduler function so they can return to DOS.  Is there something you could copy from there?

acehigh1971 wrote on Friday, August 04, 2006:

I looked at the PC port. It uses setjmp and longjmp. It seems ok for me. I’m trying it but I ran in the problem of correctly reinitialize the heap and stack(s).

I still want to find an elegant solution:
My idea is this:

in the main i have:

int main( void )
        unsigned int a;
        vStartInitTask( mainINITTASK_PRIORITY );
        //here i should go to stop and switch off the oscillator, for now it’s ok to loop for some time…
        } /* (*a*) */
        /* Should never reach here! */
    return 0;

Every time I got woken up in (*a*) I start the os and restart the scheduler.

In xPortStartScheduler (exiting from setjmp (when I call vPortEndScheduler) I do a vTaskCleanUpResources and set the processor mode to SVC, but
I found that the heap is not freed correctly.

acehigh1971 wrote on Friday, August 04, 2006:

Just to clarify:
in a task (ie inittask) at a certain moment i delete all other tasks and do a call to  vTaskEndScheduler()…

acehigh1971 wrote on Wednesday, September 06, 2006:


I wanted to ‘start’ and ‘end’ the scheduler a lot of times without going thru reset.

After some looking in the rtos code, it ended up that a lot of variables are declared as static inside the functions.
So they should have been initialized every time i ran thru vTaskStartScheduler.
I would have done some sort of startup code to reset the static variables of interest, that is something beyond the scope of what I needed.

I decided to simply do a vTaskSuspend to block all running tasks, one by one in a certain order, and to simply halt the microcontroller (waking up from external interrupt).

There is only one situation where I want to stop the rtos: firmware update. In this case I can call the vEndScheduler, but after the update (made outside operating sistem) I go out of reset, so all variables are correctly initialized.

Thanks all for you helping