EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Nested interrupts Or Alternatives

Started by Vinod November 28, 2009
Hi all,

I am working on project on metering based on MSP430F249. I am using TimerB for my multiplexed display refreshing and key scanning at 1ms.
I use UART ISR for serial communication. Both these ISRs are short and cause no problem.

But I have some issues with ADC ISR -

I am using ADC12 module for integration of AC energy. The true RMS computation of Power and energy takes couple of tens of milliseconds for computation (MSP MCU at 8MHz). This blocks the display ISR for so long, and I can see jitter in display.

I can not think of putting this process in main loop as the user interaction for view / edit meter setting should not stop this integration.

Meter has functions for frequent user interaction for entry of some user inputs, during this my energy, time integration should not stop - should continue in fore ground.

can some experienced people guide how to go about - nesting interrupts / any other means ?

if I insert a piece of code for polling this process in between user interaction - how do I manage variable of two totally different processes ?
thanks in advance.

Vinod

Beginning Microcontrollers with the MSP430

--- In m..., "Vinod" wrote:
>
> Hi all,
>
> I am working on project on metering based on MSP430F249. I am using TimerB for my multiplexed display refreshing and key scanning at 1ms.
> I use UART ISR for serial communication. Both these ISRs are short and cause no problem.
>
> But I have some issues with ADC ISR -
>
> I am using ADC12 module for integration of AC energy. The true RMS computation of Power and energy takes couple of tens of milliseconds for computation (MSP MCU at 8MHz). This blocks the display ISR for so long, and I can see jitter in display.
>
> I can not think of putting this process in main loop as the user interaction for view / edit meter setting should not stop this integration.
>
> Meter has functions for frequent user interaction for entry of some user inputs, during this my energy, time integration should not stop - should continue in fore ground.
>
> can some experienced people guide how to go about - nesting interrupts / any other means ?
>
> if I insert a piece of code for polling this process in between user interaction - how do I manage variable of two totally different processes ?
> thanks in advance.
>
> Vinod
>

I am an atheist; thus I would use nested interrupt occasionally. (If I have the Original Sin of knowing right from wrong, I do not need to follow any Commandments.)

Giving that I am not using any RTOS and one of the interrupts needs a lot CPU cycles to process at a priority lower than other interrupt services but higher than other background processes, I would consider one level of nesting.

Inside the ISR of that interrupt, I would do the critical part first, then enable interrupts, do the lengthy process, and return from interrupt.

I would constrain myself to do this for only one of the interrupts so that the nesting is one level deep at most. I would make sure that the same interrupt would not interrupt its own ISR.

--- In m..., "Vinod" wrote:
>
> Hi all,
>
> I am working on project on metering based on MSP430F249. I am using TimerB for my multiplexed display refreshing and key scanning at 1ms.
> I use UART ISR for serial communication. Both these ISRs are short and cause no problem.
>
> But I have some issues with ADC ISR -
>
> I am using ADC12 module for integration of AC energy. The true RMS computation of Power and energy takes couple of tens of milliseconds for computation (MSP MCU at 8MHz). This blocks the display ISR for so long, and I can see jitter in display.
>
> I can not think of putting this process in main loop as the user interaction for view / edit meter setting should not stop this integration.
>
> Meter has functions for frequent user interaction for entry of some user inputs, during this my energy, time integration should not stop - should continue in fore ground.
>
> can some experienced people guide how to go about - nesting interrupts / any other means ?
>
> if I insert a piece of code for polling this process in between user interaction - how do I manage variable of two totally different processes ?
> thanks in advance.
>
> Vinod
>


