Code changes for shared IRQs????

Do I need to alter the code (below) because it shares IRQs with another
card? I have the following PCI cards installed:

Slot Description IRQ
1 AHA2940 10
2 DIO-48 10
3
4 DIO-48 11
5
6 DIO-48 12
7
8 Pamux n/a
9 Pamux n/a
10 Ethernet (905) 11
11 Ethernet (82557) 10
12 Rocketport (serial) 10

Onboard:
Serial I/O 4/3
IDE (cd-rom) 15
Floppy 6

The code I’m starting is for the DIO-48 cards, one per card.

Thanks in advance for the help,

~ Jeffrey Jordan

#include <i86.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <errno.h>
#include <conio.h>
#include <sys/irqinfo.h>
#include <sys/mman.h>
#include <sys/name.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/proxy.h>
#include <sys/kernel.h>

#define MAIN

#include “basic.h”
#include “config.h”
#include “defs.h”
#include “health_api.h”
#include “messages.h”
#include “system.h”
#include “timecvt.h”
#include “dio_api.h”
#include “bithelpers.h”
#include “yd_io.h”
#include “ipc.h”
#include “timer.h”
#include “IOcard_obj.h”

//
// TASK CONTROL VARIABLES
//
nid_t My_nid; /* return value from getnid() /
pid_t My_pid; /
return value from getpid() /
pid_t My_nameid; /
return value from qnx_name_attach() */

int board_num;
int logging = FALSE;

/*

NOTE: The following defines support the change from performing two
conpiles
to get dio0 and dio1 to a single generic task which uses parameters to
support multiple boards.

*/

IO_CARD_OBJ Dio;
int BASE;

#define IRQ (Dio.irq)
#define NUM (board_num)

// max number of stacked interrupts
#define NUM_BUFFERS 200

// definition of package prepared on dio interrupt
typedef struct
{
UBYTE port0a;
UBYTE port0b;
UBYTE port0c;
UBYTE port1a;
UBYTE port1b;
UBYTE port1c;
int64 cycles; // machine cycles @ interrupt
// TIME nanotime; // Djenkins - nanotime stamp
UDWORD sequence; // sequence number
} DIO48_POINTS;

DIO48_POINTS dio48_points[NUM_BUFFERS];

// pragma for instructions to read machine cycle counter - 586 processor
only!!


void rdtsc64( int64 *ptr);

#pragma aux rdtsc64 = “db 0fh,31h” “mov [ebx],eax” “mov [ebx+4],edx”
parm nomemory [ebx] modify exact nomemory [eax edx];

unsigned rdtsc32( void );

#pragma aux rdtsc32 = “db 0fh,31h”
parm nomemory [] modify exact nomemory [eax edx];


UDWORD han_sequence;

// local working variables
pid_t proxy; // main is a proxy of the interrupt handler
pid_t dio_in_distrib_pid; // pid of cyc task
UDWORD int_sequence;
UDWORD ii;

DIO_EVENT dio_event;

char task_name[33];

// DELAY IN MACHINE CYCLES IN INTERRUPT BEFORE READ:
// 3600 = 40musec; 3300 = 37musec; 4995=55.5 musec @90MHz

//
// TBD MZ
// DELAY is bad. We need to be able to convert from machine cycles to
// musec via HZ, which should be available on the system. Where???
// TBD MZ

#define DELAY 3600

int delay_end,
delay_cycles;


// OPERATION: DIO0 ATTACHES TO THE INTERRUPT OF THE DIO BOARD. WHEN AN
INTERRUPT OCCURS,
// THE HANDLER RECORDS THE MACHINE CYCLE COUNTER AND CURRENT DIO POINT
VALUES IN A ROTATING
// STACK OF BUFFERS (FUNCTION CALLS ARE LIMITED WHILE IN INTERRUPT
STATE). THE RETURN FROM
// THE INT HANDLER TRIGGERS MAIN VIA PROXY TO PROCESS THE NEXT BUFFER.
CORRECT OPERATION
// RELIES ON QNX TO GENERATE ONE TRIGGER PER INTERRUPT HANDLER RETURN.
AS LONG AS THIS IS
// RELIABLE, THE INT HANDLER AND MAIN WILL STAY IN SYNC, WITH REGARD TO
REFERENCING THE
// CORRECT BUFFER ITEM.
// ONCE MAIN RECEIVE A TRIGGER, IT CONVERTS MACHINE CYCLES TO
HIGH-PRECISION TIME AND SENDS
// A COPY OF THE DIO POINTS TO AN IOC PROCESS AND A CYC PROCESS VIA TWO
MESSAGES. NOTE THAT
// THERE ARE TWO DIO HANDLERS (ONE PER BOARD) AND THEY SHARE THE PAIR OF
FIFOS TO THE IOC
// AND CYC CONSUMER PROCESSES.

