Deferred Service Routines / Nested Interrupts Concept

Started by Amit Gupta November 9, 2006
Hello everyone

Queries :---

Query - 1

While executing an "Interrupt A" Interrupt Service Routine , the
"Interrupt A" occurs again then how should I handle the sitaution assuming that I dont want to miss any of the interrupts( even while execting ISR).

Is it related to Deferred Service Routines ??

Query - 2

Nested Interrupts

I mean if we have two interrupts :-
Interrupt A(higher priority) and Interrupt B(lower priority)
Now while executing ISR of Interrupt - B, if interrupt A occurs , then nested interrupt will always occur or Interrupt B IST will be completed first ??

I tried the above example for HC08 controller - and found that ISR - B executes forst and then it executes ISR-A.

Does compiler provides any optimization for the same ?

Thanks a lot in avance

Regards

Amit Gupta
Amit Gupta wrote:

> Hello everyone
>
> Queries :---
>
> Query - 1
>
> While executing an "Interrupt A" Interrupt Service Routine , the
> "Interrupt A" occurs again then how should I handle the sitaution
> assuming that I dont want to miss any of the interrupts( even while
> execting ISR).
>

Clear interrupt flag at the beginning of ISR A, not at the end. Interrupts
are lost when HW is trying to set interrupt flag that is already set. To
reduce the risk of missing interrupt, you should shorten the time
interrupt_flag_is_set. Clearing flag A in ISR A sooner, you will definitely
shorten the time, flag A is set. This will help you in case 2 interrupt
event occur at frequency higher than ~1/Tlatency, this won't help you if
more interrupts are coming at too high rate.
> Is it related to Deferred Service Routines ??
>
> Query - 2
>
> Nested Interrupts
>
> I mean if we have two interrupts :-
> Interrupt A(higher priority) and Interrupt B(lower priority)
> Now while executing ISR of Interrupt - B, if interrupt A occurs , then
> nested interrupt will always occur or Interrupt B IST will be completed
> first ??
>
> I tried the above example for HC08 controller - and found that ISR - B
> executes forst and then it executes ISR-A.
>

Did you CLI in ISR-B? This is how CPU works, it masks interrupts while in
ISR. To make interrupt nesting working you should unmask interrupts in ISR
that you want to make interruptible by higher priority interrupt.

If you mean that something unexplainable is happening if nesting, then you
probably don't understand what can happen if you just CLI in lower priority
interrupt. If you CLI in ISR-B and if interrupt flag-B is set, then CPU will
interrupt your ISR-B and jump to ISR-B, and again interrupt ISR-B then jump
to ISR-B ... To prevent it, interrupt-B should be disabled in ISR-B
ISRB()
{
disable_interrupt_B();
CLI;

ISRB_body();

reenable_interrupt_B();
}
S12/HC12 will work the same way as HC08.

S12X is bit different. In S12X, in addition to autoSEI, interrupts that have
the same or lower priority are automatically masked by S12X interrupt
controller. In S12X interruptible ISR should look something like this

ISRB()
{
//disable_interrupt_B and all interrupts that have
// priority <= prio(B)();

// ^^ - this is done before CPU enters ISRB() by
// S12X hardware.
CLI; // - this is still necessary to enable interrupt nesting
ISRB_body();

// reenable_interrupt_B();
// ^^ - this is not necessary, it's handled by S12X hardware
}

> Does compiler provides any optimization for the same ?

What compiler and for what the same?

Edward

>
> Thanks a lot in avance
>
> Regards
>
> Amit Gupta
>
Amit Gupta wrote

Edward and All

I am not clear about your answer for Query 1:-

I have an Interrupt - A ISR executing and I have cleared the interrupt at
the begining and enabled the interrupts by setting _CLI. Now assume that my
Interrupt- A occurs , then in normal situation the Interrupt will start
executing but in practical situation I dont want this to happen. What I want
is that if something like this is occuring in my system , then there is some
malfunctioning in my system , then I will lower the priority of my ISR in
compared to main finction or deffer the service routine. I am exactly not
sure about how this situation needs to be handled but there needs to
deffered the routine that is disturbing the system because in such a case
the system may execute same service routine and will cause whole system to
malfunction.

