Searching \ for 'Nested Interrupt questions' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/ints.htm?key=interrupt
Search entire site for: 'Nested Interrupt questions'.

Truncated match.
PICList Thread
'Nested Interrupt questions'
1999\10\11@205844 by Thomas Brandon

flavicon
picon face
Has anyone written a program that dealt with interrupts occuring during an
interrupt. I know there are no nested interupts but from reading the docs,
the following 2 methods should allow (some) interupts during interrupts to
not be missed (delayed, but not missed):
1) Process interrupt as normal. Clear bit of specific interrupt dealt with.
Copy the PIR registers to memory and then clear them. In code after
interrupt, check saved register and deal with any other interupts. The
pseudocode would then be something like this:

Interrupt Handler:
   Find interrupt cause
   Handle interrupt (1)
   Clear appropriate bit
   Copy PIR's to memory (2)
   Return From interrupt (3)

Any interrupts between (1) and (2) would set the appropriate PIR bit , but
as the GPIE is clear no interrupt will occur. Any interrupts occuring
between (2) and (3) will trigger after (3) due to the GPIE being set again
via RETFIE. The only problem is if this occurs what do you do with the
interupts saved at (2) but not yet dealt with. You could deal with this at
the beginning of the interrupt handler but this could considerably lengthen
the interupt processing time.

This is really only suitable when all processing is interrupt triggered. The
background loop would simply continually check the appropriate memory for
missed interrupts. This is about all this loop could do assuming reasonable
interrupt response is needed.

2) Simply ignore the fact that multiple interrupts can occur. Do priority
interrupt handling (i.e. deal with only one interrupt at a time) and only
clear the appropriate bit. Thus when RETFIE is called and GPIE is set any
pending interrupts will trigger.

The 2nd method is slightly more flexible in that background processing can
continue however it means interrupts will be delayed by other interrupts.
After calling RETFIE there will be an approx. 3TCY delay to the next
interrupt trigger. Hence if 3 interrupts occur at once there will be 6TCY
and the processing time of the other 2 interrupts delay. Also, to ensure
adequate handling of critical interrupts, priority checking must be done
adding further processing time.

Both of these methods could be improved by simultaneously handling multiple
interrupts where appropriate but again extra logic is required.

Has anyone implemented an interrupt critical system on a PIC? How did you
get around the problem of overlapping interrupts? Are there any problems in
the above methods?

Tom.

1999\10\12@050059 by Morgan Olsson

picon face
Hej Thomas Brandon. Tack fšr ditt meddelande 11:00 1999-10-12 +1000 enligt nedan:
>Has anyone written a program that dealt with interrupts occuring during an
>interrupt.

Oh yes! Been experimentally using for two weeks now. Works wonderfully :)

I have split the service in two stages: Primary and secondary.

Idea: Primary get the interrupts, buffers and clears their flags, and secondary do the heavy processing, while having enabled interrupt so primary service can recieve new events.

Primary services is very short routines, check every possible interrupt cause, either does full servise of it if it can be done in few cycles, if not it sets a flag requesting secondary service.  Prim service clears the requests flags.
It is perfectly possible to buffer primary events such as the timer0 interrupt i let increment a register, which value in the secondary service is used for a lot of timing puroses and then decremented.  Another example is the 2-phase encoder reader that in primary service counts up/down a byte counter, that in secondary service is transferred to 16 bit, speed and accelerationan analysis etc.

At interrupt when running main program causes primary service to run.
If no prim service has requested secondary we retfie to main.

If any prim service request secondary service, then the prim service instead goto secondary service. Secondary service set GIE.

So, while doing secondary service (chewing buffered events, updating a bunch of software timers, running SPI etc) we can get interrupted again.

BUT if we now get interrupted we need to store W and status in another set of registers before running prim service.  I have solved it by at the interrupt vector check a flag telling wether we have saved main registers or not.  If this flag is not set, this is the first interrupt level from main (level 1) so we save W status, FSR, PCLATH, tehn set this flag, run prim serv, then goto sek serv, reenable interrupt) whan restoring theese registers we clear this flag.

If that flag is set when entering interrupt vector, that tells us that the sekondary service is running.  In taht case we goto a routine that saves W and SATAUS in other registers than used for saving main regs, set anathor flag indicating that we are now running in interrupt level 2, then goto primary service.  Et end of primary service check for that flag; if clear we are in first level so goto sek service, if set then clear it and restore W and status, and retfie to where we were in sek service.

SOME TIPS:
If we can keep all tables in the interrupt system below adress 256 then we need not save/restore PCLATH when shifting between level 1 and 2.
If using FSR only in sek or only in prim service or not at all, don«t need to handle that either.