//
/
INTERRUPT HANDLER /
/
/

#pragma off( check_stack);

void read_points ( )

{

// RE-ENABLE INTERRUPTS ON THE DIO48 BOARD
outp( BASE+0x000F, 0x00 );

// DETERMINE BUFFER TO USE
ii = int_sequence % NUM_BUFFERS ;


// GET THE MACHINE CYCLE COUNTER AT TIME OF INTERRUPT (CONVERTED LATER
TO TIME)
rdtsc64( &dio48_points[ii].cycles );

//
// Djenkins
//

// dio48_points[ii].nanotime = seconds_since_startup ();
//
// Djenkins
//

// DELAY TO ALLOW TRAPPING OF POINTS NOT DETECTED BY THIS INTERRUPT
(HARDWARE PROBLEM)
// delay_end = rdtsc32() + DELAY;
do
{
delay_cycles = rdtsc32();
}
while(delay_cycles < delay_end);



// READ THE DIO48 POINTS AND SAVE IN BUFFERED ARRAY
dio48_points[ii].port0a = inp( BASE+0x0000 );
dio48_points[ii].port0b = inp( BASE+0x0001 );
dio48_points[ii].port0c = inp( BASE+0x0002 );
dio48_points[ii].port1a = inp( BASE+0x0004 );
dio48_points[ii].port1b = inp( BASE+0x0005 );
dio48_points[ii].port1c = inp( BASE+0x0006 );

// INCREMENT THE SEQUENCE COUNTER - IGNORE ROLLOVER
dio48_points[ii].sequence = int_sequence ;

// INCREMENT BUFFER FOR NEXT INTERRUPT
//
// SCuM, 9/24/97 – added rollover logic so 1st time thru is truly
// unique, and I/O distributor(s) can toss the packet it necessary.
//
if (++int_sequence == IO_RESTART_SEQUENCE)
{
int_sequence++;
}

} // read_points

pid_t far handler()
{

read_points( );

return( proxy ); // will trigger main

}
#pragma on( check_stack );


BOOL HotBackup_Initialize_HealthRegister(char *task_name)
{
if (health_init (task_name) != SUCCESS)
{
fprintf (stderr, “%s: Can’t perform health_init()\n”, task_name);
return (TRUE);
}
return (FALSE);
}


int init_dio(int argc, char ** argv )

//
// Procedure: init_dio
//
// Purpose: Perfrom command line parsing and assoicated attach actions.
//
// Inputs: argc – argument counter
// argv – pointer to an array of string arguments of size argc
//
// Side Effects: Everything – This task initializes global data.
//
// Return: 0 – ok
// -1 – init failed
//

{
int j;
struct sigaction act; // signal handling structure
sigset_t set; // set of process specified signals

if (Dio.Type == TYPE_ISA)
board_num = atoi(argv[6]);
else
board_num = atoi(argv[4]);

if((board_num > 3) || (board_num < 0))
{
fprintf( stderr,
“dio task number: %d. Value must be 0 - 3. \n”,
board_num);
fflush( stderr );
return(-1);
}

sprintf(task_name, “dio%d”, board_num);

#ifdef HOT_BACKUP
if (HotBackup_Initialize_HealthRegister(task_name))
return (FAILURE);
#endif

printf("%s: Running at BASE: 0x%x, IRQ: %d\n",
task_name, BASE, IRQ);

logging = FALSE;
for (j=0; j<argc; j++)
if (stricmp(argv[j], “-L” ) == 0)
{
logging = TRUE;
break;
} //

//
/
INITIALIZATION /
/
/
// RE-SPECIFY THE SIGNALS RECIEVED BY MAIN TO IGNORE A BROKEN FIFO/PIPE

sigaddset( &set, SIGPIPE );
act.sa_flags = 0;
act.sa_mask = set;
act.sa_handler = SIG_IGN; //signal handler set to ‘ignore’
sigaction( SIGPIPE, &act, NULL ); //ignore fifo broken pipe signal


// GET A PROXY TO MAIN FOR THE INTERRUPT HANDLER TO KICK
if( (proxy = qnx_proxy_attach( 0, 0, 0, 0 ) ) == -1 )
{
fprintf( stderr,"%s: Unable to attach proxy. \n%s\n",
task_name, strerror(errno) );
return(-1);
}

My_pid = getpid();
My_nid = getnid();

// ATTACH THE HANDLER TO THE DIO INTERRUPT
if( qnx_hint_attach( IRQ, &handler, FP_SEG( &int_sequence)) == -1 )
{
fprintf( stderr,"%s: fatal error: unable to attach interrupt
handler\n",
task_name );
return(-1);
}

return(0);

} // init_dio



