2
\$\begingroup\$

I am learning and experimenting on the 8051 (AT89C51). From what I have learnt so far regarding interrupts, I understand that an interrupt with a higher priority can interrupt an interrupt with a lower priority.

This could mean two things. Either it can mean that since the higher priority interrupt is checked first, if both the higher and lower priority interrupts activate at the same time, the higher priority will be serviced first, meaning, the higher priority interrupt will interrupt the lower priority interrupt preventing it's immediate execution until the higher priority interrupt is serviced.

Or, - for which i am posting this question mainly - it can mean that while a low priority interrupt is already being serviced, a higher priority interrupt can literally and actually interrupt it, make the MC jump to the higher priority interrupt's own service routine and after the higher priority interrupt is serviced, execution will return to where it jumped from in the interrupt service routine of the lower priority interrupt.

The second one seems the higher probability from what I am observing.

But this would imply a few things.

Firstly, if multiple interrupts are to be used, the program has to be designed carefully, otherwise it might be a mess. One interrupt can come up within a certain process of another interrupt, change register and other values, then the previous interrupt resumes and everything is messed up.

Secondly, as it seems naturally, the reset value of the IP (Interrupt Priority) register is 00000000b. That is, no interrupt is assigned an exceptional higher priority. And in this default stage, the priority organization is such:

INT0 (external interrupt 0) TF0 (timer interrupt 0) INT1 (external interrupt 1) TF1 (timer interrupt 1) serial communication

And as such, INT0 can interrupt TF0 while it is already being serviced, and TF0 can interrupt INT1 or TF1 while they are already being serviced, unless the priorities are altered in any manner.

Now my question specifically is, is my understanding regarding a higher priority interrupt interrupting a lower priority interrupt while it is already being serviced, correct?

And, is my (possible) conclusion regarding the default value of 0 of the IP register and the default higher priority interrupts interrupting the default lower priorities interrupts while they are already being serviced, unless the priorities are altered, correct?

\$\endgroup\$
2
  • \$\begingroup\$ I think you are right, generally. Just a few things: 1) in a interrupt handler you have to manually re-enable interrupts, if you want to be further interrupted. 2) interrupts are checked sequentially, probably in order of some internal priority, but anyway it's very difficult for two interrupts to happen "in the same time". 3) An interrupt interrupting another interrupt does nothing special: every IRQ handler MUST, ALWAYS, preserve the registers it modifies - and that is all. \$\endgroup\$ Commented Oct 26, 2021 at 16:03
  • \$\begingroup\$ Oh, yeah. I was a bit aloof from the fact that if an ISR has to operate on any certain register or memory location, it can simply save everything, do it's own job, then load everything back and then return. That way it won't be much of a mess and would be relatively simpler to design and manage. Thanks, specially for the last point. \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 0:22

3 Answers 3

2
\$\begingroup\$

I've not found a decent datasheet for the uC you mention. The original 80C51 datasheet states this:

An interrupt will be serviced as long as an interrupt of equal or higher priority is not already being serviced. If an interrupt of equal or higher level priority is being serviced, the new interrupt will wait until it is finished before being serviced. If a lower priority level interrupt is being serviced, it will be stopped and the new interrupt serviced. When the new interrupt is finished, the lower priority level interrupt that was stopped will be completed.

From the AT89C51ED2 datasheet: "If interrupt requests of the same priority level are received simultaneously, an internal polling sequence determines which request is serviced. Thus within each priority level there is a second priority structure determined by the polling sequence."

enter image description here

if multiple interrupts are to be used, the program has to be designed carefully

Yes. Unless you are writing everything in assembly your compiler should provide this (check the entry/exit code added to the ISRs). You should also check the maximum call level in the "non-ISR" code to guarantee the stack use limit at the worst case.

is my understanding regarding a higher priority interrupt interrupting a lower priority interrupt while it is already being serviced, correct?

Yes.

the reset value of the IP (Interrupt Priority) register is 00000000b. That is, no interrupt is assigned an exceptional higher priority

The datasheets above have two IP registers (low and high). Please add the one you are referring to to the question (if needed). Note: that polling priority is not the same as interrupt priority. If all interrupts are initialized to 0 priority, they do not interrupt each other.

