EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

[cross-post] g21k and non-interruptible functions

Started by Alessandro Basili January 10, 2012
On 2012-01-11, Arlet Ottens <usenet+5@c-scape.nl> wrote:
> > It depends. The manufacturer could also say it's broken/fubar behavior > to withdraw an interrupt before it's properly handled by the CPU, and > there's some logic in that claim. >
This is not unreasonable provided it's handled intelligently by the MCU when it does happen.
> Anyway, I discovered this behavior the painful way on an ARM-7. A short > glitch on the FIQ line can cause an interrupt, but if you deassert it > right away, the CPU can actually make a jump to the IRQ vector. No > matter how you'd like to call that behavior, it's good to be cautious. >
This however is totally unacceptable IMHO. Which specific MCU was this ? That's just seriously broken behaviour in my opinion. It's acceptable for the interrupt source information to no longer be available in this situation when your interrupt handler executes (and you need to handle that) but to jump to a different vector sounds like a MCU hardware level bug IMHO. (Of course, _if_ you don't need the FIQ line, you could just turn off the FIQ interrupt in the CPSR, but I would still be interested in knowing which MCU this was.) Simon. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On 01/11/2012 01:49 PM, Simon Clubley wrote:

>> It depends. The manufacturer could also say it's broken/fubar behavior >> to withdraw an interrupt before it's properly handled by the CPU, and >> there's some logic in that claim. >> > This is not unreasonable provided it's handled intelligently by the MCU > when it does happen. > >> Anyway, I discovered this behavior the painful way on an ARM-7. A short >> glitch on the FIQ line can cause an interrupt, but if you deassert it >> right away, the CPU can actually make a jump to the IRQ vector. No >> matter how you'd like to call that behavior, it's good to be cautious. >> > > This however is totally unacceptable IMHO. > > Which specific MCU was this ?
It was a custom built ASIC, with an ARM7TDMI core (not sure what revision). In most cases, the IRQ would be quietly ignored, because the IRQ handler didn't see anything set in the interrupt status registers. It would however crash the firmware when it was already servicing an IRQ. Even though IRQs were disabled, the FIQ glitch would cause an interrupt (because it was a FIQ), and then jump to the IRQ handler, messing up all the IRQ-banked registers. By the way, the ARM7TDMI TRM says about nFIQ: "This signal is level-sensitive and must be held LOW until a suitable interrupt acknowledge response is received from the processor" So, the code was in violation of the ARM7 specification.
> That's just seriously broken behaviour in my opinion. It's acceptable > for the interrupt source information to no longer be available in this > situation when your interrupt handler executes (and you need to handle > that) but to jump to a different vector sounds like a MCU hardware > level bug IMHO.
I have to say none of the peripheral interrupt sources would do this by themselves. It would only occur when disabling an interrupt by writing the interrupt mask register in the peripheral. I solved it by turning off the FIQ in the CPSR, masking the interrupt source, waiting for the write delay, and re-enabling the FIQ.
On Tue, 10 Jan 2012 17:45:30 -0500, Jerry Avins wrote:

> On 1/10/2012 3:41 PM, David Brown wrote: >> On 10/01/12 19:04, Tim Wescott wrote: >>> On Tue, 10 Jan 2012 15:17:26 +0100, Alessandro Basili wrote: >>> >>>> Dear all, >>>> >>>> I have the need to define some functions as "non-interruptible" and I >>>> remember some #pragma at least for C51 which would do this. I looked >>>> for similar #pragmas for the g21k but apparently I haven't found any >>>> hint. >>>> >>>> Does anyone out there know how to reliably define a function as >>>> non-interruptible? I understand that I could disable all interrupts >>>> and enable them once the function has completed - which will >>>> potentially cause to loose an interrupt, unless level-sensitive - but >>>> I believed there are some "utilities" to do that at compilation >>>> level. >>>> >>>> Some additional info: the non-interruptable function is a function >>>> which returns system time, therefore if interrupted while the value >>>> is being read it may return a wrong value. >>> >>> Such #pragmas are exceedingly non-portable. Besides, all they're going >>> to do "under the hood" is disable interrupts for the duration of the >>> function. >>> >>> If your interrupt hardware is decent then you won't miss an interrupt: >>> either the interrupt is level sensitive and the hardware that >>> generates it won't give up until it is explicitly serviced, or the >>> interrupt is edge sensitive and the interrupt controller takes care of >>> remembering. In either case, it's your job to make sure that the >>> interrupt will persist and be serviced as soon as you come out of the >>> protected section of your function. >>> >>> So -- bite the bullet and do it the grown-up way. You want to save >>> interrupt status (because interrupts may already be turned off going >>> into your function), do your interrupt-sensitive stuff as quickly as >>> can be, restore interrupts to their former state, then exit. >>> >>> >> Obviously Tim is right if you need non-interruptable code. >> >> But there are other ways of doing the job in hand - sometimes disabling >> interrupts is not the only solution. For something like system timers >> like this, you can get correct results by reading repeatedly until you >> have two successive identical reads (and often you can do it with only >> partial duplicate reads). Most of the time you only need the two reads >> - but if you are unlucky and a timer rollover occurs during a read, >> perhaps because of an interrupt, then you will need an extra read. >> >> You'll have to think carefully about the possible interactions between >> the code, the hardware, and interrupts - but it is typically quite >> possible without disabling interrupts. > > That can lead to once-every-two-days kind of failure. A debugging > nightmare.
I'm not sure exactly what David's referring to, but if you have a clock with a bit-count that's higher than the word width of your machine, and a clock read function that's guaranteed to take a small fraction of the time it takes for your clock to run through the bottom-most machine word of it's count, then you can make a dependable clock read that works in just three reads. For example, if you have a 32 bit clock in a 16-bit machine, and it takes less than 32767 ticks to execute your function, you read the upper word, then the lower word, then the upper word. Like this: upper_first_read = upper; lower_read = lower; upper_second_read = upper; Then you look at the two upper word reads. If they're the same, then you construct your clock reading from a concatenation of either of them with the lower read. If they're different, then your look at the lower word: if it's less than 32768 you know that the clock rolled over between the first upper word read and the lower word read, so you concatenate the second upper and the lower word. If they're different and the lower word is large, you know that it rolled over _after_ the lower word was read, and you concatenate the lower word with the _first_ upper word. I assume that this makes perfect sense to you now, and that you can see how, if the overall function doesn't get stalled for a good long time, that this is going to be dead reliable, forever. Or, you'll remember doing it. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com
On 2012-01-11, Arlet Ottens <usenet+5@c-scape.nl> wrote:
> On 01/11/2012 01:49 PM, Simon Clubley wrote: >> >> This however is totally unacceptable IMHO. >> >> Which specific MCU was this ? > > It was a custom built ASIC, with an ARM7TDMI core (not sure what > revision). In most cases, the IRQ would be quietly ignored, because the > IRQ handler didn't see anything set in the interrupt status registers. >
I see. I thought may have been a problem in some manufacturer's mainstream MCU. in which case I wanted to know which one (in case I came across it :-)).
> It would however crash the firmware when it was already servicing an > IRQ. Even though IRQs were disabled, the FIQ glitch would cause an > interrupt (because it was a FIQ), and then jump to the IRQ handler, > messing up all the IRQ-banked registers. > > By the way, the ARM7TDMI TRM says about nFIQ: > > "This signal is level-sensitive and must be held LOW until a suitable > interrupt acknowledge response is received from the processor" > > So, the code was in violation of the ARM7 specification. >
That may be true, but personally I would still not expect this behaviour when that specification is violated. I would have expected it to be treated as more like a spurious interrupt would be on a normal IRQ handler. Although having said that, I can see how the internal MCU interrupt hardware logic, when it's triggered, might check FIQ to see if it's active, find out that it isn't and just wrongly assume it's been triggered as a result of a (now spurious) IRQ request.
>> That's just seriously broken behaviour in my opinion. It's acceptable >> for the interrupt source information to no longer be available in this >> situation when your interrupt handler executes (and you need to handle >> that) but to jump to a different vector sounds like a MCU hardware >> level bug IMHO. > > I have to say none of the peripheral interrupt sources would do this by > themselves. It would only occur when disabling an interrupt by writing > the interrupt mask register in the peripheral. I solved it by turning > off the FIQ in the CPSR, masking the interrupt source, waiting for the > write delay, and re-enabling the FIQ. >
I understand now. Thanks for having taken the time to explain. Simon. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On 11 Jan., 19:24, Simon Clubley <clubley@remove_me.eisner.decus.org-
Earth.UFP> wrote:
> On 2012-01-11, Arlet Ottens <usene...@c-scape.nl> wrote: > > > On 01/11/2012 01:49 PM, Simon Clubley wrote: > > >> This however is totally unacceptable IMHO. > > >> Which specific MCU was this ? > > > It was a custom built ASIC, with an ARM7TDMI core (not sure what > > revision). In most cases, the IRQ would be quietly ignored, because the > > IRQ handler didn't see anything set in the interrupt status registers. > > I see. I thought may have been a problem in some manufacturer's mainstream > MCU. in which case I wanted to know which one (in case I came across it :-)). > > > It would however crash the firmware when it was already servicing an > > IRQ. Even though IRQs were disabled, the FIQ glitch would cause an > > interrupt (because it was a FIQ), and then jump to the IRQ handler, > > messing up all the IRQ-banked registers. > > > By the way, the ARM7TDMI TRM says about nFIQ: > > > "This signal is level-sensitive and must be held LOW until a suitable > > interrupt acknowledge response is received from the processor" > > > So, the code was in violation of the ARM7 specification. > > That may be true, but personally I would still not expect this behaviour > when that specification is violated. I would have expected it to be treated > as more like a spurious interrupt would be on a normal IRQ handler.
an arm core is just a big chunk of logic, complying with specs like that needs to be done in the logic around it
> > Although having said that, I can see how the internal MCU interrupt > hardware logic, when it's triggered, might check FIQ to see if it's > active, find out that it isn't and just wrongly assume it's been > triggered as a result of a (now spurious) IRQ request. >
yes, the irq and fiq inputs probably go straight to the sequencer it is not unlikely that it could get really confused if half the steps of handling the exception is done with the fiq asserted the other half not snip -Lasse
On Wed, 11 Jan 2012 12:23:27 +0100, Alessandro Basili
<alessandro.basili@cern.ch> wrote:

