11
\$\begingroup\$

I know that interrupt latency depends on what the CPU is doing when the interrupt takes place (arm interrupt latency guide). This effect is called interrupt jitter. For my application I need an MCU with fixed interrupt latency (zero interrupt jitter). The latency may be arbitrarily high but the jitter must be zero. Do you know any MCU for that?

If there is no any zero jitter MCU, is there a way to programmatically compensate latency differences, adding some processor cycles for cases when interrupt latency is lower than maximum?

I need such MCU to measure times between two events with precision up to 1 cycle. Maybe it would be better not to look for specialized MCU but to construct an external circuit for measuring time?

\$\endgroup\$
20
  • 34
    \$\begingroup\$ I think you may have an XY problem. You want to measure time accurately, and think that it can be done with interrupts, and then you ask what MCUs have best interrupt jitter. But if you wanted to measure time accurately between two events, why would you use interrupts to begin with? Many MCUs have timers for this purpose, with hardware capture event capability, to avoid any interrupt latency or jitter issues. \$\endgroup\$
    – Justme
    Aug 20 at 8:08
  • 2
    \$\begingroup\$ Is timer capture accuracy not affected by interrupt latency of processor? Do you mean that timer can measure times with precision up to 1 timer cycle? \$\endgroup\$ Aug 20 at 8:24
  • 11
    \$\begingroup\$ Now maybe if you tell us what you are actually trying to do here, we can suggest the correct solution, instead of what you think is the the correct solution... \$\endgroup\$
    – Lundin
    Aug 20 at 8:26
  • 7
    \$\begingroup\$ @AndreyRogatkin But that's yet another XY problem, if you need to measure capacitance of a theremin antenna, there's also MCUs with hardware peripherals for capacitive sensing built-in - so neither timers with hardware event capture nor interrupt jitter has really nothing to do with this any more. \$\endgroup\$
    – Justme
    Aug 20 at 8:47
  • 2
    \$\begingroup\$ Measuring charging time doesn't sound very real-time critical at all. Sounds like something you should be able to do with the average SAC ADC, in which case ADC resolution matters a whole lot more than timing specs. \$\endgroup\$
    – Lundin
    Aug 20 at 9:00

10 Answers 10

20
\$\begingroup\$

You are approaching this from the wrong direction. You shouldn't have a specification which says "I need such mcu to measure times between two events with precision up to 1 cycle". You should have a specification which says precision of +/- x (milli/micro/nano) seconds. Time units, not cycles. In my experience, many instruction sets have a fixed amount of cycles. Then you pick a system clock which suits your specification.

Also as mentioned in comments, if you have an input capture timer peripheral (which is very likely), then that one will trigger very accurately. Then it will fire up the interrupt, which executes some time later. If you have a cyclic input capture timer, then you reset it by setting it to "previous trigger point + delay", not "the value of my timer by the time I hit the ISR + delay".

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Thanks! I think you are right. But the question may be interesting for other purposes. Can you please mention modern processors with instruction sets which have fixed amount of cycles? \$\endgroup\$ Aug 20 at 8:37
  • \$\begingroup\$ A two core mcu, such as the Pi Pico, might solve your problem: How to use the two Cores of the Pi Pico? And how fast are Interrupts? - Andreas Spiess, 71,479 views, 2021feb21 (Two thread/core at 5:03, Interrupt at 8:04, frequency counter at 8:54, PIO fast counter at 11:04) youtube.com/watch?v=9vvobRfFOwk. \$\endgroup\$
    – tlfong01
    Aug 20 at 8:40
  • 2
    \$\begingroup\$ @AndreyRogatkin I think on most modern cores it depends on what instruction you are currently executing when the interrupt hits. You'd rather be looking at older, simpler cores I think. But again, you are looking for a solution hoping that it will fix your problem, rather than to focus on fixing the actual problem. \$\endgroup\$
    – Lundin
    Aug 20 at 8:56
  • \$\begingroup\$ I have a CPU on my shelf for an abandoned embedded project that provides by specification fixed cycle execution. Unfortunately it provides zero ISRs so it doesn't answer OP's question. You must poll all IO. But it's got 8 cores so you should be able to do this. \$\endgroup\$
    – Joshua
    Aug 20 at 18:13
  • \$\begingroup\$ @AndreyRogatkin There are some DSPs with instruction sets like that (C6713 e.g.), but I don't know if that still counts as "modern". There are also several SoCs that have built in FPGA-cores which would allow you to implement the time-stamping (to FPGA-clock precision) yourself \$\endgroup\$
    – michi7x7
    Aug 22 at 7:02