\$\endgroup\$
4
  • \$\begingroup\$ I am actually used to the assembly only, so I do not understand what you mean regarding the "entry/exit codes". But we can continue the discussion anyway. Everything you say is good, but I am a bit confused regarding "two IP registers". I do not have a good datasheet either. But the most significant thing that I understand from your answer is that, polling priority and interrupt priority are not same. \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 0:44
  • \$\begingroup\$ If so, this would mean that my assumption that the default higher priority INT0 would be able to interrupt the default lower priority TF0, is wrong. Since, on reset all interrupts apparently have priority level 0 (or at least, same priority level, and from the book 8051 by Mazidi which I am studying, it seems that the default priorities are all 0). Thus, if both INT0 and TF0 activate at the same time, INT0 will be serviced first. But, if INT0 activates while TF0 is already being serviced, INT0 will have to wait until TF0 finishes, although INT0 has a higher polling priority. \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 1:11
  • \$\begingroup\$ Is this deduction of mine correct? \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 1:11
  • \$\begingroup\$ And from the answer of @Syed, it seems like the IP register is one. Maybe for ease of discussion the datasheet represented the single register as two registers, the upper and the lower parts. Would you please provide a link to the datasheet? \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 1:13
1
\$\begingroup\$

Let's say you have not set interrupt priorities. The Interrupt priority register is all logic zeros. To make the discussion easier, assume that there are two registers (let me call them upper/lower registers)

$$\begin{array}{cccccccc} 7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ - & - & - & - & - & - & - & - \\ - & - & \text{PT2} & \text{PS} & \text{PT1} & \text{PX1} & \text{PT0} & \text{PX0} \\ \end{array}$$

The Interrupt priority register is polled (right to left), there is nothing in the upper register, so the lower register is polled and the priority is established as indicated above the registers. There are 2 priority levels for the 8051 architecture.

Now let's say you bump up the priority of PT1.

$$\begin{array}{cccccccc} 7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ - & - & - & - & \text{PT1} & - & - & - \\ - & - & \text{PT2} & \text{PS} & - & \text{PX1} & \text{PT0} & \text{PX0} \\ \end{array}$$

The upper register is polled from right to left, PT1 gets the highest priority. Then the lower register is polled from right to left and priorities are established as before (excluding PT1 of course).

If you bump up the priority of every interrupt, the interrupt priority register would be polled and the priorities will be established at default values; then the lower register will be polled but there will be nothing there.

In short the IP register is polled twice: once for 1s and then for 0s.

\$\endgroup\$
3
  • \$\begingroup\$ So, this should mean, by default, all interrupts have the same (0) priority level, but the polling priority is different? And thus, no interrupt will actually be able to interrupt any other interrupt unless it's priority is raised? Meaning, if both INT0 and TF0 activate at the same time, INT0 will be serviced first since it is checked first. But TF0 will not be interrupted while it is already being serviced if INT0 is activated in the meantime. Am I right? \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 1:24
  • 1
    \$\begingroup\$ Init: all INTs have zero priority but a polling order is in place. If PT0 is being serviced and PX0 arrives, it has higher priority due to polling order. It will be serviced. But assume PT0 happens to have priority '1' i.e. it has been moved to the theoretical upper register and it is being serviced, then PX0 has lower priority and it will not block PT0. Experimentation is the key to understanding this. \$\endgroup\$
    – Syed
    Commented Oct 27, 2021 at 6:21
  • \$\begingroup\$ Ok, so the default polling order also contributes to the priority of an interrupt according to you. The book I am reading from (8051 by Mazidi) also seems to imply this. Ok, anyway, yes, the key to understanding the behavior of the MC interrupts is through experimenting. Will keep that in mind. Thanks bro. \$\endgroup\$
    – shafik
    Commented Oct 27, 2021 at 8:44
0
\$\begingroup\$

Your first characterization is a special case of your second characterization where the routine for the low-priority interrupt that happens "at the same time" is interrupted by the routine for the high-priority interrupt at the very beginning before it starts. Everything else is much as you said it is.

There are several things to note. (1) The registers R0-R7 are not fixed locations but are pointers to one of 4 register windows, which is determined by PSW. So, the simplest way to avoid register conflicts for R0-R7 and/or to do context-switching is to stack the PSW and reset the register window in PSW. (2) You can do a lot of things with priority. If a service routine at high priority is long, in the context of other time-critical high-priority routines, then you do the time-critical part of it first, drop the priority, and return from the service routine without clearing the interrupt flag. When it comes back, you can do the low-priority handling and then reset the flag for high priority when done. (3) To handle the cases where high-priority events can - during a burst most - temporarily outrun the low-priority handlers, you'd, instead, spool the requests for low-priority action and use a sleeping barber protocol.

That's essentially what happens with the handlers for the 5 data clock timestamps for the 8051FA in this example application multi-threaded data collection example (meant to be assembled using the CAS assembler), from the early 1990's, where everything is context-switching and threads (but where suggestion (1) was not used ... which would have simplified things a bit). The application cited is set up as the top-level foreground thread, which is outside of all ISR's and which self-terminates, since there is no polling, the low-priority background threads, which are all inside ISR's and the high-priority background threads, which are also all inside ISR's. This provides a natural, organic implementation of thread priority.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.