Interrupt Question

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
I recently encountered a problem, that I am having difficulty solving. Can
any please shed some light on this topic?

There is a hardware timer counter, which counts from 0 to 59. When it
rollovers from 59 to 0 it will trigger an interrupt handler ISR1.


ISR1( )  ( will increase TS by 1).
   #### A

There is another interrupt handler ISR2, which can happen at anytime and has
a higher priority than ISR1. ISR2 will want to get the exact time from the
TS value and also the value of the hardware counter.

ISR2( )



What is a good way to implement this?

If ISR2 preempts ISR1 at instruction #### A, will it be able to get the
correct values of TS and the hardware counter?

For example:
If the hardware counter is at 0 and TS should be at 100, how do I ensure
that I retrieve hardware counter 0 and TS10%0 and not hardware counter 0 and


Re: Interrupt Question
On Thu, 24 Feb 2005 15:14:02 -0500, "Adam Caruso"

Quoted text here. Click to load it


I'd probably disable higher priority interrupts for a couple of
instructions - but, in some systems, that may not be possible?

Mike Harding

Re: Interrupt Question
On Fri, 25 Feb 2005 08:40:45 +1100, Mike Harding

Quoted text here. Click to load it

I doubt it.  This guy was posting about Unix and VxWorks back in 2001.
I would guess that his college days were back at Towson in about 1997.

As for a real answer, this is a classic problem of developing a
software extension to a hardware counter.  It is a bit tricky to be
sure that you have a consistent low-order and high-order part of the
total counter (hardware plus higher-order software extension).

The fact that ISR2 has higher priority and can presumably interrupt
ISR1 makes this especially difficult.  You don't know in ISR2 whether
you interrupted just before or just after the TS++ in ISR1.  There is
no way to tell from the information available to ISR2.  Unless you
change some groundrules, I would say the problem is unsolvable.

Here is a solution that requires changing some groundrules.  Ensure
that ISR2 is called at least three times in every counter overflow
period.  If this cannot be done, then provide a poll event of this
frequency.  At each such poll, sample the hardware counter.  Compare
the sampled count with the previous count, modulo 60.  If the result
is 0 to 30, then assume the count is just going up.  If the result is
31 to 59, then assume the count has overflowed.  In the case of
overflow, do a TS++.  Forget about ISR1 entirely.  It is useless.  Use
this poll method to maintain a consistent TS and counter value.  Do a
poll on every ISR2 and if necessary at other times, often enough to
ensure that you don't miss any overflows.  That will work.

-Robert Scott
 Ypsilanti, Michigan

