Fast interrupt handler

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
Posts: 3
Joined: Fri Jan 04, 2019 7:03 pm

Fast interrupt handler

Post by Samuel97 » Fri Aug 16, 2019 3:16 pm

Hi, I'm trying to caught pulses from multiple sensors, every sensor is conected to separated pin of pyboard. Problem is that time difference of arrive between sensonrs is some times around 10us ( I measured it with scope). I need to save arrive time of pulse, so I write this callback, but for pyboard it takes 21us to proceed, (I shorted two pins, send them pulse, and measure time difference). Is there any way how to measured and save time faster?

tim = [0, 0, 0, 0]

def callback1(l):
global tim
tim[0] = pyb.micros()

User avatar
Posts: 4173
Joined: Fri Jul 18, 2014 8:01 am
Location: UK

Re: Fast interrupt handler

Post by pythoncoder » Sat Aug 17, 2019 8:43 am

I think you're running close to the limits of Pyboard timing. There are things you could try, but I suspect the improvements may be marginal or non-existent.

One thought is to make the ISR a method. You could then save the time in a bound variable rather than in an element of a global list. This might enable the ISR to terminate more quickly, reducing the latency for the next interrupt. Global access is slow, and performing the list indexing must take some time. Updating a bound integer might be faster.

Another thought would be to update the global list using micropython.schedule. But it could be that the call to that function takes as long as updating the list directly.

The ultimate solution would be to write the ISR as a C module or using the inline assembler. You'd need to study the MicroPython source to figure that one out :)
Peter Hinch

User avatar
Posts: 1963
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Fast interrupt handler

Post by Roberthh » Sat Aug 17, 2019 9:51 am

In another context (the ssd1963 driver) I made tests, how much time a function call needs on a pyboard:
Observations about code speed

It may be intersting, to tell the time micopython needs to call a function. The table below gives an estimate. An empty function was called with zero to four arguments, each supplied as a constant. The function body was pass or nop(). Each function was called 10.000 times. The time for the loop was determined before and subtracted. The time unit is µs.

Code: Select all

Code type	0	1	2	3	4
Assembler	3.3	3.6	4.0	4.4	4.7
Viper		3.3	3.6	4.0	4.4	4.7
Python		6.5	6.7	7.0	7.3	7.5
As an example: the function setXY(), coded in assembler, needs 0.9 µs for the execution of the function body, but calling it and returning needs at least additional 4.7 µs. In a real coding situation, observed 6 µs. The function drawPixel(), when used to fill the whole screen, takes 9 µs for a call, in contrast to about 1µs the net function body takes for it's task. Comparing the same job implemented in Viper or Assembler code, the Viper code is about twice as long and therefore takes about twice the time. But it is easier to read & write. Thus, I typically implemented the Viper version first, and then translated the simple ones into Assembler.

Posts: 3
Joined: Fri Jan 04, 2019 7:03 pm

Re: Fast interrupt handler

Post by Samuel97 » Sat Aug 17, 2019 10:17 am

By using time.ticks_us(), and separated variable insted of list I improve processed time to 17µs. I would like to try write callback in assembler, but how can I call micros(), or in which register is stored it value? Or is there any register where I can store value without accessing to global?

Post Reply