Software Triggered Interrupt

Hello,

I need your assistance, I need to measure the interrupt latency of QNX on my development board. To be more precise, I need to measure the time from triggering the interrupt until a thread receives the event. So it is necessary for me to trigger the interrupt by software. I saw a thread on this forum where someone implemented almost the functionality I need:
openqnx.com/phpbbforum/viewt … upt#p42931

But when i try to use this code i get a Bus error:
terminated SIGBUS code=3 fltno=5 ip=080499bc(/dev/shmem/./testit@_btext+0xb84) ref=2800037a

I explain the occurrence of this error by the fact that my development board doesn’t have a parallel port.

My question is: Which interrupt should i use to measure the Interrupt latency? Which interrupt is able to be triggered by software? Is is possible to use a SGI(Software Generated Interrupt (ARM Cortex-A9))? If yes, how can i trigger a SGI?

My environment:
Freescale Sabre Lite Board boundarydevices.com/products/sab … -imx6-sbc/
QNX 6.6.0
QNX 6.6.0 BSP for Sabre Lite community.qnx.com/sf/wiki/do/vie … QSabreLite

Thank in advance!

SIGBUS on arm is caused by misalignement or access of non existant memory.

The following records ClockCycles() at time of interrupt and at time thread runs. By subtracting the two ClockCycle() values you get the scheduling latency.

You will have to figure out what the real meaning of the difference is using…
(~(uint64_t)0) / SYSPAGE_ENTRY(qtime)->cycles_per_sec

Also note, that in some architectures you must lock the isr and thread to the same core - otherwise the timer values may be meaningless. See the ClockCycles() doc.

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <pthread.h>

/*
timint.c

A handler is attached to the timer interrupt.  main() will wait at InterruptWait()
to be awakened by the handler.  Every MAX_COUNT ticks, a thread is awakened.

*/

#define TRUE 1
#define FALSE 0
#define HIGH_PRIO 250
#define MAX_COUNT 1000

// globals
int iid;
struct sigevent int_event; /* the SIGEV_INTR event used to awaken InterruptWait() */
unsigned intThrdCount = 0;
unsigned TIMER_INTERRUPT;
unsigned long long t0, t1;

/* handler isr_tmr **********************************************************/
// param passed is NULL, id passed is value iid
const struct sigevent *isr_tmr( void *param, int id )
{
// if necessary, reset intThrdCound
if ( intThrdCount == 0 )
intThrdCount = MAX_COUNT;

// time for thread?
if (  --intThrdCount == 0 )
{
    // thread will be scheduled to run on non-NULL return!
    // get current time
    t0 = ClockCycles();
    return &int_event;
}else
    return NULL;

} /* isr_tmr */

/*************************************************************************/

int main(int argc, char **argv)
{
struct _clockperiod curclk;
int rc;

// bump priority for scheduling the thread event
rc = setprio( 0, HIGH_PRIO );
if ( rc == -1 )
    printf( "priority not set %d\n", errno );

// enable i/o privilege for attaching to interrupt
ThreadCtl( _NTO_TCTL_IO, 0 );

// setup for starting a thread at random times to current context
SIGEV_INTR_INIT(&int_event);

// get timer interrupt number
TIMER_INTERRUPT = SYSPAGE_ENTRY(qtime)->intr;

// attach isr_tmr to TIMER_INTERRUPT
if ( iid = InterruptAttach( TIMER_INTERRUPT, isr_tmr,
                            NULL, 0, _NTO_INTR_FLAGS_TRK_MSK ) != -1 )
{
	while ( TRUE )
	{
	    // wait to be notified bi isr_timr
	    InterruptWait( 0, NULL );
        t1 = ClockCycles();
        printf( "intr-to-thread latency %lld\n", t1 - t0 );
	}
}
return 0;

}

That is almost exactly what i need, and i can use this code nearly unmodified for my work, thank you denkelly!

However, i am still curious how it would be possible to trigger an interrupt by software and how a SGI (Software generated interrupt) can be used to solve this problem. Can you give me a hint where to start reading if i want to use such a SGI or other software trigger-able interrupt?

Thanks in advance!

Ps: Like this one, but working on my ARM:

for ( i = 0 ; i <= (NUM_MEASURE+1) ; i++)
{
out8( pptDataHdl , LOW ); /* send LOW bit on PPT1 /
out8( pptDataHdl , HIGH ); /
send HIGH bit on PPT1 /
ui64_cc_start = ClockCycles(); /
get the current system clockcycles /
delay(30); /
delay in milli seconds /
out8( pptDataHdl , LOW ); /
send LOW bit on PPT1 /
delay(200); /
delay in milli seconds */
}
Seen in openqnx.com/phpbbforum/viewt … upt#p42931

Your request is a little ambiguous and maybe doesn’t quite make sense, specifically the part about triggering a hardware interrupt via software. There are two things you might mean.

  1. Use software somehow to trigger a hardware interrupt.
    By this I mean, run a software statement, such as an outb to change a hardware line which feeds into a hardware interrupt line.
    This would be fairly easy to do with an old parallel port by wiring a control line into the interrupt line and then toggling the control line.

  2. Fire a hardware ISR using the software INT instruction. This is not really an Interrupt at all in the usual sense. Nothing is really interrupted. Your program synchronously transfers control to another piece of software which usually returns.

It might also be useful to know what latency you are trying to measure. There is a hardware latency between the time the interrupt controller chip detects the change in interrupt line voltage and when the processor transfers control to the ISR. Among other things, the involves pushing various registers into the stack. This is complicated with QNX 6 since your interrupt handler is not the real ISR. Instead, you registered your handler with the OS and it calls your routine from the real ISR. Further complicating this matter is that multiple handlers can attach to the same interrupt. Yours might not be the first one called.

The other latency you might be interested in is the time between your handler exiting and an application thread getting control. This amount of time can vary wildly since a higher priority thread can interfere. Having multiple processors can also complicate the matter in various ways. However this is the only type of latency that you can measure purely in software. If that is what you are trying to measure, you might consider using the Timer interrupt for testing.

You can trigger a hardware interrupt by software by putting a loopback plug on a comport. Set the uart to interrupt on DSR and trigger it in software by raising DTR.

If you read ClockCycles() just before you raise DTR, then you can read it again at the start of the ISR, measuring hw interrupt latency. In the ISR, schedule a thread to run (as in the example post) and read ClockCycles() first thing in the thread. Now you have both the h/w latency and the thread latency.

At first thank you for your answers.

According to your replies, I connected two GPIO pins on my board, and configured one as input and the one as output.

With that, I think my problem is solved.