The secondary service routines are the perfect place to have "servers" that executes on requests fron various clinets in both the interupt system and in main program.
I have one for driving SPI to external devices.  And one for generating commands to the MAX110 A/D, transfer is done through request to SPI driver.  The drivers can prioritize the tasks monitor errors etc.  The main program only have load some register with input data, set a request flag, and when it is cleared the operation is done, so read teh result register.

Each server is done like a state machine running after each other.
At the end of sek service there are two check made:
1) If new request from prim service then loop to begining of sek service.
2) If a server is not ready, but we see that it can run more (watch it«s state variable, and runing-allowed-condition i.e SPI BF flag) if so, then call it.

Using all kinds of trick we do not only reduce max interrupt response time greatly, byt also througt buffering greatly increase peak frequency and by having less registers to handle between pim and sek switch, we have more time to work on a process instead.

Another trick is to not enable interrupt for services that is not very time critical. As example i have 4kHz timer interrupt, which is buffered to trigger the secondary service.  So even if i do not enable SPI interrupt i have the SPI server routine check SPI status with average 4kHz.  Saves unnecessary register storing/restoring and flag twiddling.

Hope I got everything right, I«m stressed today.

Most important: draw everything, especialy the interrupt level flagging, register storing etc process on pieces of paper before start coding... ;)

And consider every case when an interrupt can occour.
Example; in secondsary service end: disable the interrupt enable before clearing your indicating flag and start restoring main W etc.

Good luck
/Morgan
Morgans Reglerteknik, HŠllekŒs, 277 35 KIVIK, SWEDEN
  tel +46(0)414-446620, fax -70331,   spam_OUTmrtTakeThisOuTspaminame.com

1999\10\12@052834 by Morgan Olsson

picon face
Hej Thomas Brandon. Tack fšr ditt meddelande 11:00 1999-10-12 +1000 enligt nedan:
>Has anyone written a program that dealt with interrupts occuring during an
>interrupt. I know there are no nested interupts but from reading the docs,
>the following 2 methods should allow (some) interupts during interrupts to
>not be missed (delayed, but not missed):
>1) Process interrupt as normal. Clear bit of specific interrupt dealt with.
>Copy the PIR registers to memory and then clear them. In code after
>interrupt, check saved register and deal with any other interupts.

But... code after interrupt?? That can be anywhere, right?

Maybe make a macro that chacks the stored PIR, and place that macro in manu places in the main program?

And take care when new interrupts occour, you have to OR the flags to the stored ones so you don't cear previously interrupts that have not yet been serviced!

-snip-


>2) Simply ignore the fact that multiple interrupts can occur. Do priority
>interrupt handling (i.e. deal with only one interrupt at a time) and only
>clear the appropriate bit. Thus when RETFIE is called and GPIE is set any
>pending interrupts will trigger.

This will make a lot of unnecessary time spent on entering/leaving interrupt
And a much *longer* total execution time if all interrupts happens during processing.

I«ll post my solution in another reply.

/Morgan

Morgans Reglerteknik, HŠllekŒs, 277 35 KIVIK, SWEDEN
  tel +46(0)414-446620, fax -70331,   .....mrtKILLspamspam@spam@iname.com

1999\10\15@131706 by Nikolai Golovchenko

flavicon
face
part 0 4579 bytes content-type:application/octet-stream; (decoded 7bit)

To do this, I use software stack macros (see attachment) that use FSR as a
stack pointer.

A typical interrupt handler looks like this:
           ORG     0x004                   ; interrupt vector location
           PUSHW                             ;store W
           PUSHSTATUS                 ;store STATUS

                                           ;code goes here

           POPSTATUS                      ;restore W
           POPW                            ;restore STATUS
           retfie                          ; return from interrupt

After storing W and STATUS goes usual interrupt flags polling .
As soon as a set flag is detected, it should be cleared and GIE=1 to allow
other interrupts to actually interrupt the process.
Be careful not to allow too many interrupts to be processed, only the ones
that have critical response time, because hardware stack may overflow. The
best way is to keep GIE reset during the most critical interrupt so that it
could finish without unwanted interrupts.
Priority of different interrupts is programmed by flags polling sequence(in
case they trigger at the same time).
That's it.

By the way, I find software stack macros very useful in practically every
program. The best example is when you need one scratch pad register. Using
stack it's simple:
PUSH    ;reserve one byte on stack
....use INDF as a scratch pad reg
POP    ;restore stack

Good luck.


{Original Message removed}

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...