Timer Interrupt

Hi,

I would appreciate if anyone can help with the following issue:

I have to use Timer interrupt for writing one of the software routine.Can
anyone suggest me how to iniialise the timer interrupt routine in Qnx 6.2
and
a sample code will greatly helpful to me. A pointer to various function
calls
used for the timer routine will be greatly helpful.

Tx inadvance,
Mankan

Mankan <smankan@nospam.ueidaq.com> wrote:

Hi,

I would appreciate if anyone can help with the following issue:

I have to use Timer interrupt for writing one of the software routine.Can
anyone suggest me how to iniialise the timer interrupt routine in Qnx 6.2
and
a sample code will greatly helpful to me. A pointer to various function
calls
used for the timer routine will be greatly helpful.

First question – do you actually need a timer INTERRUPT, or do you
just need to do something at a regular interval?

If you just need regular or repeated notification, then I would
strongly suggest not dealing with interrupts at all, but instead use
the POSIX timer routines: timer_create() and timer_settime(). You
can get regular notification using either a signal or a pulse.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Hi David,

Thanks for the reply and suggestion…we are just trying to get
notification within 50 micro secs
and i don’t know whether notification using signals or pulse will be faster
enough or Timer interrupt.

We would like to test both the features viz timer interrupt as well as
repeated notification using
pulse.

If you can give some pointers how to implement timer interrupts that will be
great help.

Thx inadvance,
Mankan



“David Gibbs” <dagibbs@qnx.com> wrote in message
news:b4ibng$1u1$4@nntp.qnx.com

Mankan <> smankan@nospam.ueidaq.com> > wrote:
Hi,

I would appreciate if anyone can help with the following issue:

I have to use Timer interrupt for writing one of the software
routine.Can
anyone suggest me how to iniialise the timer interrupt routine in Qnx
6.2
and
a sample code will greatly helpful to me. A pointer to various function
calls
used for the timer routine will be greatly helpful.

First question – do you actually need a timer INTERRUPT, or do you
just need to do something at a regular interval?

If you just need regular or repeated notification, then I would
strongly suggest not dealing with interrupts at all, but instead use
the POSIX timer routines: timer_create() and timer_settime(). You
can get regular notification using either a signal or a pulse.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Mankan <smankan@nospam.ueidaq.com> wrote:

Hi David,

Thanks for the reply and suggestion…we are just trying to get
notification within 50 micro secs
and i don’t know whether notification using signals or pulse will be faster
enough or Timer interrupt.

50 micro seconds is more difficult. Be default, we set the system
timer interrupt to be 1 milisecond (or 10ms on slow machines).

In general, taking this interrupt period down to the 50 microsecond
range is going to impose a fair bit of overhead (time update, timer
chain, etc) on the system.

This clock resolution can be modified with the ClockPeriod() function.

If you do this, whether you get your notification from the timer
chain, or directly from an ISR won’t make a lot of difference.

But, as I said, taking your clock resolution down that low will
have a fair bit of overhead, that you may not want.

So, I go back to my original question – what are you trying to
do/achieve? You say you want notification within 50 microseconds,
do you mean that you need regular notification every 50 microseconds?
Do you mean that you need to start some operation, and then check for
a result in 50 microseconds? Do you mean that you have to start some
operation, and if it hasn’t completed in 50 microseconds, you have to
abort it? How often do you need to do this? Can you afford to burn
CPU time to achieve this delay? And, what sort of hardware is available?

For instance, on a generic x86 box, there are usually 3 hardware
timers availabe, we use timer 0 for system time, timer 2 is, I think,
usually used for getting tones from the PC speaker, but timer 1 is
not used. You could use timer 1 for your work – but there is no
OS API for setting it up, you’d have to get a hardware book and read
the control registers, modify them for a timeout and specify what
interrupt then write them back, making sure to not modify anything
that would affect timer 0. But, if you’re not working on x86, this
wouldn’t help you – though you might find some other hardware on your
board that might have similiar capabilities.

Also, if you can afford to burn CPU waiting, the nanospin() function
and its set can be used to busy-wait for short delay periods.

I don’t know what of these might be best – of if any of them will
help at all.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

In article <b4iogk$adl$1@nntp.qnx.com>, dagibbs@qnx.com says…

For instance, on a generic x86 box, there are usually 3 hardware
timers availabe, we use timer 0 for system time, timer 2 is, I think,
usually used for getting tones from the PC speaker, but timer 1 is
not used.