void process_dio_board(DIO_EVENT *p_dio_event, UBYTE * invert_mask )
{
static UDWORD seq_delta= 0; // difference between sequences
UBYTE han_idx;

han_idx = han_sequence % NUM_BUFFERS;

p_dio_event->nanotime = cycles_to_double
(dio48_points[han_idx].cycles);

// Djenkins - cycles should removed

// p_dio_event->cycles.h = dio48_points[han_idx].cycles.h;
// p_dio_event->cycles.l = dio48_points[han_idx].cycles.l;

p_dio_event->headroom = int_sequence - han_sequence;
p_dio_event->sequence = (UDWORD) dio48_points[han_idx].sequence;
p_dio_event->points[0] = (UBYTE)dio48_points[han_idx].port0a;
p_dio_event->points[1] = (UBYTE)dio48_points[han_idx].port0b;
p_dio_event->points[2] = (UBYTE)dio48_points[han_idx].port0c;
p_dio_event->points[3] = (UBYTE)dio48_points[han_idx].port1a;
p_dio_event->points[4] = (UBYTE)dio48_points[han_idx].port1b;
p_dio_event->points[5] = (UBYTE)dio48_points[han_idx].port1c;

perform_logic_inversions(&p_dio_event->points[0],
invert_mask,
NUM_DIO_ADDRESS_PER_BOARD);

clock_gettime(CLOCK_REALTIME, &p_dio_event->rtclock);

// check sequence & post error to stderr if mismatch
if((han_sequence + seq_delta) != p_dio_event->sequence)
{
fprintf(stderr,
“%11.5f: %s: INTERRUPT STACK OVERFLOW - int %ld handler %ld delta
%ld\n”,
p_dio_event->nanotime, task_name, han_sequence,
p_dio_event->sequence, seq_delta );
fflush( stderr );
seq_delta = p_dio_event->sequence - han_sequence;
}

} // process_dio_board


display_dio_event(DIO_EVENT * p_dio_event)

{
// static BOOL first_in = FALSE;
// static DIO_EVENT old_event;
int i, j;
int dio_pt_idx;

// if (!first_in)
// {
// memcpy(&old_event, p_dio_event, sizeof(DIO_EVENT));
// first_in = TRUE;
// }

printf("\fDIO%02d Sequence %d\n\n", p_dio_event->dio,
p_dio_event->sequence);

for (i = 0; i < NUM_DIO_ADDRESS_PER_BOARD; i++)
{
for (j = 0; j < 8; j++)
{
dio_pt_idx = NUM * 8 * NUM_DIO_ADDRESS_PER_BOARD + i*8+j;

if (dio_pt_idx < I_DIO_EOL)
printf(":%-8s %1s", dio_attrib[dio_pt_idx].pt_name,
(test_bit(i *8 + j, &p_dio_event->points[0]) ? “Y” : “N”));

}
printf(":\n");

} // for i

} //

void print_usage_and_exit()
{
printf ("\n\n");
printf (“ISA usage: dio ISA BASE_ADDR 0x140 INTERRUPT 4 0 &\n”);
printf (“PCI usage: dio PCI ICS DIO-48 0 &\n”);
printf (" base and address can be either hex (0x) or decimal\n");
printf ("\n\n");
exit (-1);
}