Looks like this is bit different question. Anyway they both are bit unclear.
You wrote previously that you don't want to lose interrupts, even if
interrupt A occurs while CPU is processing previous occurence of the same
interrupt A. Right? If that's the case then it's obvious that interrupt
latency is too high, your ISR A is too long to handle more offently occuring
events A. What I wrote is an idea how to not miss at least two too fast
interrupts events. "too fast" = a time gap between interrupts is shorter
than the execution time of your ISR. It's obvious that you should avoid such
situations, you should lower interrupt latency and => shorten your ISRs.
What I suggested previously was clearing interrupt flag in the beginning of
ISR. Doing it this way can shorten minimum necessary (to be handled by CPU)
pause between two A events from exe-time of long ISR A down to the time
needed for CPU to jump to ISR A and reach your interrupt_flag_clear(). Of
course it won't work if A-events are continuously coming at rate you are
unable to handle (too long interrupt latency). I suggest you to attach some
double-pulse generator to some interrupt enabled pin and play a bit with it.
ISR should have some software delay loop inside, clear interrupt flag in the
end of routine, then in the beginning. Figure the difference between min
handleable delay between pulses in both cases. Then rise frequency and see
that it won't help you always.

Now about your new question. It's again not too clear. Do you want to 1) not
lose any of interrupts and your CPU/software is too slow; or 2) you have
some interrupt enabled pin normally triggered say up to 5kHz and higher than
5kHz is unexpected and probably is the sign of hardware malfunction? Do you
want to protect from this sort of malfunction? To solve 1) you should lower
interrupt latency or even switch to faster MCU. The second can be solved
disabling interrupt A in ISR A and reenable A after min safe delay. You may
use timer interrupt to reenale A or maybe even do it in main(). In
preemptive RTOS it can be handled similarily, ISR disables itself and some
task reenables it later.

Edward

Kindly provide me with solution where we can use thread like systems or
assign priority /scheduling ? I am not sure of that

Thanks for Query 2 - I could perform nested operation using CLI

Thanks & Regards

Amit

-----Original Message-----
From: k...@ar.fi.lt
Sent: Thu, 9 Nov 2006 10:31:33 +0200
To: 6...
Subject: Re: [68HC12] Deferred Service Routines / Nested Interrupts
Concept
Amit Gupta wrote:

> Hello everyone
>
> Queries :---
>
> Query - 1
>
> While executing an "Interrupt A" Interrupt Service Routine , the
> "Interrupt A" occurs again then how should I handle the sitaution
> assuming that I dont want to miss any of the interrupts( even while
> execting ISR).
>

Clear interrupt flag at the beginning of ISR A, not at the end.
Interrupts
are lost when HW is trying to set interrupt flag that is already set. To
reduce the risk of missing interrupt, you should shorten the time
interrupt_flag_is_set. Clearing flag A in ISR A sooner, you will
definitely
shorten the time, flag A is set. This will help you in case 2 interrupt
event occur at frequency higher than ~1/Tlatency, this won't help you if
more interrupts are coming at too high rate.

> Is it related to Deferred Service Routines ??
>
> Query - 2
>
> Nested Interrupts
>
> I mean if we have two interrupts :-
> Interrupt A(higher priority) and Interrupt B(lower priority)
> Now while executing ISR of Interrupt - B, if interrupt A occurs , then
> nested interrupt will always occur or Interrupt B IST will be
completed
> first ??
>
> I tried the above example for HC08 controller - and found that ISR - B
> executes forst and then it executes ISR-A.
>

Did you CLI in ISR-B? This is how CPU works, it masks interrupts while
in
ISR. To make interrupt nesting working you should unmask interrupts in
ISR
that you want to make interruptible by higher priority interrupt.

If you mean that something unexplainable is happening if nesting, then
you
probably don't understand what can happen if you just CLI in lower
priority
interrupt. If you CLI in ISR-B and if interrupt flag-B is set, then CPU
will
interrupt your ISR-B and jump to ISR-B, and again interrupt ISR-B then
jump
to ISR-B ... To prevent it, interrupt-B should be disabled in ISR-B

ISRB()
{
disable_interrupt_B();
CLI;

ISRB_body();

reenable_interrupt_B();
}

S12/HC12 will work the same way as HC08.

S12X is bit different. In S12X, in addition to autoSEI, interrupts that
have
the same or lower priority are automatically masked by S12X interrupt
controller. In S12X interruptible ISR should look something like this

ISRB()
{
//disable_interrupt_B and all interrupts that have
// priority <= prio(B)();

// ^^ - this is done before CPU enters ISRB() by
// S12X hardware.

CLI; // - this is still necessary to enable interrupt nesting

ISRB_body();

// reenable_interrupt_B();
// ^^ - this is not necessary, it's handled by S12X hardware
}

> Does compiler provides any optimization for the same ?

