Real Time Gpio task

Hi my name is Sorin Soare, and I am working on a university project that needs a real-time operating system, on a AT91SAM9260-ek board (ARM9), to communicate with other boards LPC2148. I chose QNX Neutrino V4 because its open source.
I’m am now at the point where i have to do some tests to evaluate the jitter of a signal that is generated by the board through a program that runs on QNX .I wrote a program that just toggles a GPIO pin on the board (PIN0 PORTC).The toggling is done with the help of a timer(first timer-id from program), witch depends on a run parameter. The problem is that when I measure the jitter,with an oscilloscope, its too big, meaning that for a 500us 50% signal there is a jitter of 100us and sometimes its bigger then the hole impulse(the signal is just not stationary). As you can see from the attached code I`v also set the program priority well above the other processes(first run parameter 100). I also tried to set the clock period to lower value than the signal to make the resolution smaller. I am using Real Time timers. I also added another timer to stop the program after 20 seconds because before I did this I couldn’t stop the program with CTRL+C through serial terminal(I am running the program with a putty attached on the serial interface of the board). The board is set to run at 180 MHz(checked it with pidin in), and the only processes running on the board are: proctno, serdebug, slogger, io-pkt-v4, qconn,pdebug,ksh,devc-pty and serusart; the rest I closed so they wouldn’t affect the program.
I must be doing something wrong because I can’t believe that for a clock period of 250us a signal period of 500us and a priority of 100, i have 100us or even larger jitter. Qnx can’t have that bad real-time abilities. I need to communicate with the other boards with SPI, and the SPI-CLK signal must have a small jitter (25-50us).

Deleted old code

Believer_X,

The code you posted looks like a cut-n-paste from more than one version of your code because you set your timer value twice and seem to be mixing signals and pulses and don’t have a way to exit after 20 seconds.

In any case it would be better if your sample code had #define values in it for initial testing before you went to using the command line args. That would let everyone see that you were using values you think you are.

Three things I’d do:

  1. Hard code your priority/clock period and other variables you are reading from the command line so it’s easier to ensure you are getting what you expect and for someone to help.
  2. Check the return of Clock_Period. That call can fail and you should make sure it isn’t failing. Also note that the timeslice is always 4x the clock period.
  3. Post your actual code :slight_smile:

Tim

Use the system profiler to figure out what is causing the jitter.

Sorry for the ugly code, its was true is was a bunch of copy paste’s from sites of documents. I made some clean ups today and made the modifications that Tim told me. Of course i ran it on the board after this clean up and i have the same results, jitter bigger even the the signal impulse time (SIGNALIMPULSE).
I would like to say that i can’t use qconn for debugging because of 2 reasons: 1 the networking connection keeps falling because of the driver issue that is posted on the BSP for my board ( here http://community.qnx.com/sf/wiki/do/viewPage/projects.bsp/wiki/Nto640AtmelAt91sam9260EKEVBTrunkReleasenotes).
2: when qconn is connected (from 20 to 20 secconds) there is no system information in the System information perspective (no cpy details, board UNKNOWN). I can only see the filesystem and upload files to the board, and run them through a run configuration.
Could someone run the code a similar speed processor (180MHz) and tell me the jitter or how much the signal moves during program running.I also want to attach a print from the terminal for you to see what programs i am running on the board before running my program.
I would happily give more information if you need.

[code]
#define MY_PULSE_CODE _PULSE_CODE_MINAVAIL //minimum pulse code available
#define PRIORITY 100 // the program priority
#define SIGNALIMPULSE 500000// 500 microsecond signal on ‘1’
#define SIGNALPERIOD 1000000// 1 milisecond signal period
#define CLOCKPERIOD 250000// 250 microsecond system clock

#define PIO_LENGHT 0x00AC
#define PIO_OWER 0x00A0
#define PIO_ODSR 0x0038

int flag=0; //the flag is used for pin toggling;
uintptr_t piocHandle; // the memory zone handler used by the out32 instructions

typedef union {
struct _pulse pulse;
}my_message_t;

void handler(int signum)
{
if(flag==0)
{
out32(piocHandle + PIO_ODSR,0x01);
flag=1;
}
else
{
out32(piocHandle + PIO_ODSR,0x00);
flag=0;
}

}

int main()
{

struct _clockperiod clkper;
timer_t  FirstTimer,SecondTimer;
struct itimerspec  timerSpec;
struct sched_param schParam;

struct sigaction newact;

struct sigevent         event;
int                     chid;
int                     rcvid;

schParam.sched_priority = PRIORITY;
if(sched_setscheduler( 0, SCHED_RR, &schParam) == -1)
{
	printf( "Error in setting priority\n");
    return -1;
}


printf("Started test with program priority=%d ,signal period = %ld ,signal impulse = %ld\n",
	    PRIORITY,SIGNALPERIOD,SIGNALIMPULSE);

//setting the system clock to 250000 ns, because the signal is 500 microseconds

clkper.nsec       = CLOCKPERIOD;
clkper.fract      = 0;
if( ClockPeriod ( CLOCK_REALTIME, &clkper, NULL, 0  ) == -1 )
{
	printf( "Can't set clock period to %d\n",clkper.nsec );
    return -1;
}


//setting the input output permisions of the program, this is to be able to use the in out instructions

if ( ThreadCtl( _NTO_TCTL_IO, NULL ) == -1 )
{
	printf( "Can't get I/O permissions\n" );
	return -1;
}

// mapping the memory zone to a handle

piocHandle = mmap_device_io(PIO_LENGHT,PIOC_BASE);

if(piocHandle==MAP_DEVICE_FAILED)
{
	printf("Error in mapping the memory zone for PIOC\n ERROR:%s\n",strerror(errno));
	return -1;
}

//setting PORTC PIN0 to be GPIO output
out32(piocHandle + PIO_PER,0x01);
out32(piocHandle + PIO_OER,0x01);
out32(piocHandle + PIO_OWER,0x01);

//creating timer for the signal; leaveing the second argument null because it raises a SIGALM by default
if ( timer_create(  CLOCK_REALTIME,NULL, &FirstTimer ) == -1 )
{
	perror ( "can't create first timer" );
	return -1;
}

timerSpec.it_value.tv_sec = 0;
timerSpec.it_value.tv_nsec = SIGNALIMPULSE;
timerSpec.it_interval.tv_sec = 0;
timerSpec.it_interval.tv_nsec = SIGNALIMPULSE;

timer_settime(FirstTimer, 0, &timerSpec, NULL);

//installing the toggle function
newact.sa_flags=0;
sigemptyset( &newact.sa_mask );
newact.sa_handler=&handler;

if(sigaction(SIGALRM,&newact,NULL)<0)
{
	printf("Error when installing handler for SIGALDM:%s",strerror(errno));
}

my_message_t            msg;
//this i actually copy pasted from a site, but it works, beacuse it stops the program after 20 secconds
			//from here
chid = ChannelCreate(0);
event.sigev_notify = SIGEV_PULSE;
event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0,chid,_NTO_SIDE_CHANNEL, 0);
event.sigev_priority = getprio(0);
event.sigev_code = MY_PULSE_CODE;
timer_create(CLOCK_REALTIME, &event, &SecondTimer);

timerSpec.it_value.tv_sec = 20; //20 secconds
timerSpec.it_value.tv_nsec = 0;
timerSpec.it_interval.tv_sec = 0;//no repetition
timerSpec.it_interval.tv_nsec = 0;
timer_settime(SecondTimer, 0, &timerSpec, NULL);

for (;;) {
	rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
	if (rcvid == 0) {//  we got a pulse
		if (msg.pulse.code == MY_PULSE_CODE) {
			printf("we got a pulse from our timer\n");//when i receive the first pulse then i exit the program
			exit(1);
		}
	}
}
			//to here

return EXIT_SUCCESS;

}[/code]

quick additional information : i`ve updated the BSP to the updated one from the site and i have the same results.