I am also an atheist therefore I do not believe on magic or spell.
Nested interrupts works fine when you know what you are doing (easier
to control when done in assembly), but it doesn't seems to be the case
of the OP.
The solution, Vinod, is to use a state machine in your main loop:
check user inputs while performing the math. Break the math in pieces
to improve the state machine's time resolution.
Even the display and keyboard scan can be done in the main loop. You
could use the timer only to change a flag to say the time has passed,
then check this flag in the state machine and proceed to the scan
routine.
-Augusto
.
On Sáb 28/11/09 17:48 , "old_cow_yellow" o...@yahoo.com
sent:
I am an atheist; thus I would use nested interrupt occasionally. (If
I have the Original Sin of knowing right from wrong, I do not need to
follow any Commandments.)
Giving that I am not using any RTOS and one of the interrupts needs
a lot CPU cycles to process at a priority lower than other interrupt
services but higher than other background processes, I would consider
one level of nesting.
Inside the ISR of that interrupt, I would do the critical part
first, then enable interrupts, do the lengthy process, and return
from interrupt.
I would constrain myself to do this for only one of the interrupts
so that the nesting is one level deep at most. I would make sure that
the same interrupt would not interrupt its own ISR.
--- In m..., "Vinod" ...> wrote:
>
> Hi all,
>
> I am working on project on metering based on MSP430F249. I am
using TimerB for my multiplexed display refreshing and key scanning
at 1ms.
> I use UART ISR for serial communication. Both these ISRs are short
and cause no problem.
>
> But I have some issues with ADC ISR -
>
> I am using ADC12 module for integration of AC energy. The true RMS
computation of Power and energy takes couple of tens of milliseconds
for computation (MSP MCU at 8MHz). This blocks the display ISR for so
long, and I can see jitter in display.
>
> I can not think of putting this process in main loop as the user
interaction for view / edit meter setting should not stop this
integration.
>
> Meter has functions for frequent user interaction for entry of
some user inputs, during this my energy, time integration should not
stop - should continue in fore ground.
>
> can some experienced people guide how to go about - nesting
interrupts / any other means ?
>
> if I insert a piece of code for polling this process in between
user interaction - how do I manage variable of two totally different
processes ?
>
>
> thanks in advance.
>
> Vinod
>



Ideally simply buy a commercial RTOS and let them do the work for you.

I have seen the 'set a flag and process the code in the main program via polling' idea many times. What starts off as a 'good idea' usually ends up as an unstructured mess.

I prefer the DPC (Deferred Procedure Call) or 'fork queue' idea.

Each interrupt simply adds a data packet to a queue, and then triggers a very low priority hardware interrupt via software.

The original hardware interrupt then exits, having done almost zero work.

This leaves the very low priority "hardware" interrupt to run: this code dequeues the packet and processes it to completetion.

This fake hardware interrupt then exists allowing the main program to continue.

Nested interrupts from hardware devcies are not allowed - but the very low priority queue servicing interrupt CAN be interrupted.

The single threaded queue processing interrupt level can be regarded as a very high priority process or task.
----- Original Message -----
From: Augusto Einsfeldt
To: m...
Sent: Sunday, November 29, 2009 11:28 AM
Subject: Re: [msp430] Re: Nested interrupts Or Alternatives


I am also an atheist therefore I do not believe on magic or spell.
Nested interrupts works fine when you know what you are doing (easier
to control when done in assembly), but it doesn't seems to be the case
of the OP.
The solution, Vinod, is to use a state machine in your main loop:
check user inputs while performing the math. Break the math in pieces
to improve the state machine's time resolution.
Even the display and keyboard scan can be done in the main loop. You
could use the timer only to change a flag to say the time has passed,
then check this flag in the state machine and proceed to the scan
routine.
-Augusto
.
On Sáb 28/11/09 17:48 , "old_cow_yellow" o...@yahoo.com
sent:
I am an atheist; thus I would use nested interrupt occasionally. (If
I have the Original Sin of knowing right from wrong, I do not need to
follow any Commandments.)
Giving that I am not using any RTOS and one of the interrupts needs
a lot CPU cycles to process at a priority lower than other interrupt
services but higher than other background processes, I would consider
one level of nesting.
Inside the ISR of that interrupt, I would do the critical part
first, then enable interrupts, do the lengthy process, and return
from interrupt.
I would constrain myself to do this for only one of the interrupts
so that the nesting is one level deep at most. I would make sure that
the same interrupt would not interrupt its own ISR.
--- In m..., "Vinod" ...> wrote:
>
> Hi all,
>
> I am working on project on metering based on MSP430F249. I am
using TimerB for my multiplexed display refreshing and key scanning
at 1ms.
> I use UART ISR for serial communication. Both these ISRs are short
and cause no problem.
>
> But I have some issues with ADC ISR -
>
> I am using ADC12 module for integration of AC energy. The true RMS
computation of Power and energy takes couple of tens of milliseconds
for computation (MSP MCU at 8MHz). This blocks the display ISR for so
long, and I can see jitter in display.
>
> I can not think of putting this process in main loop as the user
interaction for view / edit meter setting should not stop this
integration.
>
> Meter has functions for frequent user interaction for entry of
some user inputs, during this my energy, time integration should not
stop - should continue in fore ground.
>
> can some experienced people guide how to go about - nesting
interrupts / any other means ?
>
> if I insert a piece of code for polling this process in between
user interaction - how do I manage variable of two totally different
processes ?
>
>
> thanks in advance.
>
> Vinod
>






Hi Richard,

I thought about generating a low priority interrupt for long process within ADC ISR. But unless I do nesting, This process will hold up my TimerB ISR doing display refresh and key scanning. So my purpose not served.

