out8() and Stopped due to shared library event

Hello,

i have an application which toggles the parallel port, delays the signal and injects it into IRQ7 to measure the interrupt and scheduling latency.

When I compile the application, everything is fine, but when running the application on the target (QNX 6.3.2 x86 VMware) it just terminates without any output.

When compiling the debug version and debug the application I recieve the following output in the Console:

Here is my code:

[code]#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <stdint.h>
#include <hw/inout.h>
#include <time.h>

/* ************************* DEFINES ****************************************** */

#define NUM_MEASURE 20
#define DELAY_TIME_NS 50000 /* 50 us in ns */

/* The Neutrino parallel IO port used, corresponds to a single register, with one byte length /
#define PPT_PORT_LENGTH 1
#define PPT1_DATA 0x378
#define PPT1_CTRL 0x37a
#define PPT1_INIT 0x4 /
bit 2 = printer initialisation (high to initialise) bit 4 = hardware IRQ (high to enable) /
#define PPT1_IRQ 0x7
#define PPT1_INTR 0x10 /
bit 2 = printer initialisation (high to initialise) bit 4 = hardware IRQ (high to enable) */

/* High Low values */
#define HIGH 0xff
#define LOW 0x0

/* ************************* GLOBAL VARIABLES ********************************* */
uintptr_t pptCtrlHdl;
uintptr_t pptDataHdl;

pthread_t* p_triggerThread;
pthread_t* p_workThread;

struct timespec t_start;
struct timespec t_stop;

double t_diff;
int i_intID;

/* **************************************************************************** /
void
funcTriggerThread(void* arg);
void* funcWorkThread(void* arg);
const struct sigevent * ppt1_isr_handler (void event, int interruptID);
/
**************************************************************************** */

void* funcTriggerThread(void* arg)
{
int i;
int err;

/* Give thread root permissions to access the HW */
err = ThreadCtl( _NTO_TCTL_IO, NULL );
if ( -1 == err )
{
	printf( "Can't get root permission for triggerThread!\n" );
}

for ( i=1 ; i <= NUM_MEASURE ; i++ )
{
	/* Set parallel port pin to high */
	out8( pptDataHdl , HIGH );
	clock_gettime( CLOCK_REALTIME , &t_start );	
}

exit (0);

}

void* funcWorkThread(void* arg)
{
while (1)
{
clock_gettime( CLOCK_REALTIME , &t_stop );
t_diff = (double)(t_stop.tv_sec - t_start.tv_sec) + (double)(t_stop.tv_nsec - t_start.tv_nsec);
printf(“Interrupt latency: %f ns” , t_diff);
}

exit (0);

}

const struct sigevent * ppt1_isr_handler (void *event, int interruptID)
{
#ifdef MY_DEBUG
printf(“DEBUG: Entered ppt1ISR\n”);
#endif

pthread_join( *p_workThread, NULL );

#ifdef MY_DEBUG
	printf("DEBUG: Exit ppt1ISR\n");
#endif

return (event); 	

}

int main()
{

struct sched_param param;

printf("	=> Initialisiere Hardware... ");        
/* Create Handle for parallel port 1 CTRL register */	
pptCtrlHdl = mmap_device_io( PPT_PORT_LENGTH , PPT1_CTRL );
/* Create Handle for parallel port 1 DATA register */
pptDataHdl = mmap_device_io( PPT_PORT_LENGTH , PPT1_DATA );
/* Initialise parallel port */
out16( pptCtrlHdl , PPT1_INIT );
/* Activate Interrupts on parallel port */
out16( pptCtrlHdl , PPT1_INTR );

/* Interrupt handling */
i_intID = InterruptAttach( PPT1_IRQ , ppt1_isr_handler , NULL, 0, 0 );

printf("done\n");       

printf("	=> Initialisiere Threads... \n");        
param.sched_priority = 99;
pthread_create( p_triggerThread, NULL, &funcTriggerThread, NULL );
pthread_create( p_workThread, NULL, &funcWorkThread, NULL );
pthread_setschedparam( *p_workThread , SCHED_RR, &param);

pthread_join( *p_triggerThread, NULL );



InterruptDetach( i_intID );
return EXIT_SUCCESS;

}[/code]

I even don’t see the

printf("	=> Initialisiere Hardware... "); 

Anybody has an Idea for me? The Code is not yet fully optimized, but it should work atleast for one measurement.

Best Regards

  • You don’t see the first output from printf because it’s missing a \n, or a fflush(). Without a flush data stay in the buffer.
  • You need to use ThreadCtl to allow adding an interrupt handler and doing I/O operation.
  • I think standard parallel port use 8 bit port not 16 bit port, in main()
  • ALWAYS check the return value of function.
  • You cannot use printf inside an interrupt handler.
  • This program will run forever
  • If there is an interrupt, nothing clears it and probably freeze the machine.
  • If any of the exit() gets calls it will terminate the process immediately. Basically after funcTriggerThread is done with it’s forloop the process terminates.

I don’t see any point of setting just one thread to RR. RR lets a thread run until it blocks, but only against other threads running at the same priority using RR.

Mario is quite right about the parallel port using 8 bit ports.

The initialization bit you are setting is for initializing a printer. Likewise an IRQ 7 interrupt must come from attached hardware. To write data to a printer, you must load data into the data port, and then toggle the strobe line. Is your parallel port attached to a printer?

And you can’t join a thread in an isr for two reasons. One is that you can’t do this kind of kernel call from an isr. The other, is that it makes no sense. No thread is running when in the isr code.

In short, you don’t seem to know what you are doing software or hardware wise so what is your goal? If you want to learn about how to create a parallel port driver, you could start with the code for the parallel port driver.

Actually, no. Round-robin, will timeslice threads at the same priority. I believe you may be thinking of SCHED_FIFO.

Ouch, yes. What threw me off is that RR is the default, right? So why change to it at all?

Yup, SCHED_RR is the default. Not sure why it was explicitly specified…