8
\$\begingroup\$

I believe some of the simpler PIC series have constant interrupt latency. For example, the ancient PIC16F84 has latency listed as 3.25 Tcy (or 13 clock cycles).

Unless your interrupt request is synchronized with the MCU clock there will be additional +/-0.5 clock cycle.

In situations where you might ask this question, usually the answer is to use hardware such as a timer capture input or timer compare output.

In the dark ages of MCUs (think i8049) I once was able to correct for interrupt latency variations by a variable jump into a field of NOPs as part of a slope ADC, but that would be a bit crazy in 2021 where there is so much hardware available for no cost.

\$\endgroup\$
6
  • \$\begingroup\$ Oho, interesting, the currently executed instruction doesn’t affect the interrupt latency: “The latency is the same for both one and two cycle instructions.” Didn’t expect that. I wonder if they implemented it this way on purpose? \$\endgroup\$
    – Michael
    Aug 20 at 16:18
  • \$\begingroup\$ @Michael Yes, I think they did- it was mentioned as a feature, along with the compact instruction set. To some extent you can trade unneeded MCU speed for hardware and transistors were relatively expensive back then. Their peripherals back then were quite primitive compared to what we get on today's least-capable ARM, and even those are made on relatively crude processes (40-90nm) compared to the state-of-the art, so it does not make much sense now or going forward unless you're designing a highly cost-constrained product with an ultra-cheap processor. \$\endgroup\$ Aug 20 at 16:32
  • \$\begingroup\$ I know, the PIC16F88 was the first microcontroller I ever used. I recalled that instructions took only 1 or 2 cycles but didn’t know that little fact about the constant latency which is why I looked up the data sheet just to make sure ;) Looking at the data sheet I’m happy that I started with such a simple μC. The whole functional description fits in less than 50 pages :) \$\endgroup\$
    – Michael
    Aug 20 at 16:41
  • \$\begingroup\$ @Michael The earliest PICs didn't even have interrupts, which was extremely limiting in the kind of applications (controllers) I was working on at the time. 50 pages is very nice, a TI one I was looking at recently (AM64x) has a 7,411 page datasheet! And, of course, that doesn't include all the software documentation. \$\endgroup\$ Aug 20 at 16:53
  • \$\begingroup\$ @Michael: On many PIC microcontrollers, many "two-cycle" instructions do all of their work in the first cycle, but end without having fetched the next instruction they should execute; the execution unit must thus spend an idle cycle either doing nothing, or incrementing the program counter while awaiting the availability of the next instruction. If an interrupt occurs during the execution of an instruction or idle cycle, the next cycle will need to be spent fetching the first instruction of the interrupt handler while the execution unit does nothing except possibly incrementing the PC. \$\endgroup\$
    – supercat
    Aug 20 at 19:26
6
\$\begingroup\$

One way would be to not use interupts for measuring the time at all. Certain processors like the SAMD series from Microchip have an event system, where peripherals can trigger events which lead to other hardware to perform different actions.

Considering you want to measure the time taking for charging a Capacitor:

  • Analog Comparator 1 (low Voltage) -> Timer start
  • Analog Comparator 2 (high Voltage) -> Timer capture & CPU Interupt

The interupt routine can then be executed without timepressure as the time value is saved in the capture register. This way the only jitter would be from the Analog Comparator and the length of it's clock. With a maximum clock speed of 48Mhz you end up with a resolution of 20ns and a jitter of about +-10ns. This also has the advantage that the CPU can run slower than the timer to preserve power.

There will always be jitter when working with a timediscrete processor, it can only be reduced.

\$\endgroup\$
6
\$\begingroup\$

Input Capture

Many, many microcontrollers have an "input capture" feature.

A timer runs freely at a fixed frequency. When an external signal happens, the timer value is copied to a register, and an interrupt is raised.

Regardless of the interrupt latency, then, the interrupt handler can read the value in the register and determine the precise instant at which the event happened, down to the frequency of the timer.

