Interrupt handling time

Is there a large minimum handling time for GPIO based interrupts on the beaglebone under Linux? I’ve spent the day writing a platform driver in the kernel to handle the motor controller in my robot. One of the things disturbing me though is that I have high accuracy encoders. They generate 960 interrupts per revolution. I’ve got the interrupts firing on both rising and falling edge, so this gives me 1920 ticks per revolution. I’m trying to handle these in the kernel with interrupt handlers instead of having an external microcontroller. I’ve got the interrupts working but many of them seem to drop. The interrupt handler itself is very light weight, its here as follows:

// Encoder channel A IRQ
static irqreturn_t beaglebot_motor_cha_irq_handler(int irq, void *dev_id)
{
// Get the instance information
struct platform_device *pdev = dev_id;
struct beaglebot_motor *motor = platform_get_drvdata(pdev);

// Get the two GPIO pins
if(gpio_get_value(motor->encoder_chA) ^ gpio_get_value(motor->encoder_chB))
{
atomic64_inc(&motor->ticks);
} else
{
atomic64_dec(&motor->ticks);
}

// Return that the IRQ was handled successfully
return IRQ_HANDLED;
}

I seem to loose most of the interrupts when the motor is rotating at 1 rotation per second (1920 interrupts generated per second). I would have figured that a big 720 MHz arm chip could handle some encoder interrupts because an arduino can do PID control on these motors, which is what I am trying to achieve with my platform driver.

Nathaniel Lewis

Hello

I’m a newbee in this area but this seems to me the right job for the PRUSS devices present inside the SOC.
There are 2 engines available running at 200Mhz that can be programmed in a user friendly assembler.
Communication with the ARM can be done for example via shared memory.

You could implement a polling loop on one of the 2 devices and increment a counter in shared memory.
A small driver, either in the kernel or even in user land, can read to counters and makes them available to your application.
Implemented in this way the processing power on the ARM can be used for other puposes.

Best regards,
Ronny

Is there a large minimum handling time for GPIO based interrupts on the
beaglebone under Linux? I've spent the day writing a platform driver in the
kernel to handle the motor controller in my robot. One of the things
disturbing me though is that I have high accuracy encoders. They generate
960 interrupts per revolution. I've got the interrupts firing on both
rising and falling edge,

My take:
I think the problem happens when you are dealing with Edge triggered interrupts.
Level based interrupts are good in that sense, that they dont get
cleared till its handled, and the new one does not arise till then.

Is there a way to reconfigure your hw to generate level interrupts?

AM35xx processor experts can comment on how good Linux is to handle
edge triggered interrupts.
But as you can see, that is going to be a problem.

As I understand it, the PRUSS devices are essentially arm cortex-m3/4 processors embedded into the SoC? Can they handle GPIO interrupts or would I be required to actually do a polling loop on my encoders? Can they tie into any GPIO pins on the SoC? As far as shared memory goes, it that the process allocating memory in its space and passing a pointer or are there utilities setup to help with that?

Nathaniel Lewis

As I understand it, the PRUSS devices are essentially arm cortex-m3/4 processors embedded into the SoC?

It are indeed 2 processors in the soc. I do not know whether it are cortex-m3/4 processors.
You can find a detailed document here: https://github.com/beagleboard/am335x_pru_package/blob/master/am335xPruReferenceGuide.pdf?raw=true

Can they handle GPIO interrupts or would I be required to actually do a polling loop on my encoders?

I would write a simple polling loop. Basically more or less the same code as you perform in the interrupt handler.

Can they tie into any GPIO pins on the SoC?

Since it can access the complete memory map I would assume that it can indeed access all pins, but as said before I’m a newbie too.
This is a nice starting page: http://blog.boxysean.com/2012/08/12/first-steps-with-the-beaglebone-pru/

As far as shared memory goes, it that the process allocating memory in its space and passing a pointer or are there utilities setup to help with that?

You can simply put the counters in the PRUSS’ internal memory which can be accessed from your application by using the UIO driver framework.

Ronny