regards
Vinod
Hi Augusto,

I am not clear how to go about polling for signal processing within user interface functions. State machine implementation sounds tricky.
The program may be using the PCU registers and doing some computations in user interface functions. During this if I have to signal processing jobs using even HMB how do we push / pop registers and variables ?

Any pointers ?

Regards
Vinod

--- In m..., "Richard \(UK\)" wrote:
>
> Ideally simply buy a commercial RTOS and let them do the work for you.
>
> I have seen the 'set a flag and process the code in the main program via polling' idea many times. What starts off as a 'good idea' usually ends up as an unstructured mess.
>
> I prefer the DPC (Deferred Procedure Call) or 'fork queue' idea.
>
> Each interrupt simply adds a data packet to a queue, and then triggers a very low priority hardware interrupt via software.
>
> The original hardware interrupt then exits, having done almost zero work.
>
> This leaves the very low priority "hardware" interrupt to run: this code dequeues the packet and processes it to completetion.
>
> This fake hardware interrupt then exists allowing the main program to continue.
>
> Nested interrupts from hardware devcies are not allowed - but the very low priority queue servicing interrupt CAN be interrupted.
>
> The single threaded queue processing interrupt level can be regarded as a very high priority process or task.
>
>
> ----- Original Message -----
> From: Augusto Einsfeldt
> To: m...
> Sent: Sunday, November 29, 2009 11:28 AM
> Subject: Re: [msp430] Re: Nested interrupts Or Alternatives
>
>
>
>
> I am also an atheist therefore I do not believe on magic or spell.
> Nested interrupts works fine when you know what you are doing (easier
> to control when done in assembly), but it doesn't seems to be the case
> of the OP.
> The solution, Vinod, is to use a state machine in your main loop:
> check user inputs while performing the math. Break the math in pieces
> to improve the state machine's time resolution.
> Even the display and keyboard scan can be done in the main loop. You
> could use the timer only to change a flag to say the time has passed,
> then check this flag in the state machine and proceed to the scan
> routine.
> -Augusto
> .
> On Sáb 28/11/09 17:48 , "old_cow_yellow" old_cow_yellow@...
> sent:
> I am an atheist; thus I would use nested interrupt occasionally. (If
> I have the Original Sin of knowing right from wrong, I do not need to
> follow any Commandments.)
> Giving that I am not using any RTOS and one of the interrupts needs
> a lot CPU cycles to process at a priority lower than other interrupt
> services but higher than other background processes, I would consider
> one level of nesting.
> Inside the ISR of that interrupt, I would do the critical part
> first, then enable interrupts, do the lengthy process, and return
> from interrupt.
> I would constrain myself to do this for only one of the interrupts
> so that the nesting is one level deep at most. I would make sure that
> the same interrupt would not interrupt its own ISR.
> --- In m..., "Vinod" ...> wrote:
> >
> > Hi all,
> >
> > I am working on project on metering based on MSP430F249. I am
> using TimerB for my multiplexed display refreshing and key scanning
> at 1ms.
> > I use UART ISR for serial communication. Both these ISRs are short
> and cause no problem.
> >
> > But I have some issues with ADC ISR -
> >
> > I am using ADC12 module for integration of AC energy. The true RMS
> computation of Power and energy takes couple of tens of milliseconds
> for computation (MSP MCU at 8MHz). This blocks the display ISR for so
> long, and I can see jitter in display.
> >
> > I can not think of putting this process in main loop as the user
> interaction for view / edit meter setting should not stop this
> integration.
> >
> > Meter has functions for frequent user interaction for entry of
> some user inputs, during this my energy, time integration should not
> stop - should continue in fore ground.
> >
> > can some experienced people guide how to go about - nesting
> interrupts / any other means ?
> >
> > if I insert a piece of code for polling this process in between
> user interaction - how do I manage variable of two totally different
> processes ?
> >
> >
> > thanks in advance.
> >
> > Vinod
> >
>
>
>
>
>
>
>
>
>
>

Hi all,

I tried enabling interrupts and disabling ADC INTS in long processing periods of ADC ISR and finishing the signal processing and then disabling GIE as follows .

ADC ISR
disable ADC INT
enable GIE
..
Process signals
..
disable GIE
enable ADC INT

the codes seem to work fine as of now. The UART and TIMERB INTS worked during signal processing as required. I had to increase stack from default 80 to 160 as warning of 90% usage was appearing in debug mode (IAR EW).

Any expert comments ?