Timer 1 was used for memory refresh purposes years ago. It’s also marked as “Refresh Request Signal”
in PIIX4 datasheet, so I believe it is not changed yet. Correct me if I’m wrong. And RTC chip can
generate IRQ 8, but min period is 122.070 uS (freq.=8192Hz). I believe external timer card can do
the trick. 50 uS you can get just by deviding PCICLK or SYSCLK, for example.

Eduard.

ed1k <ed1k@humber.bay> wrote:

In article <b4iogk$adl$> 1@nntp.qnx.com> >, > dagibbs@qnx.com > says…
For instance, on a generic x86 box, there are usually 3 hardware
timers availabe, we use timer 0 for system time, timer 2 is, I think,
usually used for getting tones from the PC speaker, but timer 1 is
not used.

Timer 1 was used for memory refresh purposes years ago. It’s also
marked as “Refresh Request Signal” in PIIX4 datasheet, so I believe
it is not changed yet.

You could be right. I just remember having a customer reprogramming
this many moons ago, and thinking that it was an “available” timer
at this time. (It was a tech support issue cause the customer was
setting the 2 bits they wanted in variable, then writing that to the
control register, and thereby disabling timer 0 and then claiming that
QNX (4.xx) was broken cause time stopped when they did that. Doh.)

But, my little XT/AT reference (yes, its old) says Refresh as well.

Maybe timer2 – if you don’t need the PC speaker – would be better.

Correct me if I’m wrong. And RTC chip can generate IRQ 8, but min
period is 122.070 uS (freq.=8192Hz).

Yeah, I think it can – but I’ve never looked at using it.

I believe external timer card can do the trick.

Yes, an external timer card is a good way to go for something like
this as well.

50 uS you can get just by deviding PCICLK or SYSCLK, for example.

Hm… yeah, but I don’t think you can get an irq from them – so
that also would be a busy-wait type of thing.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Regarding the use of ClockPeriod(), David, I have often seen you warn
ominously about the overhead associated with cranking up the resolution, but
when I take it right up to 10 microseconds (really ~9219 nanoseconds because
you can only put integers into that decrement counter in the timer chip) on
a 333MHz Pentium II, the desktop shelf System Monitor’s CPU display seems to
be showing only around 5% overhead, if that. Neutrino really does handle
timer interrupts quite efficiently, even 100K of them per second! :slight_smile:

dB

David Gibbs <dagibbs@qnx.com> wrote in message
news:b4l0qj$otq$1@nntp.qnx.com

ed1k <> ed1k@humber.bay> > wrote:
In article <b4iogk$adl$> 1@nntp.qnx.com> >, > dagibbs@qnx.com > says…
For instance, on a generic x86 box, there are usually 3 hardware
timers availabe, we use timer 0 for system time, timer 2 is, I think,
usually used for getting tones from the PC speaker, but timer 1 is
not used.

Timer 1 was used for memory refresh purposes years ago. It’s also
marked as “Refresh Request Signal” in PIIX4 datasheet, so I believe
it is not changed yet.

You could be right. I just remember having a customer reprogramming
this many moons ago, and thinking that it was an “available” timer
at this time. (It was a tech support issue cause the customer was
setting the 2 bits they wanted in variable, then writing that to the
control register, and thereby disabling timer 0 and then claiming that
QNX (4.xx) was broken cause time stopped when they did that. Doh.)

But, my little XT/AT reference (yes, its old) says Refresh as well.

Maybe timer2 – if you don’t need the PC speaker – would be better.

Correct me if I’m wrong. And RTC chip can generate IRQ 8, but min
period is 122.070 uS (freq.=8192Hz).

Yeah, I think it can – but I’ve never looked at using it.

I believe external timer card can do the trick.

Yes, an external timer card is a good way to go for something like
this as well.

50 uS you can get just by deviding PCICLK or SYSCLK, for example.

Hm… yeah, but I don’t think you can get an irq from them – so
that also would be a busy-wait type of thing.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Bacon <dbacon@qnx.com> wrote:

Regarding the use of ClockPeriod(), David, I have often seen you warn
ominously about the overhead associated with cranking up the resolution, but
when I take it right up to 10 microseconds (really ~9219 nanoseconds because
you can only put integers into that decrement counter in the timer chip) on
a 333MHz Pentium II, the desktop shelf System Monitor’s CPU display seems to
be showing only around 5% overhead, if that. Neutrino really does handle
timer interrupts quite efficiently, even 100K of them per second! > :slight_smile:

The issue isn’t, so much, in an idle system – it is when you start
doing things.

It now, means, that say you start a calculation that would take 1s to
complete. If you had a ticksize of 1ms – that would get interrupted
1000 times, with 1000 switches into kernel space, and back out again.

If you take that ticksize down to 10 microseconds, you are now getting
interrupted 100,000 times – this means 100x as many context switches
etc.