Believer_X,

Unfortunately I don’t have an ARM processor board to test your code on. All I would be able to do is run it on an Intel CPU which isn’t going to be exactly the same as what you have.

Looking at your code I don’t see anything obviously wrong. However I am not big on using signals when I code. You could for example do:

#define MY_PULSE_CODE1   _PULSE_CODE_MINAVAIL+1
 
// Now instead of using signal handler use pulse similar to the 20 second timer
event.sigev_notify = SIGEV_PULSE;
   event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0,chid,_NTO_SIDE_CHANNEL, 0);
   event.sigev_priority = getprio(0);
   event.sigev_code = MY_PULSE_CODE1;
   timer_create(CLOCK_REALTIME, &event, &FirstTimer);

 timerSpec.it_value.tv_sec = 0;
    timerSpec.it_value.tv_nsec = SIGNALIMPULSE;
   timerSpec.it_interval.tv_sec = 0;
   timerSpec.it_interval.tv_nsec = SIGNALIMPULSE; 
   timer_settime(FirstTimer, 0, &timerSpec, NULL);

// Now in your main loop see exactly which timer expired
for (;;) {
      rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
      if (rcvid == 0) {//  we got a pulse
         if (msg.pulse.code == MY_PULSE_CODE) {
            printf("we got a pulse from our timer\n");//when i receive the first pulse then i exit the program
            exit(1);
         }
         else if (msg.pulse.code == MY_PULSE_CODE1) {
            handler();  // Call my handler function to toggle the GPIO pin
         }
      }
   } 