Re: Interrupt Question
On Fri, 25 Feb 2005 00:01:15 GMT, (Robert

Quoted text here. Click to load it

If the higher priority ISR2, which is caused by a higher priority but
unrelated event to isr1, can stand to be off by one ISR1 time, record
both the hardware timer and the TS counter. ISR1 must be able to shut
off ISR2 some way, because incrementing its counter TS and saving the
H/W is non-atomic. For instance with a "isr_disable" ISR1code
"isr_enable" sequence. Using this, ISR1 can never interrupt ISR2, and
ISR2 cannot interrupt ISR1 while it is updating the ram copy of TS and
the hardware register.

There are many inherently racy conditions. If you guarantee a winner
to all races that is ok. It is better to prevent the race and
guarantee atomicity of data.

Regards ~Steve

Re: Interrupt Question
Quoted text here. Click to load it

There is also a big processor dependency here.  If  the processor
is 32-bit and TS is a 32-bit value,  the incrementing process
may be atomic.  In that case, the TS value  will either be correct,
or may be one count low, as the timer has triggered ISR1 (which
has not been serviced).  In that case you can poll the hardware
timer register to see if there is a pending interrupt from the
timer.  If so, make a local copy of TC and increment it.

If the incrementing process is not atomic, it gets a bit
more complicated, as you may have to detect an increment
in progress.  You may be able to do this by having ISR1
update two copies of TC. If the first one  is different
from the second, an increment is in progress, and you
can take appropriate action.  (the action to take is
intuitively obvious to the casual observer---as my
physics prof. was fond of saying---yeah, right!)

I suspect there is even more complexity added if ISR1 has
to update some timer hardware  to keep the timing going.
In that case,  you may have to ensure that ISR2 doesn't take
more than one timer tick.
Quoted text here. Click to load it
How do you time the polling?   What if some elements of the main program
loop take longer than the desired polling interval?  (I sometimes get
into that area when doing operations with CF cards.)

It would help a bit if we knew whether TS was counting microseconds,
milliseconds, or seconds.  I hate to make assumptions based on
60 being some sort of magic number.

Mark Borgerson

Re: Interrupt Question
On Thu, 24 Feb 2005 17:04:27 -0800, Mark Borgerson

Quoted text here. Click to load it

Then this method won't work.  The solution is very
application-dependent.  If you can guarantee that polling is never
held off for more than 1/3 (actually 1/2, but I like to add some
margin) of the overflow period then it will work.

I have used a method something like this to extend the 16-bit 8254
counter in regular PCs to a 32-bit count.

-Robert Scott
 Ypsilanti, Michigan

Re: Interrupt Question
What processor do you use? Most motorola processors lock the low byte
of their counters in a buffer if you access teh high byte first. This
way, as long as you read the high byte first and then the low byte, you
are sure of getting the value of the counter when you initiated the

Also there MPU/MCUs don't allow you to preempt and interrupt with
another unless you explicitly clear the interrupt mask. The interrupt
mask is set when you enter the interrupt.

-- Arya

Re: Interrupt Question

Quoted text here. Click to load it
solving. Can
and has
from the
counter 0 and
Quoted text here. Click to load it

If possible my approach would be to move the TS increamenting step to a
task.I would make ISR1 to release a semaphore and make the task
increamenting the value of TS to pend for it.At the task what ever I am
increamenting,I will make another copy of it.Use that copy to read the
updated value from another ISR.
As far Aryas reply,masking may or maynot be involved in the OPs case.If
masking is enabled then theres no question of ISR2 preempting ISR1.So
from what he describes it seems that masking is not involved in his


Re: Interrupt Question

Quoted text here. Click to load it

It seems that it is not possible to resolve the ambiguity of
this problem within the constraints described.

As long as ISR1 can be interrupted the state of TS cannot be
determined by ISR2 under all conditions.

There will always exist at least one meta state where the
sequence of requests for ISR1 and ISR2 is unknowable.

Many methods have been described in this thread that can
minimize this ambiguity. Most of them have been used to solve
this problem in the real world but the only deterministic
solution is to change the problem.

Re: Interrupt Question

Quoted text here. Click to load it


Like... stop interrupts for a bit?

Mike Harding

Re: Interrupt Question

Quoted text here. Click to load it

Disabling interrupts can not fix the problem only reduce the occurrence
rate. If it was homework you would be getting a D.

A high priority interrupt which depends on data generated in a low priority
interrupt is a contradiction. Probably the result of fuzzy thinking in the
system design or hardware restrictions.

If the interrupt priorities can be exchanged the solution is simple,
otherwise some other agent is needed to help the high priority interrupt
know the validity of data from the other or to do the work of the other in
a different way.

Re: Interrupt Question
snipped-for-privacy@nospam.invalid says...
Quoted text here. Click to load it
I would think that the solution is very hardware dependent.
If the processor in question requires that an ISR re-enable ints if
there is to be pre-emption by higher priority interrupts then there is
no problem.  Even thought ISR2 is a higher priority it can be blocked by
ISR1 just by not enabling INTs in the routine.  If the processor in
question guarantees that the at least one instruction is executed in an
ISR when it has occurred then make the first instruction a disable
interrupts.  Basically you need to use some way to temporarily raise the
priority of ISR1 or consider it a critical section and block other INTs.
You gotta' do a Kirk and change the parameters of the test ;).


Re: Interrupt Question says...
Quoted text here. Click to load it

Now that I REALLY think about it, there would still be a problem if ISR2
were running when the hardware timer overflowed.  If ISR2 were being
responded to when the hardware timer rolled over to 0 ISR1 would still
be blocked and the counts would be wrong.  Oh, well, I guess that's why
we don't use interrupts in this manner, huh?


Re: Interrupt Question

Quoted text here. Click to load it

The relative priorities of the interrupts is a moot point.  The third
element (the timer) is running all the time, and cannot be interrupted
(by definition).  All that has to happen is for the timer to roll over
between the time ISR2 is invoked and ISR2 actually reads the timer.

There really is no way to solve this problem without knowing the
hardware involved.  For example, if this were an AVR, I could simply
(Ha!) 1) read the timer, 2) read the RAM value, 2) read the timer
overflow interrupt flag, 3) if the interrupt flag is set, read the
timer again and increment the value read from RAM.  E.g.

      uint8_t lsb;
      uint8_t msb;

      lsb = TCNT0;       // timer count register
      msb = timer0_msb;  // incremented by T0 Ovf ISR

      if (TIFR & _BV(TOV0))  // pending T0 Ovf interrupt
         lsb = TCNT0;

      timestamp = ((uint16_t)msb<<8) | lsb;