Google "input capture timer" or "input capture interrupt" for many links.

\$\endgroup\$
4
\$\begingroup\$

For my application I need a mcu with fixed interrupt latency (zero interrupt jitter). The latency may be arbitrarily high but the jitter must be zero. Do you know any mcu for that?

Even if you got a CPU with completely deterministic interrupt latency other things will break your timing. That is to say, deterministic interrupt latency won't by itself guarantee that your interrupt code runs with fixed timing.

  • If you are running interrupts its likely that you will have other pieces of code that will need to be interrupt-safe. For example writing or reading a data structure that requires more than one read/write instruction. Safely accessing such structures usually involves defining "critical sections" where you briefly disable interrupts to do something atomically and then re-enable them. If your interrupt occurs while a critical section is executing then you just created non-deterministic interrupt latency.
  • If the CPU instructions within your interrupt routine don't have deterministic timing then you will have timing jitter regardless of if the interrupt latency is fixed. This can happen for example if you use a cache. If the instructions/data were/weren't in the cache when the interrupt began then the timing can change.
  • If there is any peripherals that share access to the memory bus, then your instruction timing can change. For example if a DMA transfer is running when the interrupt occurs then there your interrupt code may run slower than if a DMA transfer wasn't happening when the interrupt occurred.

So to sum up, if you want completely deterministic timing you can't have any critical sections which disable interrupts. Data structures shared with the interrupt code must be lock free. All code and data used by the interrupt must always permanently be either locked in or out of the cache. And you can't use any DMA or other peripherals that can stall the processor's access to memory.

So if you need very stable timing the solution is to put that timing critical processing into some sort of dedicated hardware that's doing nothing else. This could be...

  • A capture-compare peripheral (present in may MCUs)
  • A small auxiliary microcontroller running code that just captures your signal.
  • An FPGA
  • A special chip or circuit.

You can also look at something like the ZYNQ SoC made by Xilinx. The ZYNQ combines either 1 or two ARM Cortex A9 processor cores and FPGA fabric in one chip. Its possible to configure a small part of the FPGA fabric into a specialized circuit that will capture your signal with accuracy down to 1 clock cycle.

If you want both high speed and cycle accurate timing then FPGAs are a good option.

\$\endgroup\$
5
  • \$\begingroup\$ without elaborating further, "So to sum up, if you want completely deterministic timing you can't use any data structures larger than the processor register size (8, 16, 32, 64 bits) that are also somehow shared with interrupt code" is totally wrong! \$\endgroup\$
    – schnedan
    Aug 22 at 21:35
  • \$\begingroup\$ @schnedan It would be useful if you would elaborated further. If there is any mistake I will amend my answer to avoid misleading any readers. \$\endgroup\$
    – user4574
    Aug 23 at 1:36
  • \$\begingroup\$ in short: on an deterministic mcu, without caches n stuff, the code and data size in interrupts only add latency, but not jitter. if your mcu has modern features like out of order and caches, every piece of sw, no matter of code and data size has now jitter (but without further thinking about, it should have an upper bound...). \$\endgroup\$
    – schnedan
    Aug 23 at 6:28
  • \$\begingroup\$ " If your interrupt occurs while a critical section is executing then you just created non-deterministic interrupt latency." Thats only relevant if the data is altered in the interrupt. Also you should keep interrupts and such sections short. So if memory is available, e.g. a double-buffer (fifo) can be used, so no disabling of the interrupt is needed and jitter is reduced. \$\endgroup\$
    – schnedan
    Aug 23 at 10:18
  • \$\begingroup\$ @schnedan I agree that if data structures can be used that don't require critical sections then that problem goes away. Thanks. the answer was changed to reflect that. Interestingly, it tends to be the older 8-bit processors/MCU like a PIC or AVR that are deterministic. On something like a PIC atomically switching between buffers must be done with care. There is not a way to pull an arbitrary 16-bit pointer out of memory and populate the bank select bits and INDF atomically. The buffers must both either be in the same bank, or same offset in different banks to atomically switch. \$\endgroup\$
    – user4574
    Aug 23 at 17:17
3
\$\begingroup\$