Vinod
--- In m..., "Richard \(UK\)" wrote:
>
> Ideally simply buy a commercial RTOS and let them do the work for you.
>
> I have seen the 'set a flag and process the code in the main program via polling' idea many times. What starts off as a 'good idea' usually ends up as an unstructured mess.
>
> I prefer the DPC (Deferred Procedure Call) or 'fork queue' idea.
>
> Each interrupt simply adds a data packet to a queue, and then triggers a very low priority hardware interrupt via software.
>
> The original hardware interrupt then exits, having done almost zero work.
>
> This leaves the very low priority "hardware" interrupt to run: this code dequeues the packet and processes it to completetion.
>
> This fake hardware interrupt then exists allowing the main program to continue.
>
> Nested interrupts from hardware devcies are not allowed - but the very low priority queue servicing interrupt CAN be interrupted.
>
> The single threaded queue processing interrupt level can be regarded as a very high priority process or task.
>
>
> ----- Original Message -----
> From: Augusto Einsfeldt
> To: m...
> Sent: Sunday, November 29, 2009 11:28 AM
> Subject: Re: [msp430] Re: Nested interrupts Or Alternatives
>
>
>
>
> I am also an atheist therefore I do not believe on magic or spell.
> Nested interrupts works fine when you know what you are doing (easier
> to control when done in assembly), but it doesn't seems to be the case
> of the OP.
> The solution, Vinod, is to use a state machine in your main loop:
> check user inputs while performing the math. Break the math in pieces
> to improve the state machine's time resolution.
> Even the display and keyboard scan can be done in the main loop. You
> could use the timer only to change a flag to say the time has passed,
> then check this flag in the state machine and proceed to the scan
> routine.
> -Augusto
> .
> On Sáb 28/11/09 17:48 , "old_cow_yellow" old_cow_yellow@...
> sent:
> I am an atheist; thus I would use nested interrupt occasionally. (If
> I have the Original Sin of knowing right from wrong, I do not need to
> follow any Commandments.)
> Giving that I am not using any RTOS and one of the interrupts needs
> a lot CPU cycles to process at a priority lower than other interrupt
> services but higher than other background processes, I would consider
> one level of nesting.
> Inside the ISR of that interrupt, I would do the critical part
> first, then enable interrupts, do the lengthy process, and return
> from interrupt.
> I would constrain myself to do this for only one of the interrupts
> so that the nesting is one level deep at most. I would make sure that
> the same interrupt would not interrupt its own ISR.
> --- In m..., "Vinod" ...> wrote:
> >
> > Hi all,
> >
> > I am working on project on metering based on MSP430F249. I am
> using TimerB for my multiplexed display refreshing and key scanning
> at 1ms.
> > I use UART ISR for serial communication. Both these ISRs are short
> and cause no problem.
> >
> > But I have some issues with ADC ISR -
> >
> > I am using ADC12 module for integration of AC energy. The true RMS
> computation of Power and energy takes couple of tens of milliseconds
> for computation (MSP MCU at 8MHz). This blocks the display ISR for so
> long, and I can see jitter in display.
> >
> > I can not think of putting this process in main loop as the user
> interaction for view / edit meter setting should not stop this
> integration.
> >
> > Meter has functions for frequent user interaction for entry of
> some user inputs, during this my energy, time integration should not
> stop - should continue in fore ground.
> >
> > can some experienced people guide how to go about - nesting
> interrupts / any other means ?
> >
> > if I insert a piece of code for polling this process in between
> user interaction - how do I manage variable of two totally different
> processes ?
> >
> >
> > thanks in advance.
> >
> > Vinod
> >
>
>
>
>
>
>
>
>
>
>

Hello Vinod,
I don't know if I can be called an expert on this issue, but I'd say you're doing good. I did the same procedure not long ago for the first time and it's working flawlessly on the 20 equipments installed on field, (with another 100 more to be installed). In my case the need for nesting was a little more crucial because I needed to update the timer A registers for continuous FSK transmission. Given certain circumstances/coincidences, a second timerA interrupt would be triggered while the first one has not yet been processed, resulting in a missing FSK half cycle causing errors on the receiver side. This would occur at least twice during every packet sent, which meant no packets were ever received without errors, so all were discarded.
Nesting Timer A solved the problem nicely. I too had to increase the stack slightly to accomodate the biggest other ISR which now will sometimes be pushed onto the stack.

But as OCY recommended, you should analyse if you need to do some processing (like reading the ADC registers before they are overwritten during an immediate Timer ISR call) before you enable GIE within the ADC ISR.

