This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM335x interrupt latency



Dear Sir,

We are using AM335x microprocessor in one of our project. We are using TI-SDK linux package i.e. ti-sdk-am335x-evm-06.00.00.00 for linux kernel source.

1) Case 1:

We have written a simple kernel driver for having GPIO input pin as interrupt and configured a irq_handler routine for this GPIO pin on signal rising edge. This pulse comes on GPIO input at every 1 second and this pulse is very precise and accurate as it is coming from GPS receiver module.

I am able to get the interrupt routine called on every pulse on this configured GPIO pin as interuupt source. But, the signal latency is too much. I am checking the latency by making another GPIO pin as output "LOW" on every interrupt routine Called. I am checking the latency on CRO by keeping my input pulse on trigger and measuring the duration between input pulse and generated GPIO output pulse.

I found that interrupt latency is around 16 t0 20 microsecods. It seems very high as AM335x processor is running at 720 MHz cpu clock frequency. Again, this latency is not stable though my GPIO input pulse is stable. The interrupt latency varies from 16 us to 25 us randomly. There is only kernel driver running and no user application code running.

Query:
1) Why the interrupt latency is very high as it should be in nanoseconds only if processor is running at 720 MHz ?
2) Why the interrupt latency is not stable at said value, as it varies from 16us to 25us?

2) Case 2:

In similar above case, if i run a simple user application code, there is jump of latency from 20us directly to 65us approx. randomly (please check below image). Also the pulse width of pulse
output have increased significantly as compare to case 1.

As my user application code is very simple blank code, having only while(1) loop in void main(). Please find the attached code.

Why my GPIO output jumps from 20us to 65 us (i.e. interrupt latency) randomly though there is no system calls from user applicaiton code as this jump in case 1.

Query:

1) Why the interrupt latency jumps for such a large value if user application code is running?

All the above readings are taken on calibrated 1 GHz CRO and directly on GPIO bank port pin of AM335x processor.



I will appreciate for any kind of support provided.

Regards,

Ajay

  • Hi Ajay,

    The fact that the MPU is running at 720MHz does not mean that the whole SoC is running at this frequency. GPIOs in particular are located on the L4 inteconnect, which runs at 100MHz. Besides there is an expected latency in the GPIO module itself - see section 25.3.3.2 of the AM335X TRM Rev. K. Also Linux is not a real-time OS, this also adds to the overall latency accumulation.

  • Under operating system, the interrupt is managed by a Mechanism. The interrupt routine are handled by other task. This is Linux 2.6 latency model, FYI. https://www.osadl.org/fileadmin/dam/rtlws/12/Rodriguez.pdf You can try to patch the real time component for kernel . These things for your reference. http://www.osadl.org/Realtime-Linux.projects-realtime-linux.0.html
  • I see similar latency of 25 usec and I'd be interested in ways to reduce it.

    My system is a custom am335x based board running Linux mainline (4.2). The issues are the same when running Linux 3.14 built using the TI AM335x DevKit.

    Signal source is a 1 pulse-per-second timepulse  from two different gps devices fed into two different gpios. From the GPS manufacturer's datasheets, the timepulse accuracy is  well under 100 nsec. I am using a the pps_gpio.ko driver (with some bugfixes), which allocates a interrupt like this:

    /* from drivers/pps/clients/pps-gpio.c */
    
    	/* IRQ setup */
    	ret = gpio_to_irq(data->gpio_pin);
    	if (ret < 0) {
    		dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret);
    		return -EINVAL;
    	}
    	data->irq = ret;
    
    	/* initialize PPS specific parts of the bookkeeping data structure. */
    	data->info.mode = PPS_CAPTUREASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC;
    	if (data->capture_clear)
    		data->info.mode |= PPS_CAPTURECLEAR ;
    	data->info.owner = THIS_MODULE;
    
    
    	/* register PPS source */
    	pps_default_params = PPS_CAPTUREASSERT ;
    	if (data->capture_clear)
    		pps_default_params |= PPS_CAPTURECLEAR;
    	data->pps = pps_register_source(&data->info, pps_default_params);
    	if (data->pps == NULL) {
    		dev_err(&pdev->dev, "failed to register IRQ %d as PPS source\n",
    			data->irq);
    		return -EINVAL;
    	}
    
    	/* register IRQ interrupt handler */
    	ret = devm_request_irq(&pdev->dev, data->irq, pps_gpio_irq_handler,
    			get_irqf_trigger_flags(data), data->info.name, data);
    	if (ret) {
    		pps_unregister_source(data->pps);
    		dev_err(&pdev->dev, "failed to acquire IRQ %d\n", data->irq);
    		return -EINVAL;
    	}
    

    The kernel cannot service the two interrupts at the same time, so one of them is serviced first. By collecting data from  /sys/class/pps/pps0/assert and /sys/class/pps/pps1/assert I can compute the (sysclock) time between the time pulses, which comes out to 24.503 usec +/- 1.804 usec. This is about the same latency as reported by Ajay.

    Perhaps 25 usec latency is "just the way it is" but this seems pretty sluggish to me. That's a ~40 kHz rate; even serial ports work faster than that.

    I do notice that the gpio interrupts are being handled differently from most of the other systems. From /proc/interrupts, most of the peripherals are being handled by the INTC unit. Is there a better way to configure the gpios to get lower interrupt latency?

     

    $cat /proc/interrupts 
                CPU0       
     16:    1301008      INTC  68 Level     gp_timer
     20:       1536      INTC  12 Level     edma
     22:          0      INTC  14 Level     edma_error
     28:      12615  44e07000.gpio   4 Edge      ublox_lea4H
     86:          0  4804c000.gpio  29 Edge      48060000.mmc cd
    114:      12475  481ac000.gpio  24 Edge      ublox_max7
    155:       6475      INTC  72 Level     OMAP UART0
    156:       7224      INTC  73 Level   
    157:     288000      INTC  45 Level     OMAP UART4
    158:        343      INTC  70 Level     44e0b000.i2c
    159:          0      INTC  30 Level     4819c000.i2c
    160:       6440      INTC  64 Level     mmc0
    161:         51      INTC  28 Level     mmc1
    172:      44348      INTC  41 Level     4a100000.ethernet
    173:      15093      INTC  42 Level     4a100000.ethernet
    175:          0      INTC  16 Level     TI-am335x-adc
    176:          0      INTC 109 Level     53100000.sham
    180:          1      INTC 111 Level     48310000.rng
    181:          8      INTC  18 Level     musb-hdrc.0.auto
    182:         31      INTC  19 Level     musb-hdrc.1.auto
    183:          0      INTC  17 Level     47400000.dma-controller

  • Possibly debounce registers are being set incorrectly in gpio-omap.c, see lkml.org/.../163 .
  • Aren't you confusing latency and throughput in your comparison to serial ports?  UARTs can have high throughput but their latency will be the same as anything else that is interrupt driven, if not worse.

    The AM335x is not a microcontroller.  To achieve the low-latency that you can expect from microcontrollers you need to apply the real-time patch to your kernel:

    https://rt.wiki.kernel.org/index.php/Main_Page

    and make use of the PRU (the purpose of which is to provide low-latency processing).