I can't think of any cpu I've used that has a consistent X clocks per instruction. Something like an AVR has most instructions at 1 clock and conditional branches at 2 clocks. Maybe the Propeller or XMOS can do it?

Cortex M ARM can vary significantly, especially as yet get about 30MHz with internal flash as there needs to be wait states, caching or some form of flash accelerator. Get up to the M7 where it can do multiple issue and the execution time of a given instruction depends what other instructions are around it. Cortex A might be 1/2 clock to 1000+ clocks depending on cache hit/miss, page faults etc.

As mentioned in the comments, most micros have an input capture feature for this very reason - it can capture with the resolution of the timer clock. Even the Intel 8052 had it on timer2.

\$\endgroup\$
2
\$\begingroup\$

This should be possible with an ARM9 FIQ handler that is locked into instruction cache.

The FIQ is the last exception defined, so the handler can begin immediately without an extra jump, and it has the second-highest priority (after reset) and will interrupt multi-cycle instructions like ldmia and stmdb, that will be restarted afterwards.

Interrupt entry does not generate memory accesses as the CPU switches to a shadow register bank, and if you can get the instruction fetch timing predictable (by locking the handler, or at least the part at the beginning that needs to be jitter-free, into cache), then I can't think of more jitter sources.

\$\endgroup\$
5
  • \$\begingroup\$ There are two additional sources. If the user disables interrupts to run critical sections then they added jitter to an otherwise deterministic system. Its almost always necessary to do this when writing interrupt safe access to data structures. Also peripherals that might cause the CPU to wait for memory access are another source. \$\endgroup\$
    – user4574
    Aug 21 at 4:36
  • \$\begingroup\$ Yes, that's why there are two interrupts -- so the FIQ could remain active while all other interrupts are disabled. \$\endgroup\$ Aug 21 at 9:24
  • \$\begingroup\$ But wouldn't accessing any data generated by the FIQ interrupt be dangerous unless you disabled that also while accessing it? \$\endgroup\$
    – user4574
    Aug 22 at 2:55
  • 1
    \$\begingroup\$ @user4574, yes, you'd need a lock-free data exchange method, like a ring buffer with pointers that can be atomically read and written. \$\endgroup\$ Aug 22 at 13:00
  • \$\begingroup\$ That's a good point. Swapping datasets with a pointer is a good solution that can be done atomically in a lot of CPUs and opens up a lot of possibilities. Probably not easy to do on older 8 bit processors, but 16 bit or more seems likely. \$\endgroup\$
    – user4574
    Aug 23 at 1:35
2
\$\begingroup\$

Due to different instructions in CPU taking a different number of instruction cycles, whenever a interrupt is triggered it needs to wait until those instruction finish the required cycles (different latency) then push data into the stack and call the INT subroutine. As a result it is not possible to have fixed interrupt latency without hardware help even when using a simple CPU.

\$\endgroup\$
2
\$\begingroup\$
  • there is no clock (clock source) without jitter, so you can not have an mcu without jitter
  • input and output pins in any hardware have a jitter, so your interrupt will have input pin + clock jitter at least
  • yes you can compensate deterministic jitter with adding latency.
  • no, you can not compensate for random jitter
  • jitter always has a deterministic and a non deterministic component.
  • if properly designed, systems can reach relative jitter between components below 1ns (CERN does things like that for example), so jitter is something you need to deal with, but it is possible

Edit:

  • if the mcu has an deterministic architecture (in Order, no caches,... most old Architectures are deterministic), interrupts are deterministic too (there is still jitter from analog circuits!, digital logic is made of analog transistors, so there is jitter to!). But here interrupts are as precise as e.g. a hardware timer, capture compare peripheral,.-..
  • a capture compare peripheral normally is faster, so you can measure e.g. higher frequencies than by using interrupts
  • in industrial automation without an RTOS its totally common to use the timer interrupt + state machines to write deterministic software. In fact that is the best RTOS you can have, because if the interrupt is deterministic, the timing performance is mathematically provable!
\$\endgroup\$
0
\$\begingroup\$

Interrupts and using code to do the measurement is definitely not the way to do this. You use a timer peripheral that does it for you and can be cycle accurate. Or you use a cpld or other chip to do this measurement if this is a hard requirement. But you are barking up the wrong tree if you want to try to do this with interrupts into the processor.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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