What compiler and for what the same?

Edward

>
> Thanks a lot in avance
>
> Regards
>
> Amit Gupta
>
Amit,

It's more clear now.

Solution to protect your input capture and detect if pulse edge rate is to
high :-). As I said, you should disable input capture ICn interrupt ICn_ISR,
then reenable ICn interrupt after some safe delay. Suppose you have free
timer channel, configre it for output compare and :
ICn_ISR()
{

...
// setup for delayed ICn reenable, OCm
TCm = TCn + min_delay;
TFLG1 &= (1< TIE |= (1<
// clear ICn flag and interrupt
TFLG1 &= (1< TIE &= ~(1< }

OCm_ISR()
{
if(TFLG1 & (1< ^^^^ you cleared ICn flag on last pulse edge, if it is
set here then
IC occured during min_delay safety period.

// reenable ICn
TFLG1 &= (1< TIE |= (1<
// disable OCm
TIE &= ~(1< }

If you don't have free timer then you could reconfigure your IC channel to
OC temporarily, reconfigure it back to OC after min_delay. However "too
early" detection won't be possible in this case, better check if modulo down
counter or PIT are available, or do it in main().

Regarding your solutions. 1.) - it won't protect you against very high pulse
rate on IC pin. When frequency of pulses is higher than 1/T of your ISR,
then other tasks including your check_for_too_high_freq_task() will not
proceed or proceed very slowly because CPU will continuously enter and enter
ISR... 2.) - RTOS will be better only if you disabled IC interrupt
completely. Using RTOS to reenable IC interrupt after some min_delay isn't
any better than 2-ints solution without a RTOS.
Edward

----- Original Message -----
From: Amit Gupta
To: 6... ; k...@ar.fi.lt
Sent: Thursday, November 16, 2006 1:07 PM
Subject: Re: [68HC12] Deferred Service Routines / Nested Interrupts
Concept
Edward and all
Yeah they are two different question which I mistakingly merged in one.

Well Now, I am interested in second question - malfunctioning part. I do
not understand how the faster MCU willl help in this case, only the
execution rate (MIPS rate increase) which is not the result for
malfunctioning.

Let me tell you the situation - I am using an Input capture interrupt to
measure vehicle speed - number to edge triggered pulses will result in
generating an interrupt. Now assume that due to some drivers mistake- he
overspeed the vehicle - then speed and number of pulses received at port pin
are too high. This is a real scearion failure - mal functioning issue. Now
even if I reenable the Interrupt in the end of ISR, this will actually not
solve my problem.

What can be possible solutions :-

1. Either I use a user variable which actually measures like how many
times the Interrupt is taking place in aminute(or some time), so that if an
interrupt is occuring at very high rate, then I will completely disable the
interrupt.

2. Or I use some time of preemptive RTOS - or if not, then have an OS (by
making it myself) above the processor level layer which actually prioritize
the complate component (measuring vehicle speed is just a part of it).
Something like Priority inversion can take place if some process is
continously running.

This is just in thinking process. Kindly elaborate these solutiion
possible. What I feel practically we have second type solution more
prominent.

Thanks & Regards

Amit

-----Original Message-----
From: k...@ar.fi.lt
Sent: Thu, 16 Nov 2006 12:17:55 +0200
To: 6...
Subject: Re: [68HC12] Deferred Service Routines / Nested Interrupts
Concept

Amit Gupta wrote

Edward and All

I am not clear about your answer for Query 1:-

I have an Interrupt - A ISR executing and I have cleared the interrupt
at
the begining and enabled the interrupts by setting _CLI. Now assume that
my
Interrupt- A occurs , then in normal situation the Interrupt will start
executing but in practical situation I dont want this to happen. What I
want
is that if something like this is occuring in my system , then there is
some
malfunctioning in my system , then I will lower the priority of my ISR
in
compared to main finction or deffer the service routine. I am exactly
not
sure about how this situation needs to be handled but there needs to
deffered the routine that is disturbing the system because in such a
case
the system may execute same service routine and will cause whole system
to
malfunction.

Looks like this is bit different question. Anyway they both are bit
unclear.
You wrote previously that you don't want to lose interrupts, even if
interrupt A occurs while CPU is processing previous occurence of the
same
interrupt A. Right? If that's the case then it's obvious that interrupt
latency is too high, your ISR A is too long to handle more offently
occuring
events A. What I wrote is an idea how to not miss at least two too fast
interrupts events. "too fast" = a time gap between interrupts is shorter
than the execution time of your ISR. It's obvious that you should avoid
such
situations, you should lower interrupt latency and => shorten your ISRs.
What I suggested previously was clearing interrupt flag in the beginning
of
ISR. Doing it this way can shorten minimum necessary (to be handled by
CPU)
pause between two A events from exe-time of long ISR A down to the time
needed for CPU to jump to ISR A and reach your interrupt_flag_clear().
Of
course it won't work if A-events are continuously coming at rate you are
unable to handle (too long interrupt latency). I suggest you to attach
some
double-pulse generator to some interrupt enabled pin and play a bit with
it.
ISR should have some software delay loop inside, clear interrupt flag in
the
end of routine, then in the beginning. Figure the difference between min
handleable delay between pulses in both cases. Then rise frequency and
see
that it won't help you always.

Now about your new question. It's again not too clear. Do you want to 1)
not
lose any of interrupts and your CPU/software is too slow; or 2) you have
some interrupt enabled pin normally triggered say up to 5kHz and higher
than
5kHz is unexpected and probably is the sign of hardware malfunction? Do
you
want to protect from this sort of malfunction? To solve 1) you should
lower
interrupt latency or even switch to faster MCU. The second can be solved
disabling interrupt A in ISR A and reenable A after min safe delay. You
may
use timer interrupt to reenale A or maybe even do it in main(). In
preemptive RTOS it can be handled similarily, ISR disables itself and
some
task reenables it later.

Edward

Kindly provide me with solution where we can use thread like systems or
assign priority /scheduling ? I am not sure of that

Thanks for Query 2 - I could perform nested operation using CLI

Thanks & Regards

Amit

-----Original Message-----
From: k...@ar.fi.lt
Sent: Thu, 9 Nov 2006 10:31:33 +0200
To: 6...
Subject: Re: [68HC12] Deferred Service Routines / Nested Interrupts
Concept

Amit Gupta wrote:

> Hello everyone
>
> Queries :---
>
> Query - 1
>
> While executing an "Interrupt A" Interrupt Service Routine , the
> "Interrupt A" occurs again then how should I handle the sitaution
> assuming that I dont want to miss any of the interrupts( even while
> execting ISR).
>

Clear interrupt flag at the beginning of ISR A, not at the end.
Interrupts
are lost when HW is trying to set interrupt flag that is already set. To
reduce the risk of missing interrupt, you should shorten the time
interrupt_flag_is_set. Clearing flag A in ISR A sooner, you will
definitely
shorten the time, flag A is set. This will help you in case 2 interrupt
event occur at frequency higher than ~1/Tlatency, this won't help you if
more interrupts are coming at too high rate.

> Is it related to Deferred Service Routines ??
>
> Query - 2
>
> Nested Interrupts
>
> I mean if we have two interrupts :-
> Interrupt A(higher priority) and Interrupt B(lower priority)
> Now while executing ISR of Interrupt - B, if interrupt A occurs , then
> nested interrupt will always occur or Interrupt B IST will be
completed
> first ??
>
> I tried the above example for HC08 controller - and found that ISR - B
> executes forst and then it executes ISR-A.
>

Did you CLI in ISR-B? This is how CPU works, it masks interrupts while
in
ISR. To make interrupt nesting working you should unmask interrupts in
ISR
that you want to make interruptible by higher priority interrupt.

If you mean that something unexplainable is happening if nesting, then
you
probably don't understand what can happen if you just CLI in lower
priority
interrupt. If you CLI in ISR-B and if interrupt flag-B is set, then CPU
will
interrupt your ISR-B and jump to ISR-B, and again interrupt ISR-B then
jump
to ISR-B ... To prevent it, interrupt-B should be disabled in ISR-B

ISRB()
{
disable_interrupt_B();
CLI;

ISRB_body();

reenable_interrupt_B();
}

S12/HC12 will work the same way as HC08.

S12X is bit different. In S12X, in addition to autoSEI, interrupts that
have
the same or lower priority are automatically masked by S12X interrupt
controller. In S12X interruptible ISR should look something like this

ISRB()
{
//disable_interrupt_B and all interrupts that have
// priority <= prio(B)();

// ^^ - this is done before CPU enters ISRB() by
// S12X hardware.

CLI; // - this is still necessary to enable interrupt nesting

ISRB_body();

// reenable_interrupt_B();
// ^^ - this is not necessary, it's handled by S12X hardware
}

> Does compiler provides any optimization for the same ?

What compiler and for what the same?

Edward

>
> Thanks a lot in avance
>
> Regards
>
> Amit Gupta
>