I doubt this makes any difference to the issue you see but it at least removes the complexity of using signals. You may want to give it a quick try before moving on to what I suggest next.

Even though you can’t get qconn to work on your board it is still possible to use the system profiler in the IDE to diagnose exactly what is happening. Take a look in the QNX documents under the instrumented kernel/instrumented profiling. That explains how to create a special version of the QNX kernel that can trace what’s happening and allow you to upload it to the IDE for review. This as Mario mentioned is the best way to track down something like what you are seeing.

Tim

Maybe I’m misunderstanding, but if the clock fires every 250ms and you request a period of 500ms I would think that the jitter would get as large as 250ms and that 100ms would be just plain lucky. This is not a bad real time OS, this is just basic math. Let’s say you have a clock that records time in seconds and you want to measure a two second interval. You start by looking at the clock and recording the time it shows. Let’s say it says 12:00:01. The problem is you don’t know if it just turned to 12:00:01 or if is about to turn to 12:00:02. So you must wait until 12:00:04 to make sure 2 seconds go by, and you have a jitter of 1 second.

Ok maschoen, so theoretically if i set the clock 4 times smaller then i should have small jitter, but if i set the clockPeriod bellow 150 000 ns =150 micoseconds, then i probably have interrupt overhead, because on the osciloscope i see the signal move in a periodical fashion.
What would you recommend in order to make the gpio signal more precise? I would like to mention that the Spi communication protocol works with a CLK of 250 micro seconds.

Hum I swear I made a post that refered to: qnx.com/developers/articles/ … 826_2.html so I posted again ;-)

You always have interrupt overhead. Sometimes it is significant and other times not. The signal may move periodically for a variety of reasons. If you want more precise readings, I’d suggest you find or attach hardware that provides a precise periodic interrupt at the rate you need. On x86 systems there is a device called the real time timer that can do this.

Hello,
maschoen my board has a Real Time Timer, is there a way through i can connect a process to this RTT with qnx, besides writing in the RTT registers with out32 instructions, and writing in the intrerupt vector?
mario i know that article, i read it and as you cand see copy-pasted a lot of it intro my code, it works , but the problems with it are written above (jitter). So this means that qnx cant produce a steady 500 usecond signal on my board?

If you are asking whether QNX already provides driver for the RTT, I don’t know, I haven’t looked in a while. If they haven’t then yes you need to write some hardware code. I wrote such a driver a long time ago either for QNX 2 or maybe QNX 4. It’s a pretty straight forward task.