Note that this code assumes interrupts are disabled, which is the
normal case during an ISR.


Change is inevitable, progress is not.

Re: Interrupt Question

Quoted text here. Click to load it

In which case with the correct priorities ISR1 will have interrupted ISR2
and incremented the software timer extension. The only problem is when ISR1
occurs between ISR2 reading the software extension and the hardware timer
which is simply detected by reading the software extension again and noting
that any change must have been caused by a hardware timer rollover.

Quoted text here. Click to load it

The OP stated the random (ISR2) interrupt will interrupt the timer (ISR1)

Quoted text here. Click to load it

That would fail if ISR2 interrupted ISR1 before it incremented the

Re: Interrupt Question
Quoted text here. Click to load it
... snip ...
Quoted text here. Click to load it

The reader needs to be at a lower priority than the timer.  Then,
to get a consistent set of values, the reader should:

   1. Read the register
   2. Read the overflow counter.
   3. Reread the register.

If the register counts agree, the reading is consistent, else go
back to step 2.  This time things should work, barring a foolishly
short period between timer ticks.

"If you want to post a followup via, don't use
 the broken "Reply" link at the bottom of the article.  Click on
We've slightly trimmed the long signature. Click to see the full one.
Re: Interrupt Question

Quoted text here. Click to load it

...and here is a solution that changes the problem a little bit.

Make ISR1 have higher priority than anything else that might be
dealing with GetTime(), including ISR2.  ISR1 can continue to be:

interrupt ISR1()    //..whenever hardware counter overflows..

Now, when anybody (main program or ISR2) wants to get a consistent
long time, it does this:


   FirstTS = TS;    //..initial fetch of overflow count
   LowOrderAnswer = hardware counter;
   SecondTS = TS;   //..second fetch of overflow count
   if(sign bit of LowOrderAnswer is set)
      HighOrderAnswer = FirstTS;
      HighOrderAnswer = SecondTS;

   return (HighOrderAnswer with LowOrderAnswer);

If the hardware counter sign bit is set, you can be sure the first
fetch of TS is consistent with it.  If the hardware counter sign bit
is not set, then you can be sure the second fetch of TS is consistent
with it.  Most of the time the two fetches of TS are the same.  But on
those occasions when they are different, this routine always picks the
right one, provided ISR1 is enabled during this time.

-Robert Scott
 Ypsilanti, Michigan

Re: Interrupt Question
Quoted text here. Click to load it

Redefining the problem to one where ISR2 is responsible to
measuring the time of an event to a high resolution and
ISR1 is responsible for keeping track of time over a long
period. We can solve the ambiguity by adding another hardware

The additional counter must have a roll over period longer
than the interrupt rate of ISR1.

The addition counter is never reset by software and is used
to provide time correlation between ISR1 and ISR2.

With this in place the solution is:

When ISR2 begins execution it:

1) Sample the time correlation counter.

2) Place the sample in a queue to be serviced by ISR1.

When ISR1 begins execution it:

1) Samples the time correlation counter.

2) Sample the number of events in the ISR2 queue.

3) Updates the long time period counter.

4) Process the events from the ISR2 time stamp queue
and correlates them to the long time period counter.

5) Then posts ISR2 events for use by the application.

This solution limits the event signaling rate of ISR2
to the tick rate of ISR1.

The combined execution time of ISR1 plus all of the
possible ISR2 interrupts must be less than the interrupt
rate of ISR1. If not you will run out of real time and
could only execute this on a quantum subspace controller.

Quantum Subspace Controllerä a trademark of
Yoyodyne Propulsion Systems. John Bigboote says:
"Can't make an overthruster with out one."

Site Timeline