high-frequency timebase?

Hello,

we are about to develop a demonstrator for a motion control system on a QNX
PC. In this system we have to set up a control cycle with a much higher
cycle frequency than 1/10ms (100Hz), which seems to be the default timebase
using QNX.

  1. As it is the case that increasing basetime-ticks per second leads to
    greater operation system overhead (reduction of user application
    performance), what basetime resolution range would be reasonable on a 3GHz
    Pentium processor? Is a timebase with a resolution of e.g. 10 or 100
    microseconds conceivable using the ClockPeriod() function and PULSEs or
    SIGNALs?

  2. Is there any other possibility to get a “tick” in the user application,
    apart from using the QNX timers together with the standard timebase? E.g. is
    the ClockCycles() function somehow usable for cyclic notification of a user
    application?

Thank you.

Nnamdi

Nnamdi Kohn <nnamdi.kohn@web.de> wrote:

Hello,

we are about to develop a demonstrator for a motion control system on a QNX
PC. In this system we have to set up a control cycle with a much higher
cycle frequency than 1/10ms (100Hz), which seems to be the default timebase
using QNX.

Um… 1/10ms and 100Hz are not the same – did you mean 100KHz?

  1. As it is the case that increasing basetime-ticks per second leads to
    greater operation system overhead (reduction of user application
    performance), what basetime resolution range would be reasonable on a 3GHz
    Pentium processor? Is a timebase with a resolution of e.g. 10 or 100
    microseconds conceivable using the ClockPeriod() function and PULSEs or
    SIGNALs?

On a 3 GHz pentium, 100 us should be fine, getting down to 10 us, the
overhead is going to start to get to extreme. :frowning:



  1. Is there any other possibility to get a “tick” in the user application,
    apart from using the QNX timers together with the standard timebase? E.g. is
    the ClockCycles() function somehow usable for cyclic notification of a user
    application?

ClockCycles() doesn’t generate an extraneous interrupt.

The (usual) timer chip on an x86/PC has three timers in it, we use timer 0
for the system time. One of the other timers is used for “sounds”, like
keyboard/warning beeps. The third is, I think, available. You could
use this timer to drive your loop, through either an interrupt handler,
or scheduling a thread. At this frequency, you may want to do the
really time critical hardware work in the interrupt handler, and then
only schedule a thread when “sufficient” data/work has been done to be
worth it. Or, if you need OS resources directly at that frequency, use
an INTERRUPT event to a thread blocked on InterruptWait(), as that is
the least overhead, fastest scheduling method.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Nnamdi Kohn wrote:

Hello,

we are about to develop a demonstrator for a motion control system on a QNX
PC. In this system we have to set up a control cycle with a much higher
cycle frequency than 1/10ms (100Hz), which seems to be the default timebase
using QNX.

QNX 6.x default is 1 kHz. This is enough for unbuffered profile
generation but if you are doing the servo loop as well then something
faster is preferred. As David says, the system tick can be adjusted.
Armin has provided the RTC alarm as it can generate IRQ#8 up to 8192 Hz.

Read up on ClockPeriod() for adjusting the system tick.


  1. As it is the case that increasing basetime-ticks per second leads to
    greater operation system overhead (reduction of user application
    performance), what basetime resolution range would be reasonable on a 3GHz
    Pentium processor? Is a timebase with a resolution of e.g. 10 or 100
    microseconds conceivable using the ClockPeriod() function and PULSEs or
    SIGNALs?

No. Interrupts are your friend. :slight_smile:

As for the Pentium, I would not recommend a P4 based design, they don’t
take kindly to fast interrupts. Go for P3/K7/K8 solutions.

Nnamdi Kohn wrote:

Hello,

we are about to develop a demonstrator for a motion control system on a QNX
PC. In this system we have to set up a control cycle with a much higher
cycle frequency than 1/10ms (100Hz), which seems to be the default timebase
using QNX.

  1. As it is the case that increasing basetime-ticks per second leads to
    greater operation system overhead (reduction of user application
    performance), what basetime resolution range would be reasonable on a 3GHz
    Pentium processor? Is a timebase with a resolution of e.g. 10 or 100
    microseconds conceivable using the ClockPeriod() function and PULSEs or
    SIGNALs?

  2. Is there any other possibility to get a “tick” in the user application,
    apart from using the QNX timers together with the standard timebase?

Yes, use the RTC (IRQ8).

Here is the code for the RTC handling:

const struct sigevent *
IRQ8handler(void *area, int id)
{

InterruptDisable();
(void) out8(CMOS_ADDR, 0x0c); // Prepare to read register C
(void) in8(CMOS_DATA); // Read register C to clear interrupts
InterruptEnable();

return (&TimerEvent); // TimerEvent triggers the application …
}