//
/* MAIN */
/
/

void main(int argc, char ** argv)
{
pid_t rpid = INV_PID;
pid_t timer_proxy;
int status; // local scratch
static UBYTE invert_mask[NUM_DIO_ADDRESS_PER_BOARD];
int message[6]; // to keep health ping happy

//
// SCuM, 9/24/97 – added rollover logic so 1st time thru is truly
// unique, and I/O distributor(s) can toss the packet it necessary.
//
int_sequence = IO_RESTART_SEQUENCE; // set so CYC can assume IOC
restarted

if (argc >= 5)
{
if (strcmp(“ISA”,argv[1]) ==0)
{
SetISA_CardObject(&Dio, argc, argv, TRUE); // True yields
verbose
BASE = Dio.BaseAddr1;
}
if (strcmp(“PCI”,argv[1]) ==0)
{
SetPCI_CardObject(&Dio, argc, argv, TRUE); // True yields
verbose
BASE = Dio.BaseAddr2;
}
}

if (BASE == 0)
{
printf ("\ndio: base_address not assigned!\n");
print_usage_and_exit();
}

status = init_dio( argc, argv);
if (status == -1)
{
exit(0);
} // if


// INIT HANDLER INDEX TO BUFFERS
han_sequence = 0;

init_invert_logic_mask( &dio_attrib[(board_num *
NUM_DIO_ADDRESS_PER_BOARD*8)],
&invert_mask[0], NUM_DIO_ADDRESS_PER_BOARD);

// SETUP THE DIO48 TO GENERATE INTERRUPTS (DO AS LAST ITEM BEFORE INT
LOOP)
outp( BASE+0x0003, 0x9b ); // port 0 as input
outp( BASE+0x0007, 0x9b ); // port 1 as input
outp( BASE+0x000b, 0x00 ); // enable change of state intrpt

// RE-ENABLE INTERRUPTS ON THE DIO48 BOARD
outp( BASE+0x000F, 0x00 );

//
/* PROCESS INTERRUPT DATA LOOP - DO FOREVER */
/
/

// PACK THE DATA FOR THE CONSUMERS
dio_event.msg_id = DIO_UPDATE; // define message as dio update
dio_event.node = getnid();
dio_event.dio = NUM; // indicator of which dio was sender


read_points( );
process_dio_board(&dio_event, &invert_mask[0] );
han_sequence++;

while (send_message( &dio_in_distrib_pid, NODE_LOCAL,
DIO_IN_DISTRIB_PROCESS,
&dio_event, NULL, sizeof(DIO_EVENT), 0) != SUCCESS)
{
// printf(“DIO%d – waiting for dioin_distrib\n”, NUM);
sleep(2);
}


if (logging)
display_dio_event(&dio_event);


if ((status = timer_init(&timer_proxy, 2, 0, 2, 0)) != SUCCESS)
{
fprintf(stderr, “%s: timer_init() error[%d], task ABEND\n”,
task_name, status);
exit(-1);
}



while (1)
{
if (get_next_message (&rpid, &message, sizeof(message)) != SUCCESS )
continue;

if (rpid == timer_proxy)
continue;

if (rpid != proxy)
continue;

process_dio_board(&dio_event, &invert_mask[0] );

if (logging)
{
display_dio_event(&dio_event);
}

//
/
NOTIFY IOC CONSUMERS /
/
/

/-----------------------------------------------------------/
/* LOCATE AND SEND A COPY OF THE UPDATE TO THE IOC PROCESSOR /
/
USING TASK ‘dio_in_distrib’ /
/
-----------------------------------------------------------*/

send_message( &dio_in_distrib_pid, NODE_LOCAL, DIO_IN_DISTRIB_PROCESS,
&dio_event, NULL, sizeof(DIO_EVENT), 0);

// ---------------------------------
// INCREMENT SEQUENCE FOR NEXT EVENT
// ---------------------------------
han_sequence++;
} // while
// qnx_hint_detach( id );

}

“Jeffrey O L Jordan” <jljordan@wans.net> wrote in message
news:3BE7EA64.64326A3D@wans.net

Do I need to alter the code (below) because it shares IRQs with another
card? I have the following PCI cards installed:

Slot Description IRQ
1 AHA2940 10
2 DIO-48 10
3 <empty
4 DIO-48 11
5 <empty
6 DIO-48 12
7 <empty
8 Pamux n/a
9 Pamux n/a
10 Ethernet (905) 11
11 Ethernet (82557) 10
12 Rocketport (serial) 10

That’s a very odd list, I’ve never seen devices hook on interrupt 1
and 2 aside standard PC devices (keyboard and RTC)

Onboard:
Serial I/O 4/3
IDE (cd-rom) 15
Floppy 6

I don’t think interrupt 6 (floppy) can be share unless you disable
the device in the BIOS. Same for serial port 1.

[cut]

//
/
INTERRUPT HANDLER /
/
/

#pragma off( check_stack);

void read_points ( )

{

You are assuming the interrupt was generated by your board, it may
have been generated by the another board sharing the interrupt.
You should have a register on the board that indicates if an
interrupt was generated.

Why not reenable the interrupt at the end of the function?

// RE-ENABLE INTERRUPTS ON THE DIO48 BOARD
outp( BASE+0x000F, 0x00 );

I see that ii is global, (as oppose to being on the stack).
If the interrupt gets call recursevly ii might not be
equal to what you expect. Because int_sequence
is increated at the end of the ISR, a recursive call
to the ISR migh have ii point the the same index as
the previous ISR. That should not cause a crash though.


I’m not sure 100% if the module is allow in the interrupt,
I know that like a / in some case it can cause a SIGFPU,
which in a ISR is BAD :wink: It thing that would only happen
if the doing 200 % 0. Since you are using a define (NUM_BUFFERS)
you’re ok :wink:

// DETERMINE BUFFER TO USE
ii = int_sequence % NUM_BUFFERS ;



[cut]

I don’t see anything wrong with the code. Have you compiled
with the -zu flag?

With the given information I would guestimate the problem
is with sharing interrupt with some PC device like the floppy.

What if you install only one board on interrupt 5 for example.

Jeffrey O L Jordan <jljordan@wans.net> wrote:

First: I strongly recommend putting the irq handler, and any functions
called from it, in a different .c file from the rest of your application
and compiling that .c file with the options:
-Wc,-s -zu

This compiles it with stack checking disabled & with SS != DS. Both
are required for an irq handler. I did notice that you had the pragmas
for disabling stack checking – I recommend against using those primarily
because there is no error checking for pragmas – if you get one wrong,
it is just ignored.

i.e. if you did
#pragma check_stack(off)
#pragma off(checkstack)
#pragma off(stack_check)

The compiler will discard both of those without complaint.

Do I need to alter the code (below) because it shares IRQs with another
card? I have the following PCI cards installed:

Your irq handler should query your card to see if it generated the irq
or not. This is the main change when handling a shared irq. Usually
this involves reading a status register on the card. It must also
acknowledge the irq – tell the card to drop the line – if it is your
card’s irq, otherwise you will get infinite interrupts.

In general, any variables that are accessed/updated in both the irq
handler and at process type should be declared volatile.


// DELAY TO ALLOW TRAPPING OF POINTS NOT DETECTED BY THIS INTERRUPT
(HARDWARE PROBLEM)
// delay_end = rdtsc32() + DELAY;
do
{
delay_cycles = rdtsc32();
}
while(delay_cycles < delay_end);

How long could this loop last? I thought rdtsc returned unsigned values.
Shouldn’t you be working with unsigneds, not signeds here?


-David

QNX Training Services
I do not answer technical questions by email.

Mario Charest <mcharest@clipzinformatic.com> wrote:

“Jeffrey O L Jordan” <> jljordan@wans.net> > wrote in message
news:> 3BE7EA64.64326A3D@wans.net> …
Do I need to alter the code (below) because it shares IRQs with another
card? I have the following PCI cards installed:

Slot Description IRQ
1 AHA2940 10
2 DIO-48 10
3 <empty
4 DIO-48 11
5 <empty
6 DIO-48 12
7 <empty
8 Pamux n/a
9 Pamux n/a
10 Ethernet (905) 11
11 Ethernet (82557) 10
12 Rocketport (serial) 10


That’s a very odd list, I’ve never seen devices hook on interrupt 1
and 2 aside standard PC devices (keyboard and RTC)

The irq numbers are in the column on the right, the SLOT number is
on the left. He isn’t hooking 1 or 2.

-David

QNX Training Services
I do not answer technical questions by email.

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:9s911f$mo8$2@nntp.qnx.com

Mario Charest <> mcharest@clipzinformatic.com> > wrote:

“Jeffrey O L Jordan” <> jljordan@wans.net> > wrote in message
news:> 3BE7EA64.64326A3D@wans.net> …
Do I need to alter the code (below) because it shares IRQs with another
card? I have the following PCI cards installed:

Slot Description IRQ
1 AHA2940 10
2 DIO-48 10
3 <empty
4 DIO-48 11
5 <empty
6 DIO-48 12
7 <empty
8 Pamux n/a
9 Pamux n/a
10 Ethernet (905) 11
11 Ethernet (82557) 10
12 Rocketport (serial) 10


That’s a very odd list, I’ve never seen devices hook on interrupt 1
and 2 aside standard PC devices (keyboard and RTC)

The irq numbers are in the column on the right, the SLOT number is
on the left. He isn’t hooking 1 or 2.

Doh!!! Thanks!



-David

QNX Training Services
I do not answer technical questions by email.

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:9s90tn$mo8$1@nntp.qnx.com

Jeffrey O L Jordan <> jljordan@wans.net> > wrote:

First: I strongly recommend putting the irq handler, and any functions
called from it, in a different .c file from the rest of your application
and compiling that .c file with the options:
-Wc,-s -zu

This compiles it with stack checking disabled & with SS != DS. Both
are required for an irq handler. I did notice that you had the pragmas
for disabling stack checking – I recommend against using those primarily
because there is no error checking for pragmas – if you get one wrong,
it is just ignored.

Not to mention that if you call a function that is outside the pragma, or
wasn’t compile with -Wc,-s it would probably barf at run time.

i.e. if you did
#pragma check_stack(off)
#pragma off(checkstack)
#pragma off(stack_check)

The compiler will discard both of those without complaint.

Do I need to alter the code (below) because it shares IRQs with another
card? I have the following PCI cards installed:

Your irq handler should query your card to see if it generated the irq
or not. This is the main change when handling a shared irq. Usually
this involves reading a status register on the card. It must also
acknowledge the irq – tell the card to drop the line – if it is your
card’s irq, otherwise you will get infinite interrupts.

In general, any variables that are accessed/updated in both the irq
handler and at process type should be declared volatile.


// DELAY TO ALLOW TRAPPING OF POINTS NOT DETECTED BY THIS INTERRUPT
(HARDWARE PROBLEM)
// delay_end = rdtsc32() + DELAY;
do
{
delay_cycles = rdtsc32();
}
while(delay_cycles < delay_end);

How long could this loop last? I thought rdtsc returned unsigned values.
Shouldn’t you be working with unsigneds, not signeds here?

For the sake of discussion; a very long loop would freeze
the computer not make it crash?!?

-David

QNX Training Services
I do not answer technical questions by email.

David Gibbs <dagibbs@qnx.com> wrote:


// DELAY TO ALLOW TRAPPING OF POINTS NOT DETECTED BY THIS INTERRUPT
(HARDWARE PROBLEM)
// delay_end = rdtsc32() + DELAY;
do
{
delay_cycles = rdtsc32();
}
while(delay_cycles < delay_end);

How long could this loop last? I thought rdtsc returned unsigned values.
Shouldn’t you be working with unsigneds, not signeds here?

Or, if you do comment the initialization of delay_end from rtdsc32()+DELAY
back in, couldn’t this end up (if you’re very unlucky) being an infinite
or nearly infinite loop? i.e. if rtdsc32 + DELAY = MAX_INT (or MAX_UNSIGNED)
or is very close to it, and the increment each time you call is more than

  1. (Which I think it will normally be). Sure, it’s not likely to happen,
    but do you want the chance?

-David

QNX Training Services
I do not answer technical questions by email.

Mario Charest <mcharest@clipzinformatic.com> wrote:

How long could this loop last? I thought rdtsc returned unsigned values.
Shouldn’t you be working with unsigneds, not signeds here?

For the sake of discussion; a very long loop would freeze
the computer not make it crash?!?

Hmmm… I think so.

-David

QNX Training Services
I do not answer technical questions by email.

Sorry, mistake on my part. That loop was commented, but should not
have been. As a side note, the task only freezes the computer when
I kill it. I was thinking that it is not exiting gracefully.

There appears to be more to it than that, though. As you all have
pointed out, it needs a lot of cleaning up. This may have worked
“pre PCI”, but not now that everything is PCI.

~ Jeff

David Gibbs wrote:

Mario Charest <> mcharest@clipzinformatic.com> > wrote:


How long could this loop last? I thought rdtsc returned unsigned values.
Shouldn’t you be working with unsigneds, not signeds here?

For the sake of discussion; a very long loop would freeze
the computer not make it crash?!?

Hmmm… I think so.

-David

QNX Training Services
I do not answer technical questions by email.


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/ \ | __ ) | ~Jeffrey Jordan jordanj@abc-naco.com
/ | \ | _ ( Phone: (610)630-2330x216 jljordan@wans.net
/ ++ \ | ) (
Fax: (610)630-2323
|
| |||/_| 2550 Blvd. o/t Generals, Norristown PA 19403
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

“Jeffrey O L Jordan” <jljordan@wans.net> wrote in message
news:3BE8479D.942E21D0@wans.net

Sorry, mistake on my part. That loop was commented, but should not
have been. As a side note, the task only freezes the computer when
I kill it. I was thinking that it is not exiting gracefully.

That’s important information. You say freeze, I assume you mean crash?
When you say kill it does that mean a something like CTRL-C?

As a rule of thumb i trap most signal that cause termination of the program
and call cleanup code before exiting.

PCI interrput are usually level senstive , as oppose to edge sensitive on
ISA.
If your board keeps the interrupt line active, all handlers that are hook to
that same
interrupt will be call constanting, resulting in a freeze.

If there are no other handler connected to this interrupt, the kernel will
disable it so it should not create a freeze situation. However your program
could crash at the next startup :wink:

  • Mario

Mario Charest <mcharest@clipzinformatic.com> wrote:

I see that ii is global, (as oppose to being on the stack).
If the interrupt gets call recursevly ii might not be
equal to what you expect. Because int_sequence
is increated at the end of the ISR, a recursive call
to the ISR migh have ii point the the same index as
the previous ISR. That should not cause a crash though.

Does such recursive calling of ISRs happen? I thought that an
interrupt handler could only be preempted by a higher priority
interrupt. So unless that interrupt shared the handler (unlikely),
recursion would not occur.

Have I misunderstood ?

William Morris
wrm@innovation-tk.com

“William Morris” <wrm@innovation-tk.com> wrote in message
news:9sbpkk$vp$1@inn.qnx.com

Mario Charest <> mcharest@clipzinformatic.com> > wrote:
I see that ii is global, (as oppose to being on the stack).
If the interrupt gets call recursevly ii might not be
equal to what you expect. Because int_sequence
is increated at the end of the ISR, a recursive call
to the ISR migh have ii point the the same index as
the previous ISR. That should not cause a crash though.

Does such recursive calling of ISRs happen? I thought that an
interrupt handler could only be preempted by a higher priority
interrupt. So unless that interrupt shared the handler (unlikely),
recursion would not occur.

Have I misunderstood ?

No you haven’t. I was talking if the same interrupt handler was
use to handle more then one level of interrupt. That is why
it said might :wink:


William Morris
wrm@innovation-tk.com

William Morris <wrm@innovation-tk.com> wrote:

Mario Charest <> mcharest@clipzinformatic.com> > wrote:
I see that ii is global, (as oppose to being on the stack).
If the interrupt gets call recursevly ii might not be
equal to what you expect. Because int_sequence
is increated at the end of the ISR, a recursive call
to the ISR migh have ii point the the same index as
the previous ISR. That should not cause a crash though.

Does such recursive calling of ISRs happen? I thought that an
interrupt handler could only be preempted by a higher priority
interrupt. So unless that interrupt shared the handler (unlikely),
recursion would not occur.

No, recursive calls to an irq handler will not happen. Repeated
calls, and nested calls (if your handler is pre-empted by a higher
priority interrupt) can happen, but not recursive.

-David

QNX Training Services
I do not answer technical questions by email.