>On 1/11/2012 9:52 AM, Mac Decman wrote: >[...] >> >> Well, all of this deviates from the fact that YES the analog devices >> sequencer can deal with masking interrupts the way OP requires. All >> he has to do is set the registers correctly for his needs. The >> sequencer has a direct connection to the Interrupt controller on most >> AD parts as far as I can tell. Masking is done in the sequencer >> before it vectors. It took me one whole minute to look at three >> Analog Devices manuals to see this. It takes two clock cycles no >> matter what for delay in doing this and two clocks to undo it. > >It's not clear yet to me whether the interrupt are latched (IRPTL >updated) if interrupts are disabled (IRPTEN=0). By the way, the target >is an ADSP21020. > >> Since >> he never expanded on his actual implementation I guess that is up to >> him. Of course his ISR-masked routine better not run for more than >> two edge-interrupts minus the time to run for the ISR of his >> peripheral otherwise what is the point of masking it. > >Did you mean "...not run for _less_ than two edge-interrupts..."? >Otherwise I think I missed the point. > >> PS. Well I can >> think of a lot of reasons against the previous statement. But they >> are not relevant to what I work on. > >Given the fact that all external interrupts (4) are completely >asynchronous it is not possible to determine the time between >interrupts. But I will be more than happy to listen to other reasons >"against the previous statement" you mentioned. > >> >> Mark DeArman
From the book. 3.6.3.1 Interrupt Mask All interrupts except for reset interrupt can be masked. Masked means the interrupt is disabled. Interrupts that are masked are still latched, so that if the interrupt is later unmasked, it is processed. Upon chip reset, all interrupts except reset are masked. The IMASK register controls interrupt masking. The bits in the IMASK register correspond directly to the same bits in the IRPTL register; for example, bit 10 in the IMASK register masks or unmasks the same interrupt latched by bit 10 in the IRPTL register. If a bit is set, its interrupt is unmasked (enabled); if the bit is cleared, the interrupt is masked (disabled). The IMASK register prevents the interrupts from being serviced but not from being latched in IRPTL for future recognition.
On Wed, 11 Jan 2012 12:23:27 +0100, Alessandro Basili
<alessandro.basili@cern.ch> wrote:

>On 1/11/2012 9:52 AM, Mac Decman wrote: >[...] >>
[snip]
> >It's not clear yet to me whether the interrupt are latched (IRPTL >updated) if interrupts are disabled (IRPTEN=0). By the way, the target >is an ADSP21020.
[snip]
> >> >> Mark DeArman
For example #define ENABLE_INTERRUPTS() asm("bit set IMASK SOMEBITS; nop; nop;") #define DISABLE_INTERRUPTS() asm("bit clr IMASK SOMEBITS; nop; nop;") Mark DeArman
On 12-01-12 00:20 , Mac Decman wrote:
> On Wed, 11 Jan 2012 12:23:27 +0100, Alessandro Basili > <alessandro.basili@cern.ch> wrote: > >> >> It's not clear yet to me whether the interrupt are latched (IRPTL >> updated) if interrupts are disabled (IRPTEN=0). By the way, the target >> is an ADSP21020.
> From the book. > > 3.6.3.1 Interrupt Mask > All interrupts except for reset interrupt can be masked. Masked means > the interrupt is disabled. Interrupts that are masked are still > latched, so that if the interrupt is later unmasked, it is processed.
That's clear, for interrupt *masking*. I think Alessandro's point is that the 21020 User Manual does not explicitly say that interrupts are latched while all interrupts are *globally disabled* with IRPTEN = 0. I looked for it in the UM, but did not find it (either). Most processors I've looked at do latch interrupts even whle interrupts are globally disabled, and whatever the status of the interrupt mask, but the 21020 User Manual does not positively say that. It should be simple to solve the question by experiment, for one who has a real 21020 available. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .
On Thu, 12 Jan 2012 14:30:48 +0200, Niklas Holsti
<niklas.holsti@tidorum.invalid> wrote:

>On 12-01-12 00:20 , Mac Decman wrote: >> On Wed, 11 Jan 2012 12:23:27 +0100, Alessandro Basili >> <alessandro.basili@cern.ch> wrote: >> >>> >>> It's not clear yet to me whether the interrupt are latched (IRPTL >>> updated) if interrupts are disabled (IRPTEN=0). By the way, the target >>> is an ADSP21020. > >> From the book. >> >> 3.6.3.1 Interrupt Mask >> All interrupts except for reset interrupt can be masked. Masked means >> the interrupt is disabled. Interrupts that are masked are still >> latched, so that if the interrupt is later unmasked, it is processed. > >That's clear, for interrupt *masking*. I think Alessandro's point is >that the 21020 User Manual does not explicitly say that interrupts are >latched while all interrupts are *globally disabled* with IRPTEN = 0. I >looked for it in the UM, but did not find it (either).
That is not what OP asked. He said what is the pragma to disable interrupts yet continue to latch them. So... The Analog Devices parts do not latch Interrupts when IRPTEN=0 or atleast don't respond to them. That is on the same page of the manual.
> >Most processors I've looked at do latch interrupts even whle interrupts >are globally disabled, and whatever the status of the interrupt mask, >but the 21020 User Manual does not positively say that. > >It should be simple to solve the question by experiment, for one who has >a real 21020 available.
On 1/12/2012 9:29 PM, Mac Decman wrote:
[snip]
>>> On Wed, 11 Jan 2012 12:23:27 +0100, Alessandro Basili >>> <alessandro.basili@cern.ch> wrote: >>> >>>> >>>> It's not clear yet to me whether the interrupt are latched (IRPTL >>>> updated) if interrupts are disabled (IRPTEN=0). By the way, the target >>>> is an ADSP21020. >>
[snip]
> > That is not what OP asked. He said what is the pragma to disable > interrupts yet continue to latch them. So...
I snipped the - what I think - not relevant part of your message and left what you already quoted. I never asked "what is the pragma to disable interrupts yet continue to latch them".
> The Analog Devices parts do not latch Interrupts when IRPTEN=0 or > atleast don't respond to them. That is on the same page of the > manual. >
While it is perfectly clear that if interrupts are disabled "Analog Devices parts" don't respond to them, my question still stays, because I would like to understand whether I will miss completely the interrupt if I disable them with IRPTEN=0 or not. I may decide to mask the interrupts instead, which on the contrary it is explicitly stated that masking will not prevent latching for future recognition. quoting the manual:
> 3.6.2 Interrupt Latch > The interrupt latch (IRPTL) register is a 32-bit register that latches > interrupts generated by an external event (one of IRQ3-0) or an internal > processor event (e.g., multiplier exception). This register contains any > current interrupt or any pending interrupts. Because this register is > readable and writeable, any interrupt except for reset can be set or cleared > in software. Do not write to the reset bit (bit 1) in IRPTL because this puts > the processor in an illegal state. > IRPTL is cleared by a processor reset.
no mentioning of latching while IRPTEN=0.
> 3.6.3 Interrupt Masking And Control > All interrupts except for reset can be enabled and disabled by the global > interrupt enable bit, IRPTEN, bit 12 in the MODE1 register. This bit is > cleared at reset. You must set this bit for interrupts to be enabled.
no mentioning of latching while IRPTEN=0.

The 2024 Embedded Online Conference