For instance, I have a little s/r/r test program, it does a bunch
of 4K Send & 4K replies, then figures out how many clock cycles it
took to complete.

With a ticksize of 1ms – I get a ipc cost of 4850 clock cycles
(850 Mhz Pentium 3). If I take the ticksize down to 10 microseconds,
I get an ipc cost of 6140 clock cycles. That’s a little over 26%
worse.

If I do 0 length S/R/R, the numbers I get are 1950 and 2440 –
again about 25% cost.

I would consider 25% a significant overhead, which is why I warn
about the cost of doing this.

Of course, using some other interrupt at this frequency will
impose similar overhead – but if it can be used more flexibly,
e.g. only set it to interrupt once, 50 microseconds after needed,
then disable; then re-enable next time – that could significantly
reduce the interrupt overhead.

Still, choosing an interrupt where we don’t do any work
(e.g. updating time, checking the timer chain) will also
reduce the overhead at each interrupt.

-David

P.S. My S/R/R test program:

/*

  • sendrec.c

*/

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

void *worker( void * );

#define NUM_LOOP 100000

int chid; /* the channel id that the server will receive on */
char device; / the device that the worker thread will read from */
char *progname = “sendrec”;
char buf[4096];

int
main( int argc, char **argv )
{
message_t msg;
reply_t reply;
int rcvid;

// printf(“setprio returned %d\n”, setprio(0,62));

chid = ChannelCreate( 0 );
if ( chid == -1 ) {
printf( “%s: (server) couldn’t create a channel: %s\n”,
progname, strerror(errno) );
exit( EXIT_FAILURE );
}

if (!fork()) worker(NULL);

while (1) {
rcvid = MsgReceive(chid, buf, 4096, NULL );

MsgReply( rcvid, 0, buf, 4096 );
}


return 0;
}

void *
worker( void *unused )
{
int coid;
int ret;
int i;
uint64_t before, after;
uint64_t loop_delta, ipc_delta;
uint64_t ipc_cost;

coid = ConnectAttach( 0, getppid(), chid, _NTO_SIDE_CHANNEL, 0 );

before = ClockCycles();
for(i = 0; i<NUM_LOOP; i++);
after = ClockCycles();
loop_delta = after - before;

before = ClockCycles();
for(i = 0; i<NUM_LOOP; i++)
{
ret = MsgSend( coid, buf, 4096, buf, 4096 );
}
after = ClockCycles();
ipc_delta = after - before;

printf(“loop_delta: %lld, ipc_delta: %lld\n”, loop_delta, ipc_delta );
ipc_cost = (ipc_delta-loop_delta)/NUM_LOOP;
printf(“ipc overhead = %lld\n”, ipc_cost );
printf(“cycles/sec is %lld\n”, SYSPAGE_ENTRY( qtime )->cycles_per_sec );
kill(getppid(), SIGTERM );
exit(0);
return( NULL );
}

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Indeed, and on my 333MHz Pentium II, taking the timer interrupt frequency up
to 100KHz causes the time taken by your program’s IPC loop to increase by
about 70% (from a little over 1.8 sec to about 3.2 sec). Even the CPU loop
takes about 60% longer. Nice demo!

dB

David Gibbs <dagibbs@qnx.com> wrote in message
news:b4l4q1$rb1$1@nntp.qnx.com

David Bacon <> dbacon@qnx.com> > wrote:
Regarding the use of ClockPeriod(), David, I have often seen you warn
ominously about the overhead associated with cranking up the resolution,
but
when I take it right up to 10 microseconds (really ~9219 nanoseconds
because
you can only put integers into that decrement counter in the timer chip)
on
a 333MHz Pentium II, the desktop shelf System Monitor’s CPU display
seems to
be showing only around 5% overhead, if that. Neutrino really does
handle
timer interrupts quite efficiently, even 100K of them per second! > :slight_smile:

The issue isn’t, so much, in an idle system – it is when you start
doing things.

It now, means, that say you start a calculation that would take 1s to
complete. If you had a ticksize of 1ms – that would get interrupted
1000 times, with 1000 switches into kernel space, and back out again.

If you take that ticksize down to 10 microseconds, you are now getting
interrupted 100,000 times – this means 100x as many context switches
etc.

For instance, I have a little s/r/r test program, it does a bunch
of 4K Send & 4K replies, then figures out how many clock cycles it
took to complete.

With a ticksize of 1ms – I get a ipc cost of 4850 clock cycles
(850 Mhz Pentium 3). If I take the ticksize down to 10 microseconds,
I get an ipc cost of 6140 clock cycles. That’s a little over 26%
worse.