IAR has a useful feature that lets you see the functions that are in the stack and the size of the stack (Menu View->Stack and View->Call_Stack).
You can try put a breakpoint in the ADC ISR and once IAR halts on it, put a breakpoint in the timer ISR (and set the timer interrupt flag), then hit run and when IAR halts again, you'll see the contents of the stack. You can then find out how much space this additional level of stack (the ADC ISR) takes.
There are other things you can try/test, I hope you get the idea.

Regards,
Michael K.

--- In m..., "Vinod" wrote:
>
> Hi all,
>
> I tried enabling interrupts and disabling ADC INTS in long processing periods of ADC ISR and finishing the signal processing and then disabling GIE as follows .
>
> ADC ISR
> disable ADC INT
> enable GIE
> ..
> Process signals
> ..
> disable GIE
> enable ADC INT
>
> the codes seem to work fine as of now. The UART and TIMERB INTS worked during signal processing as required. I had to increase stack from default 80 to 160 as warning of 90% usage was appearing in debug mode (IAR EW).
>
> Any expert comments ?
>
> Vinod
>
>
> --- In m..., "Richard \(UK\)" wrote:
> >
> > Ideally simply buy a commercial RTOS and let them do the work for you.
> >
> > I have seen the 'set a flag and process the code in the main program via polling' idea many times. What starts off as a 'good idea' usually ends up as an unstructured mess.
> >
> > I prefer the DPC (Deferred Procedure Call) or 'fork queue' idea.
> >
> > Each interrupt simply adds a data packet to a queue, and then triggers a very low priority hardware interrupt via software.
> >
> > The original hardware interrupt then exits, having done almost zero work.
> >
> > This leaves the very low priority "hardware" interrupt to run: this code dequeues the packet and processes it to completetion.
> >
> > This fake hardware interrupt then exists allowing the main program to continue.
> >
> > Nested interrupts from hardware devcies are not allowed - but the very low priority queue servicing interrupt CAN be interrupted.
> >
> > The single threaded queue processing interrupt level can be regarded as a very high priority process or task.
> >
> >
> > ----- Original Message -----
> > From: Augusto Einsfeldt
> > To: m...
> > Sent: Sunday, November 29, 2009 11:28 AM
> > Subject: Re: [msp430] Re: Nested interrupts Or Alternatives
> >
> >
> >
> >
> > I am also an atheist therefore I do not believe on magic or spell.
> > Nested interrupts works fine when you know what you are doing (easier
> > to control when done in assembly), but it doesn't seems to be the case
> > of the OP.
> > The solution, Vinod, is to use a state machine in your main loop:
> > check user inputs while performing the math. Break the math in pieces
> > to improve the state machine's time resolution.
> > Even the display and keyboard scan can be done in the main loop. You
> > could use the timer only to change a flag to say the time has passed,
> > then check this flag in the state machine and proceed to the scan
> > routine.
> > -Augusto
> > .
> > On Sáb 28/11/09 17:48 , "old_cow_yellow" old_cow_yellow@
> > sent:
> > I am an atheist; thus I would use nested interrupt occasionally. (If
> > I have the Original Sin of knowing right from wrong, I do not need to
> > follow any Commandments.)
> > Giving that I am not using any RTOS and one of the interrupts needs
> > a lot CPU cycles to process at a priority lower than other interrupt
> > services but higher than other background processes, I would consider
> > one level of nesting.
> > Inside the ISR of that interrupt, I would do the critical part
> > first, then enable interrupts, do the lengthy process, and return
> > from interrupt.
> > I would constrain myself to do this for only one of the interrupts
> > so that the nesting is one level deep at most. I would make sure that
> > the same interrupt would not interrupt its own ISR.
> > --- In m..., "Vinod" ...> wrote:
> > >
> > > Hi all,
> > >
> > > I am working on project on metering based on MSP430F249. I am
> > using TimerB for my multiplexed display refreshing and key scanning
> > at 1ms.
> > > I use UART ISR for serial communication. Both these ISRs are short
> > and cause no problem.
> > >
> > > But I have some issues with ADC ISR -
> > >
> > > I am using ADC12 module for integration of AC energy. The true RMS
> > computation of Power and energy takes couple of tens of milliseconds
> > for computation (MSP MCU at 8MHz). This blocks the display ISR for so
> > long, and I can see jitter in display.
> > >
> > > I can not think of putting this process in main loop as the user
> > interaction for view / edit meter setting should not stop this
> > integration.
> > >
> > > Meter has functions for frequent user interaction for entry of
> > some user inputs, during this my energy, time integration should not
> > stop - should continue in fore ground.
> > >
> > > can some experienced people guide how to go about - nesting
> > interrupts / any other means ?
> > >
> > > if I insert a piece of code for polling this process in between
> > user interaction - how do I manage variable of two totally different
> > processes ?
> > >
> > >
> > > thanks in advance.
> > >
> > > Vinod
> > >
> >
> >
> >
> >
> >
> >
> >
> >
> >
>