/*

  • Setup the RTC
    */

void SetupRTC( unsigned short tr )
{
int reg ;

InterruptDisable(); // hopefully no NMIs …
(void) out8( CMOS_ADDR, 0x0A ) ; /* init to read RTC status register A /
reg = in8( CMOS_DATA ) ; /
Read RTC status register A */
InterruptEnable();

reg &= CMOS_ADDR; /* save bit 6… bit 4 of status register A */
reg |= tr; /*tr 3 = 122us /
/
4 = 244us /
/
5 = 488us /
/
6 = 976us /
/
7 =1953us /
/
8 =3906us */

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0A ); /* init to update RTC status register A /
(void) out8( CMOS_DATA, reg ) ; /
set tick intervall */
InterruptEnable();

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0B ) ;/* init to read register B /
reg = in8( CMOS_DATA ) ; /
Read it */
InterruptEnable();

reg |= 0x40 ; /* enable IRQ 8 */

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0B ) ;/* init to update register B /
(void) out8( CMOS_DATA, reg ) ; /
Update register B */
InterruptEnable();

/*

  • On some machines there may be dangling interrupts following
  • the POST test. Clear any dangling interrupts here.
    */

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0c ) ;/* Prepare to read register C /
(void) in8( CMOS_DATA ) ; /
Read register C to clear interrupts */
InterruptEnable();

}


/*

  • RestoreRTC()
    */

void RestoreRTC( void )
{
int reg ;

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0B ) ;/* init to read register B /
reg = in8( CMOS_DATA ) ; /
Read register B */
InterruptEnable();

reg &= 0xBF ; /* Clear interrupt enable bit of IRQ 8*/

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0B ) ;/* init to update register B /
(void) out8( CMOS_DATA, reg ) ;/
Update register B */
InterruptEnable();

InterruptDisable();
(void) out8( CMOS_ADDR, 0x0C ) ;/* init to read register C /
(void) in8( CMOS_DATA ) ; /
Read reg. C to clear any interrupts */
InterruptEnable();

}

Regards

Armin Steinhoff

http://www.steinhoff-automation.com

E.g. is
the ClockCycles() function somehow usable for cyclic notification of a user
application?

Thank you.

Nnamdi

Opps, Correction …


Nnamdi Kohn wrote:

  1. Is there any other possibility to get a “tick” in the user application,
    apart from using the QNX timers together with the standard timebase? E.g. is
    the ClockCycles() function somehow usable for cyclic notification of a user
    application?

No. Interrupts are your friend. :slight_smile:

Hi Armin,

thanks for the code. So, I modify the IRQ-Handler according to my demands,
set up the RTC-Hardware and the interrupt handler (using InterruptAttach()).
This should work fine. Though, I have problems figuring out, what real
values are to put in for CMOS_ADDR and CMOS_DATA. Could you give me a hint?

Thanks.

Nnamdi

#define CMOS_ADDR 0x70
#define CMOS_DATA 0x71

Evan, thank you for your help.

One last question: where do I find general information about other standard
(built in) devices accessible via in() and out(), together with their
standard access specification (addresses)? From where do I get the
information about e.g. CMOS_ADDR = 0x70 ?

Nnamdi

“Evan Hillas” <blarg@blarg.blarg> schrieb im Newsbeitrag
news:cj9ves$19d$1@inn.qnx.com

#define CMOS_ADDR 0x70
#define CMOS_DATA 0x71

Nnamdi Kohn wrote:

Evan, thank you for your help.

One last question: where do I find general information about other standard
(built in) devices accessible via in() and out(), together with their
standard access specification (addresses)? From where do I get the
information about e.g. CMOS_ADDR = 0x70 ?

Legacy PC hardware info can be found in any PC hardware book. In fact it’s about the only thing that such books will talk about and as such are prolly fading into the secondhand market.

There is plenty online too, just google for the item of interest combined with terms like ioport, hardware, programming, library, source code.

Evan Hillas <blarg@blarg.blarg> wrote:
EH > Nnamdi Kohn wrote:

Evan, thank you for your help.

One last question: where do I find general information about other standard
(built in) devices accessible via in() and out(), together with their
standard access specification (addresses)? From where do I get the
information about e.g. CMOS_ADDR = 0x70 ?

EH > Legacy PC hardware info can be found in any PC hardware book. In fact it’s about the only thing that such books will talk about and as such are prolly fading into the secondhand market.

EH > There is plenty online too, just google for the item of interest combined with terms like ioport, hardware, programming, library, source code.

An excellent book is “The Undocumented PC”. I don’t have the author’s
name in front of me right now.