If I do 0 length S/R/R, the numbers I get are 1950 and 2440 –
again about 25% cost.

I would consider 25% a significant overhead, which is why I warn
about the cost of doing this.

Of course, using some other interrupt at this frequency will
impose similar overhead – but if it can be used more flexibly,
e.g. only set it to interrupt once, 50 microseconds after needed,
then disable; then re-enable next time – that could significantly
reduce the interrupt overhead.

Still, choosing an interrupt where we don’t do any work
(e.g. updating time, checking the timer chain) will also
reduce the overhead at each interrupt.

-David

P.S. My S/R/R test program:

/*

  • sendrec.c

*/

#include <errno.h
#include <fcntl.h
#include <stdio.h
#include <stdlib.h
#include <pthread.h
#include <unistd.h
#include <sched.h
#include <ctype.h
#include <stdint.h
#include <sys/neutrino.h
#include <sys/stat.h
#include <sys/syspage.h

void *worker( void * );

#define NUM_LOOP 100000

int chid; /* the channel id that the server will receive on
*/
char device; / the device that the worker thread will read
from */
char *progname = “sendrec”;
char buf[4096];

int
main( int argc, char **argv )
{
message_t msg;
reply_t reply;
int rcvid;

// printf(“setprio returned %d\n”, setprio(0,62));

chid = ChannelCreate( 0 );
if ( chid == -1 ) {
printf( “%s: (server) couldn’t create a channel: %s\n”,
progname, strerror(errno) );
exit( EXIT_FAILURE );
}

if (!fork()) worker(NULL);

while (1) {
rcvid = MsgReceive(chid, buf, 4096, NULL );

MsgReply( rcvid, 0, buf, 4096 );
}


return 0;
}

void *
worker( void *unused )
{
int coid;
int ret;
int i;
uint64_t before, after;
uint64_t loop_delta, ipc_delta;
uint64_t ipc_cost;

coid = ConnectAttach( 0, getppid(), chid, _NTO_SIDE_CHANNEL, 0 );

before = ClockCycles();
for(i = 0; i<NUM_LOOP; i++);
after = ClockCycles();
loop_delta = after - before;

before = ClockCycles();
for(i = 0; i<NUM_LOOP; i++)
{
ret = MsgSend( coid, buf, 4096, buf, 4096 );
}
after = ClockCycles();
ipc_delta = after - before;

printf(“loop_delta: %lld, ipc_delta: %lld\n”, loop_delta, ipc_delta );
ipc_cost = (ipc_delta-loop_delta)/NUM_LOOP;
printf(“ipc overhead = %lld\n”, ipc_cost );
printf(“cycles/sec is %lld\n”, SYSPAGE_ENTRY( qtime )->cycles_per_sec );
kill(getppid(), SIGTERM );
exit(0);
return( NULL );
}

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

In article <b4l0qj$otq$1@nntp.qnx.com>, dagibbs@qnx.com says…

But, my little XT/AT reference (yes, its old) says Refresh as well.

Maybe timer2 – if you don’t need the PC speaker – would be better.

The problem is, I believe, that you can’t use it in a way to generate interrupt. Neither of them,
nor timer1 nor timer2, don’t connected to interrupt controller.

Correct me if I’m wrong. And RTC chip can generate IRQ 8, but min
period is 122.070 uS (freq.=8192Hz).

Yeah, I think it can – but I’ve never looked at using it.

As I told the min period is 122.07 uS that doesn’t feet into requirments of 50 uS. But this is a
great piece of hardware almost never used in x86 (well, developers of RTD Enhanced Award BIOS use it
for power management - you can setup time to wakeup your Geode). I wrote article on using RTC, but
it’s in Russian and I have no time nor mood to translate it to English. But you can look at
demonstration program for this article (mostly it’s in C :slight_smile:), if you’re interested:

ftp://ftp.qnx.org.ru/projects/ed1k/clock.tgz

I believe external timer card can do the trick.

Yes, an external timer card is a good way to go for something like
this as well.

50 uS you can get just by deviding PCICLK or SYSCLK, for example.

Hm… yeah, but I don’t think you can get an irq from them – so
that also would be a busy-wait type of thing.

I meant some hardware card. Just riding of quartz oscilator to make it cheap :slight_smile: Yes, it’s an hours’
hardware design… You need some counter to divide system clock, some RS trigger to set interrupt
request, and some logic to decode a couple of address lines and I/O signal to reset this trigger in
interrupt handler.

I believe, there is something wrong with system design, if there is such requirement of 50 uS
notifications (interrupts). But without knowing details I only can say how to bake nice brick for,
might be, completely wrong designed wall.

Eduard.

-David