I agree with Augusto in that you can move time consuming computations to the main loop if you keep them short or break them down to shorter functions which will be called sequentialy (NOT nested) or using state machines which is about the same. And the use of state machines is pretty easy to implement.

>From the description, I think the OP problem may lay in the user interaction programming, which may own the main loop. Some times people (often students) use the main loop for one task only (often the menu tree) and in this way this task *owns* the main loop, not leaving room for any other tasks to be executed because the main loop is halted waiting for user input or polling a flag. There is where a state machine comes in very handy.

Let me show you what I usually do when there is a screen with a menu tree:

I have a function called menu(action). Within it there is a state machine MENU_STATE, each of the states is one particular menu from the menu tree.
The parameter 'action' may be the press of a button (digits 0 to 9 or ESC/ENTER/Cursor keys) or a command, like print that menu's screen (which also initializes variables for that menu) or refresh the screen (for updating the value of a variable that's been showed, like current time/date for example).

Here's an example of the menu() state machine. Note there are usually two switches(), the first enters the current menu and within it an action is taken depending on the button or command:

void menu (unsigned char action)
{
static enum {Select=0, Set, View} MENU_STATE=Select; //State Machine
switch (MENU_STATE)
{
case Select:
switch (action)
{
case prt_screen:
// prints this menu screen on display
// initializes this menus variable
LCD_Set(0,0);
printf ("1. Set Parameters");
LCD_Set(0,1);
printf ("2. View Variables");
break;
case Button_1:
MENU_STATE = Set;
menu(prt_screen);
break;
case Button_2:
MENU_STATE = View;
menu(prt_screen);
break;
}
break; // End case for menu 'Select'
case Set:
if (prt_screen)
{
// prints this menu screen on display
// initializes this menus variable
}
else if (action >=0) && (action<=9)
{
// register and print numeric pad keystroke
}
else switch (action)
{
case key_Enter:

MENU_STATE = Select;
menu(prt_screen);
break;
case key_Esc:
MENU_STATE = Select;
menu(prt_screen);
break;
}
break; // End case for menu 'Set'
case View:
switch (action)
{
case prt_screen:
// prints this menu screen on display
// prints this menus variables
break;
case cmd_refresh:
// refreshes the values of variables on display
break;
default:
MENU_STATE = Select;
menu(prt_screen);
break;
}
break; // End case for menu 'View'
default:
printf("Error, menu doesn't exist");
break;
}
}

This is a very large function, but it's execution is pretty fast because it only performs the function of the pressed key in the current menu tree leave.
menu() can be called from the function that scans the keypad when it detects a key was just pressed, and by a timer to refresh the screens status: menu(cmd_refresh). This will only have an effect on a menu that needs refreshing and has a case for cmd_refresh.
In the case of a large processing function, this is much easier. I guess the following would work just fine:

unsigned char Process (unsigned char start)
{
static enum {Pready=0,Pstep1=1,Pstep2=2,...,Pstep6=6} Pstate = Pready;
static operand1,operand2;
if (start) // Start/Restart computation;
Pstate=Pstep1;
switch (Pstate)
{
case Pstep1:
operand1=;
operand2=;

Pstate=Pstep2;
break;
case Pstep2:

Pstate=Pstep3;
break;
...
case Pstep5:

Pstate=Pstep6;
break;
case Pstep6:


Pstate=Pready;
break;
case Pready
// optionally Pstate=Pstep1 for continuous processing
break;
default:
break;
}
return Pstate;
}

then your main loop looks like

for(;;)
{
if (new_key)
{
new_key = 0;
menu(key_value);
}
else if (timer_ms >= 333) // refresh 3Hz (like a tester)
{
timer_ms -= 333;
menu(cmd_refresh); // refresh data on screen at 3Hz
}
if (!Process(0))
menu(cmd_new_result); //
}

Hope this helps.

Michael K.

