SIGEV_INTR and timers

I want to create a timer that generates a SIGEV_INTR every millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

SIGEV_INTR_INIT( &TimerEvent);
timer_create( CLOCK_REALTIME, &TimerEvent, &hTimer);
ITime.it_value.tv_sec = 0;
ITime.it_value.tv_nsec = 1000000;
ITime.it_interval.tv_sec = ITime.it_value.tv_sec;
ITime.it_interval.tv_nsec = ITime.it_value.tv_nsec;
timer_settime( hTimer, 0, &ITime, NULL);
InterruptAttachEvent( …); // (1)
for(;:wink: {
InterruptWait( 0, NULL);
InterruptDisable(); // (2)
// do time sensitive stuff here
InterruptUnmask(); // (3)
InterruptEnable();
}

My question is:
(1) Is a call to IntterruptAttachEvent() necessary, or does timer_*()
replace this?
(2) Do I need to disable interrupts manually, or is this already done?
(3) Do I need to unmask an interrupt? Which one?
Lastly, does the SIGEV_INTR get sent to the thread that called
timer_create() and timer_settime()?

Thanks,
Shaun

Hey Shaun,

can’t you make the timer to generate a pulse and works with it?
I used to have a situation like yours and for me, i replace the
interrupt-timer-generate to timer-pulse notification scheme…
It’s working well…

Bye,
Leandro

“Shaun Jackman” <sjackman@nospam.vortek.com> escreveu na mensagem
news:ai48i2$kpe$1@inn.qnx.com

I want to create a timer that generates a SIGEV_INTR every millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

SIGEV_INTR_INIT( &TimerEvent);
timer_create( CLOCK_REALTIME, &TimerEvent, &hTimer);
ITime.it_value.tv_sec = 0;
ITime.it_value.tv_nsec = 1000000;
ITime.it_interval.tv_sec = ITime.it_value.tv_sec;
ITime.it_interval.tv_nsec = ITime.it_value.tv_nsec;
timer_settime( hTimer, 0, &ITime, NULL);
InterruptAttachEvent( …); // (1)
for(;:wink: {
InterruptWait( 0, NULL);
InterruptDisable(); // (2)
// do time sensitive stuff here
InterruptUnmask(); // (3)
InterruptEnable();
}

My question is:
(1) Is a call to IntterruptAttachEvent() necessary, or does timer_*()
replace this?
(2) Do I need to disable interrupts manually, or is this already done?
(3) Do I need to unmask an interrupt? Which one?
Lastly, does the SIGEV_INTR get sent to the thread that called
timer_create() and timer_settime()?

Thanks,
Shaun

Funnily enough, I’m actually going the opposite way. I had it generating a
pulse first. I measured the jitter on the MsgReceive() though, and it was in
the tens of micro-seconds on a one milli-second timer (on a PIII/750) ,
which for my application is too much. I think the timing sensitivity
requires that it be as high-priority as interrupt handlers, so I thought
SIGEV_INTR might do the trick for me. I’ve got it working in a
single-threaded test app, but I’ve yet to make it work within io-net (my
final goal). If I can’t get this to go, I’ll try to InterruptAttach() the
hardware timer interrupt (the clock is running at 1ms).

To answer my own questions (correctly I hope):
(1) not necessary
(2) yes you need to disable interrupts, no this is not already done
(3) no
(lastly) beats me. Anyone else?

Thanks,
Shaun


Leandro Colen <lcrocha@yahoo.com> wrote in message
news:ai4cks$nbn$1@inn.qnx.com

Hey Shaun,

can’t you make the timer to generate a pulse and works with it?
I used to have a situation like yours and for me, i replace the
interrupt-timer-generate to timer-pulse notification scheme…
It’s working well…

Bye,
Leandro

“Shaun Jackman” <> sjackman@nospam.vortek.com> > escreveu na mensagem
news:ai48i2$kpe$> 1@inn.qnx.com> …
I want to create a timer that generates a SIGEV_INTR every millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

SIGEV_INTR_INIT( &TimerEvent);
timer_create( CLOCK_REALTIME, &TimerEvent, &hTimer);
ITime.it_value.tv_sec = 0;
ITime.it_value.tv_nsec = 1000000;
ITime.it_interval.tv_sec = ITime.it_value.tv_sec;
ITime.it_interval.tv_nsec = ITime.it_value.tv_nsec;
timer_settime( hTimer, 0, &ITime, NULL);
InterruptAttachEvent( …); // (1)
for(;:wink: {
InterruptWait( 0, NULL);
InterruptDisable(); // (2)
// do time sensitive stuff here
InterruptUnmask(); // (3)
InterruptEnable();
}

My question is:
(1) Is a call to IntterruptAttachEvent() necessary, or does
timer_*()
replace this?
(2) Do I need to disable interrupts manually, or is this already
done?
(3) Do I need to unmask an interrupt? Which one?
Lastly, does the SIGEV_INTR get sent to the thread that called
timer_create() and timer_settime()?

Thanks,
Shaun

You boost-up your thread priority?
you can configure the priority of the pulse as well to…
Maybe this jitter may caused by priority on the timer thread and if you
won’t boost-up you will continue with the difference.

Assuming that you have set the priority and still have the problem, think of
using a hardware-generate clock tick (like an PIC or an ALTERA), an then use
Interrupt*() functions. That’s what i use in my lab…

Sorry if i can’t help… :slight_smile:

Best regards…
Leandro

“Shaun Jackman” <sjackman@nospam.vortek.com> escreveu na mensagem
news:ai4egd$ome$1@inn.qnx.com

Funnily enough, I’m actually going the opposite way. I had it generating a
pulse first. I measured the jitter on the MsgReceive() though, and it was
in
the tens of micro-seconds on a one milli-second timer (on a PIII/750) ,
which for my application is too much. I think the timing sensitivity
requires that it be as high-priority as interrupt handlers, so I thought
SIGEV_INTR might do the trick for me. I’ve got it working in a
single-threaded test app, but I’ve yet to make it work within io-net (my
final goal). If I can’t get this to go, I’ll try to InterruptAttach() the
hardware timer interrupt (the clock is running at 1ms).

To answer my own questions (correctly I hope):
(1) not necessary
(2) yes you need to disable interrupts, no this is not already done
(3) no
(lastly) beats me. Anyone else?

Thanks,
Shaun


Leandro Colen <> lcrocha@yahoo.com> > wrote in message
news:ai4cks$nbn$> 1@inn.qnx.com> …
Hey Shaun,

can’t you make the timer to generate a pulse and works with it?
I used to have a situation like yours and for me, i replace the
interrupt-timer-generate to timer-pulse notification scheme…
It’s working well…

Bye,
Leandro

“Shaun Jackman” <> sjackman@nospam.vortek.com> > escreveu na mensagem
news:ai48i2$kpe$> 1@inn.qnx.com> …
I want to create a timer that generates a SIGEV_INTR every
millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

SIGEV_INTR_INIT( &TimerEvent);
timer_create( CLOCK_REALTIME, &TimerEvent, &hTimer);
ITime.it_value.tv_sec = 0;
ITime.it_value.tv_nsec = 1000000;
ITime.it_interval.tv_sec = ITime.it_value.tv_sec;
ITime.it_interval.tv_nsec = ITime.it_value.tv_nsec;
timer_settime( hTimer, 0, &ITime, NULL);
InterruptAttachEvent( …); // (1)
for(;:wink: {
InterruptWait( 0, NULL);
InterruptDisable(); // (2)
// do time sensitive stuff here
InterruptUnmask(); // (3)
InterruptEnable();
}

My question is:
(1) Is a call to IntterruptAttachEvent() necessary, or does
timer_*()
replace this?
(2) Do I need to disable interrupts manually, or is this already
done?
(3) Do I need to unmask an interrupt? Which one?
Lastly, does the SIGEV_INTR get sent to the thread that called
timer_create() and timer_settime()?

Thanks,
Shaun

Shaun Jackman <sjackman@nospam.vortek.com> wrote:

I want to create a timer that generates a SIGEV_INTR every millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

I started out with a post saying that you can’t use SIGEV_INTR with
anything except interrupts… because I thought that was so. The docs
seem to suggest this is not the case… I’ll have to do some more
research on this.

-David

SIGEV_INTR_INIT( &TimerEvent);
timer_create( CLOCK_REALTIME, &TimerEvent, &hTimer);
ITime.it_value.tv_sec = 0;
ITime.it_value.tv_nsec = 1000000;
ITime.it_interval.tv_sec = ITime.it_value.tv_sec;
ITime.it_interval.tv_nsec = ITime.it_value.tv_nsec;
timer_settime( hTimer, 0, &ITime, NULL);
InterruptAttachEvent( …); // (1)
for(;:wink: {
InterruptWait( 0, NULL);
InterruptDisable(); // (2)
// do time sensitive stuff here
InterruptUnmask(); // (3)
InterruptEnable();
}

My question is:
(1) Is a call to IntterruptAttachEvent() necessary, or does timer_*()
replace this?
(2) Do I need to disable interrupts manually, or is this already done?
(3) Do I need to unmask an interrupt? Which one?
Lastly, does the SIGEV_INTR get sent to the thread that called
timer_create() and timer_settime()?

Thanks,
Shaun


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

Shaun Jackman <sjackman@nospam.vortek.com> wrote in article <ai4egd$ome$1@inn.qnx.com>…

Funnily enough, I’m actually going the opposite way. I had it generating a
pulse first. I measured the jitter on the MsgReceive() though, and it was in
the tens of micro-seconds on a one milli-second timer (on a PIII/750) ,
which for my application is too much.

tens of microsecond is quite normal precission of timers. you want to look at ClockPeriod()
function.

I think the timing sensitivity
requires that it be as high-priority as interrupt handlers, so I thought
SIGEV_INTR might do the trick for me.

no, it will not do the trick. as it was mentioned by Leandro, you could use external hardware
timer. for x86 platform, you could use RTC chip to generate hardware interrupts every:
500 mS
250 mS
125 mS
62.5 mS
31.25 mS
15.625 mS
7.8125 mS
3.90625 mS
1.953125 mS
976.5625 uS
488.281 uS
244.141 us
122.070 us
if none of above periods meets your requirements you want custom external board.

cheers,

eduard.
ed1k at ukr dot net


I’ve got it working in a
single-threaded test app, but I’ve yet to make it work within io-net (my
final goal). If I can’t get this to go, I’ll try to InterruptAttach() the
hardware timer interrupt (the clock is running at 1ms).

To answer my own questions (correctly I hope):
(1) not necessary
(2) yes you need to disable interrupts, no this is not already done
(3) no
(lastly) beats me. Anyone else?

Thanks,
Shaun


Leandro Colen <> lcrocha@yahoo.com> > wrote in message
news:ai4cks$nbn$> 1@inn.qnx.com> …
Hey Shaun,

can’t you make the timer to generate a pulse and works with it?
I used to have a situation like yours and for me, i replace the
interrupt-timer-generate to timer-pulse notification scheme…
It’s working well…

Bye,
Leandro

“Shaun Jackman” <> sjackman@nospam.vortek.com> > escreveu na mensagem
news:ai48i2$kpe$> 1@inn.qnx.com> …
I want to create a timer that generates a SIGEV_INTR every millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

SIGEV_INTR_INIT( &TimerEvent);
timer_create( CLOCK_REALTIME, &TimerEvent, &hTimer);
ITime.it_value.tv_sec = 0;
ITime.it_value.tv_nsec = 1000000;
ITime.it_interval.tv_sec = ITime.it_value.tv_sec;
ITime.it_interval.tv_nsec = ITime.it_value.tv_nsec;
timer_settime( hTimer, 0, &ITime, NULL);
InterruptAttachEvent( …); // (1)
for(;:wink: {
InterruptWait( 0, NULL);
InterruptDisable(); // (2)
// do time sensitive stuff here
InterruptUnmask(); // (3)
InterruptEnable();
}

My question is:
(1) Is a call to IntterruptAttachEvent() necessary, or does
timer_*()
replace this?
(2) Do I need to disable interrupts manually, or is this already
done?
(3) Do I need to unmask an interrupt? Which one?
Lastly, does the SIGEV_INTR get sent to the thread that called
timer_create() and timer_settime()?

Thanks,
Shaun
\

David Gibbs <dagibbs@qnx.com> wrote:

Shaun Jackman <> sjackman@nospam.vortek.com> > wrote:
I want to create a timer that generates a SIGEV_INTR every millisecond.
Following is a code snippet showing what I want to accomplish: (note:
non-smp)

I started out with a post saying that you can’t use SIGEV_INTR with
anything except interrupts… because I thought that was so. The docs
seem to suggest this is not the case… I’ll have to do some more
research on this.

With a bit more research – you should not use a SIGEV_INTR with a
timer (nor should you use a SIGEV_UNBLOCK, despite the fact that the
docs have both in their “recommended” list, I’ve issued a PR vs the
docs for this).

SIGEV_INTR should only be used with InterruptAttachEvent() or in the
return from an ISR.

-David

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

If I can’t get this to go, I’ll try to InterruptAttach() the hardware
timer interrupt (the clock is running at 1ms).

The following code works perfectly once, and then the second time I run it,
it stalls after printing “0”. InterruptWait() never returns. The system
timer seems totally broken afterwards. Calling `shutdown’ afterwards says
“Shutting down apps…”, and never actually does anything (waiting for a
timer to expire I assume). Is hooking the RTC IRQ allowed, or have I broken
it in some other way?

#define RTC_IRQ 0
ThreadCtl( _NTO_TCTL_IO, 0);
SIGEV_INTR_INIT( &event);
hInterrupt = InterruptAttachEvent( RTC_IRQ, &event, 0);
for( i = 0; i < 100; i++) {
printf( “%d\n”, i);
InterruptWait( 0, NULL);
InterruptDisable();
// do stuff
InterruptUnmask( RTC_IRQ, hInterrupt);
InterruptEnable();
}
InterruptDetach( hInterrupt);

Thanks,
Shaun

Shaun Jackman <sjackman@nospam.vortek.com> wrote:

If I can’t get this to go, I’ll try to InterruptAttach() the hardware
timer interrupt (the clock is running at 1ms).

The following code works perfectly once, and then the second time I run it,
it stalls after printing “0”. InterruptWait() never returns. The system
timer seems totally broken afterwards. Calling `shutdown’ afterwards says
“Shutting down apps…”, and never actually does anything (waiting for a
timer to expire I assume). Is hooking the RTC IRQ allowed, or have I broken
it in some other way?

#define RTC_IRQ 0
ThreadCtl( _NTO_TCTL_IO, 0);
SIGEV_INTR_INIT( &event);
hInterrupt = InterruptAttachEvent( RTC_IRQ, &event, 0);

You NEED to put in _INTR_FLAGS_TRK_MSK in the flags parameter of any
call to InterruptAttach() and ESPECIALLY for InterruptAttachEvent() where
the irq is being masked automatically for you.

If you do not, you may end up with the irq permanently masked.

-David

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

Great! This fixed my problem. Thanks for you quick reply. I don’t fully
understand what the problem is though. The implicit InterruptMask() of
InterruptWait() is matched with my explicit InterruptUnmask() every single
time. I don’t see how an extra InterruptMask() could sneak in to leave the
interrupt inadvertently disabled. What magic is QNX doing when the TRK_MSK
flag is specified? If this flag is necessary, I suggest putting your exact
words into the documentation for InterruptAttachEvent().

Thanks!
Shaun

You NEED to put in _INTR_FLAGS_TRK_MSK in the flags parameter of any
call to InterruptAttach() and ESPECIALLY for InterruptAttachEvent() where
the irq is being masked automatically for you.

If you do not, you may end up with the irq permanently masked.

Shaun Jackman <sjackman@nospam.vortek.com> wrote:

Great! This fixed my problem. Thanks for you quick reply. I don’t fully
understand what the problem is though. The implicit InterruptMask() of
InterruptWait() is matched with my explicit InterruptUnmask() every single
time.

Here is your code again:

: #define RTC_IRQ 0
: ThreadCtl( _NTO_TCTL_IO, 0);
: SIGEV_INTR_INIT( &event);
: hInterrupt = InterruptAttachEvent( RTC_IRQ, &event, 0);
: for( i = 0; i < 100; i++) {
: printf( “%d\n”, i);
: InterruptWait( 0, NULL);
: InterruptDisable();
: // do stuff
: InterruptUnmask( RTC_IRQ, hInterrupt);
: InterruptEnable();

On your 100th loop, at this point an interrupt is generated, the
interrupt is automatically masked…
: }

You fall out of the loop, rather than doing an InterruptWait() and
InterruptUnmask().

: InterruptDetach( hInterrupt);

And, now, the interrupt is (almost) permanently masked.

I don’t see how an extra InterruptMask() could sneak in to leave the
interrupt inadvertently disabled. What magic is QNX doing when the TRK_MSK
flag is specified?

QNX maintains a mask counter for the interrupt level on a system global
basis, each time a mask is performed (InterruptMask() or each event
attached to that interrupt level), this counter is increment. On each
InterruptUnMask() this counter is decremented. When this counter goes
to 0, the interrupt is actually unmasked at the PIC (hardware) level.

Setting TRK_MSK creates a per-process counter of how many masks & unmasks
are “owned” by that process. If the process counter is greater than 0
when the process exits, that number of “unmasks” will be applied to the
system global counter. In essence, this flag asks the OS to cleanup
after your process properly on process exit.

If this flag is necessary, I suggest putting your exact
words into the documentation for InterruptAttachEvent().

It is not strictly neccessary – if you disable your hardware
before exiting, so you will never have a pending mask for your
process at exit time, or if you are not sharing interrupt levels
(that is, you don’t have more than one handler/event attached to
a particular interrupt level) then you don’t need this. But, most
of the time, and especially during development when things might go
unexpectedly wrong, it is usually good to have. I will pass on a
suggestion to docs (a PR) that this should be more strongly worded.

-David

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