--- In m..., Augusto Einsfeldt wrote:
>
>
> I am also an atheist therefore I do not believe on magic or spell.
> Nested interrupts works fine when you know what you are doing (easier
> to control when done in assembly), but it doesn't seems to be the case
> of the OP.
> The solution, Vinod, is to use a state machine in your main loop:
> check user inputs while performing the math. Break the math in pieces
> to improve the state machine's time resolution.
> Even the display and keyboard scan can be done in the main loop. You
> could use the timer only to change a flag to say the time has passed,
> then check this flag in the state machine and proceed to the scan
> routine.
> -Augusto
> .
> On Sáb 28/11/09 17:48 , "old_cow_yellow" old_cow_yellow@...
> sent:
> I am an atheist; thus I would use nested interrupt occasionally. (If
> I have the Original Sin of knowing right from wrong, I do not need to
> follow any Commandments.)
> Giving that I am not using any RTOS and one of the interrupts needs
> a lot CPU cycles to process at a priority lower than other interrupt
> services but higher than other background processes, I would consider
> one level of nesting.
> Inside the ISR of that interrupt, I would do the critical part
> first, then enable interrupts, do the lengthy process, and return
> from interrupt.
> I would constrain myself to do this for only one of the interrupts
> so that the nesting is one level deep at most. I would make sure that
> the same interrupt would not interrupt its own ISR.
> --- In m..., "Vinod" ...> wrote:
> >
> > Hi all,
> >
> > I am working on project on metering based on MSP430F249. I am
> using TimerB for my multiplexed display refreshing and key scanning
> at 1ms.
> > I use UART ISR for serial communication. Both these ISRs are short
> and cause no problem.
> >
> > But I have some issues with ADC ISR -
> >
> > I am using ADC12 module for integration of AC energy. The true RMS
> computation of Power and energy takes couple of tens of milliseconds
> for computation (MSP MCU at 8MHz). This blocks the display ISR for so
> long, and I can see jitter in display.
> >
> > I can not think of putting this process in main loop as the user
> interaction for view / edit meter setting should not stop this
> integration.
> >
> > Meter has functions for frequent user interaction for entry of
> some user inputs, during this my energy, time integration should not
> stop - should continue in fore ground.
> >
> > can some experienced people guide how to go about - nesting
> interrupts / any other means ?
> >
> > if I insert a piece of code for polling this process in between
> user interaction - how do I manage variable of two totally different
> processes ?
> >
> >
> > thanks in advance.
> >
> > Vinod
> >
>
>
>
>
>

Thank you Michael for reply with an elaborate example. I have understood the logic, let me give it a try.

In fact as you rightly guessed - user interface function is one of the functions in main loop and is taking the main loop ownership when user interaction starts and hence the issue. Looks like - UI function can be inserted into key scanning ISR itself.

with best regards

Vinod

--- In m..., "Michael" wrote:
>
> I agree with Augusto in that you can move time consuming computations to the main loop if you keep them short or break them down to shorter functions which will be called sequentialy (NOT nested) or using state machines which is about the same. And the use of state machines is pretty easy to implement.
>
> From the description, I think the OP problem may lay in the user interaction programming, which may own the main loop. Some times people (often students) use the main loop for one task only (often the menu tree) and in this way this task *owns* the main loop, not leaving room for any other tasks to be executed because the main loop is halted waiting for user input or polling a flag. There is where a state machine comes in very handy.
>
> Let me show you what I usually do when there is a screen with a menu tree:
>
> I have a function called menu(action). Within it there is a state machine MENU_STATE, each of the states is one particular menu from the menu tree.
> The parameter 'action' may be the press of a button (digits 0 to 9 or ESC/ENTER/Cursor keys) or a command, like print that menu's screen (which also initializes variables for that menu) or refresh the screen (for updating the value of a variable that's been showed, like current time/date for example).
>
> Here's an example of the menu() state machine. Note there are usually two switches(), the first enters the current menu and within it an action is taken depending on the button or command:
>
> void menu (unsigned char action)
> {
> static enum {Select=0, Set, View} MENU_STATE=Select; //State Machine
> switch (MENU_STATE)
> {
> case Select:
> switch (action)
> {
> case prt_screen:
> // prints this menu screen on display
> // initializes this menus variable
> LCD_Set(0,0);
> printf ("1. Set Parameters");
> LCD_Set(0,1);
> printf ("2. View Variables");
> break;
> case Button_1:
> MENU_STATE = Set;
> menu(prt_screen);
> break;
> case Button_2:
> MENU_STATE = View;
> menu(prt_screen);
> break;
> }
> break; // End case for menu 'Select'
> case Set:
> if (prt_screen)
> {
> // prints this menu screen on display
> // initializes this menus variable
> }
> else if (action >=0) && (action<=9)
> {
> // register and print numeric pad keystroke
> }
> else switch (action)
> {
> case key_Enter:
>
> MENU_STATE = Select;
> menu(prt_screen);
> break;
> case key_Esc:
> MENU_STATE = Select;
> menu(prt_screen);
> break;
> }
> break; // End case for menu 'Set'
> case View:
> switch (action)
> {
> case prt_screen:
> // prints this menu screen on display
> // prints this menus variables
> break;
> case cmd_refresh:
> // refreshes the values of variables on display
> break;
> default:
> MENU_STATE = Select;
> menu(prt_screen);
> break;
> }
> break; // End case for menu 'View'
> default:
> printf("Error, menu doesn't exist");
> break;
> }
> }
>
> This is a very large function, but it's execution is pretty fast because it only performs the function of the pressed key in the current menu tree leave.
> menu() can be called from the function that scans the keypad when it detects a key was just pressed, and by a timer to refresh the screens status: menu(cmd_refresh). This will only have an effect on a menu that needs refreshing and has a case for cmd_refresh.
>
>
> In the case of a large processing function, this is much easier. I guess the following would work just fine:
>
> unsigned char Process (unsigned char start)
> {
> static enum {Pready=0,Pstep1=1,Pstep2=2,...,Pstep6=6} Pstate = Pready;
> static operand1,operand2;
> if (start) // Start/Restart computation;
> Pstate=Pstep1;
> switch (Pstate)
> {
> case Pstep1:
> operand1=;
> operand2=;
>
> Pstate=Pstep2;
> break;
> case Pstep2:
>
> Pstate=Pstep3;
> break;
> ...
> case Pstep5:
>
> Pstate=Pstep6;
> break;
> case Pstep6:
>
>
> Pstate=Pready;
> break;
> case Pready
> // optionally Pstate=Pstep1 for continuous processing
> break;
> default:
> break;
> }
> return Pstate;
> }
>
> then your main loop looks like
>
> for(;;)
> {
> if (new_key)
> {
> new_key = 0;
> menu(key_value);
> }
> else if (timer_ms >= 333) // refresh 3Hz (like a tester)
> {
> timer_ms -= 333;
> menu(cmd_refresh); // refresh data on screen at 3Hz
> }
> if (!Process(0))
> menu(cmd_new_result); //
> }
>
> Hope this helps.
>
> Michael K.
>
> --- In m..., Augusto Einsfeldt wrote:
> >
> >
> > I am also an atheist therefore I do not believe on magic or spell.
> > Nested interrupts works fine when you know what you are doing (easier
> > to control when done in assembly), but it doesn't seems to be the case
> > of the OP.
> > The solution, Vinod, is to use a state machine in your main loop:
> > check user inputs while performing the math. Break the math in pieces
> > to improve the state machine's time resolution.
> > Even the display and keyboard scan can be done in the main loop. You
> > could use the timer only to change a flag to say the time has passed,
> > then check this flag in the state machine and proceed to the scan
> > routine.
> > -Augusto
> > .
> > On Sáb 28/11/09 17:48 , "old_cow_yellow" old_cow_yellow@
> > sent:
> > I am an atheist; thus I would use nested interrupt occasionally. (If
> > I have the Original Sin of knowing right from wrong, I do not need to
> > follow any Commandments.)
> > Giving that I am not using any RTOS and one of the interrupts needs
> > a lot CPU cycles to process at a priority lower than other interrupt
> > services but higher than other background processes, I would consider
> > one level of nesting.
> > Inside the ISR of that interrupt, I would do the critical part
> > first, then enable interrupts, do the lengthy process, and return
> > from interrupt.
> > I would constrain myself to do this for only one of the interrupts
> > so that the nesting is one level deep at most. I would make sure that
> > the same interrupt would not interrupt its own ISR.
> > --- In m..., "Vinod" ...> wrote:
> > >
> > > Hi all,
> > >
> > > I am working on project on metering based on MSP430F249. I am
> > using TimerB for my multiplexed display refreshing and key scanning
> > at 1ms.
> > > I use UART ISR for serial communication. Both these ISRs are short
> > and cause no problem.
> > >
> > > But I have some issues with ADC ISR -
> > >
> > > I am using ADC12 module for integration of AC energy. The true RMS
> > computation of Power and energy takes couple of tens of milliseconds
> > for computation (MSP MCU at 8MHz). This blocks the display ISR for so
> > long, and I can see jitter in display.
> > >
> > > I can not think of putting this process in main loop as the user
> > interaction for view / edit meter setting should not stop this
> > integration.
> > >
> > > Meter has functions for frequent user interaction for entry of
> > some user inputs, during this my energy, time integration should not
> > stop - should continue in fore ground.
> > >
> > > can some experienced people guide how to go about - nesting
> > interrupts / any other means ?
> > >
> > > if I insert a piece of code for polling this process in between
> > user interaction - how do I manage variable of two totally different
> > processes ?
> > >
> > >
> > > thanks in advance.
> > >
> > > Vinod
> > >
> >
> >
> >
> >
>


Memfault Beyond the Launch