Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

How to generate interrupts with the PCI-6602 in QNX using the MHDDK?

    Hello Guys,

can anybody help me to find out, which registers and bits must be set, to generate interrupts? I used the examples shipped with the DDK, my test-function looks like this

.....
tAddressSpace  Bar1;
    tTIO *board;
   
    Bar1 = bus->createAddressSpace(kPCI_BAR1);
    board = new tTIO(Bar1);

    //Reset GPCTR 0
    board->G01_Joint_Reset_Register.writeG0_Reset(1);

    //Disarm
    board->G0_Command_Register.writeG0_Disarm(1);

    //load initial value of 0
    board->G0_Load_A_Registers.writeG0_Load_A(0x10000000);
    board->G0_Command_Register.writeG0_Load(1);

    //set source to internal time base 3, the 80Mhz internal clock
    board->G0_Input_Select_Register.writeG0_Source_Select(30);
   
    //set gate to no gate
    board->G0_Input_Select_Register.writeG0_Gate_Select(30);
    board->G0_Mode_Register.writeG0_Gate_Polarity(1);
    board->G0_Mode_Register.writeG0_Trigger_Mode_For_Edge_Gate(3);
   
    board->G0_Mode_Register.writeG0_Loading_On_TC(1); //reload-mode

    //set counting direction to down
    board->G0_Command_Register.writeG0_Up_Down(0);
    board->Interrupt_G0_Enable_Register.writeG0_TC_Interrupt_Enable(1); //interrupts enable

    board->Global_Interrupt_Control_Register.writeGlobal_Interrupt_Enable(1);
   
    //arm counter
    printf("counter value is 0x%08lx\n", board->G0_Save_Registers.readRegister());
    board->G0_Command_Register.writeG0_Arm(1);
....

With this settings QNX crashes. The sense of it (later) is to provide a call like "sleep()" or "nanosleep()", which blocks until TC (is TC always 0, or can it be defined?) is reached.

Thanks
0 Kudos
Message 1 of 4
(8,575 Views)
So, QNX no longer crashes, it was a problem in my ISR. But the problem with the right registers remains.

The bit Global_Int (31) in the  Global_Interrupt_Status_Register (offset 0x754) is set, when an interrupt (every Interrupt from every counter?)occurs, right?
The bits Counter_x_Int(19-16) in the same register are set, when counter x generates an interrupt, right?

Furthermore, in the Gx_Status_Register(0x4..) the Gx_TC_Status bit(3) is also set during an interrupt, or just by reaching TC? These bits can be cleared by using the Gx_Interrupt_Acknowledge_Register.

But how are the first bits - Global_Int and Counter_x_Int - cleared? Now I clear them manually.
Is Global_int cleared automatically, when all Counter_x_Int bits are cleared? Now I just ignore it, but it would be useful in my ISR, if i would know how and when they are cleared and set.

Is there a State-Maschine or something else, which discribes the interrupt system? That would be really useful, I am a bit overstrained right now, with all that different possibilities.

P.S.: What does the Gx_Interrupt bit in the Gx_Status_Register do? The explanation isn't helpful.("This counter asserts an interrupt. TC or DMA interrupt is true an enabled") Can somebody explain?

Thanks

0 Kudos
Message 2 of 4
(8,560 Views)
Hi, Horst,

I would like to see how you resolved your QNX ISR issue; I am having the same problems, despite all the documentations and testing so far. I really appreciate it.

Joe
0 Kudos
Message 3 of 4
(8,488 Views)
Hello, I've done it in this way, but I still don't know, if it's right (but works):

//First, create a new thread, for handling the Interrupt, so the main-method can do something else (not in this example, here it just waits till the thread ends)
int main ( void )
    {    pthread_t t1;
        pthread_create(&t1,NULL,int_thread,NULL);   
        pthread_join(t1,NULL);
    }

void * int_thread (void *args)
    {       
        u32               serverHdl;
        int             i = 0;
        struct pci_dev_info     info;
       
        iBus*             bus;
       
        tAddressSpace          Bar1;
        tTIO             *board;
       
        unsigned long         counterValue1, counterValue2;
        int             iid;

        ThreadCtl (_NTO_TCTL_IO,NULL);
       
        if ( serverHdl = pci_attach ( 0 ) < 0 )
        {
            perror ( "pci_attach" );
            return NULL;
        }
   
        void *hdl;
        memset ( &info, 0, sizeof ( info ) );
        info.VendorId = kPCIVendorIdNationalInstruments;
        info.DeviceId = 0x1310;
       
        bus = acquireBoard("PXI4::2::INSTR"); // 4=BusNumber, 2=DeviceNumber, you get it from "pci -v" or from the pci_dev_info struct
            
        if(bus == NULL)
        {
            printf("Error accessing the PCI device.  Exiting.\n");
            return NULL;
        }
   
        //Intitialise Mite Chip.
       // I made a class out of it, but you can also use the function shipped with the examples
   
        Mite *mite = new Mite();
        mite->initMite(bus);
        delete mite;

        //new Counter0....
        Bar1 = bus->createAddressSpace(kPCI_BAR1);
        board = new tTIO(Bar1);
        //Reset GPCTR 0
        board->G01_Joint_Reset_Register.writeG0_Reset(1);
        //Disarm
        board->G0_Command_Register.writeG0_Disarm(1);
        //load initial value of 0
        board->G0_Load_A_Registers.writeG0_Load_A(0x4C4B400); // 1 sec
        board->G0_Command_Register.writeG0_Load(1);
        //set source to internal time base 3, the 80Mhz internal clock
        board->G0_Input_Select_Register.writeG0_Source_Select(30);
        //set gate to no gate
        board->G0_Input_Select_Register.writeG0_Gate_Select(30);
        board->G0_Mode_Register.writeG0_Gate_Polarity(1);
        board->G0_Mode_Register.writeG0_Trigger_Mode_For_Edge_Gate(3);
        board->G0_Mode_Register.writeG0_Loading_On_TC(1); //Reload-Mode
        //set counting direction to down
        board->G0_Command_Register.writeG0_Up_Down(0);
        board->Interrupt_G0_Enable_Register.writeG0_TC_Interrupt_Enable(1); //Interrupts enable
        //arm counter
        printf("counter value is 0x%08lx\n", board->G0_Save_Registers.readRegister());
        board->G0_Command_Register.writeG0_Arm(1);
   
        //attach Interrupt: handler = ISR
        if(iid = InterruptAttach(_NTO_INTR_CLASS_EXTERNAL|info.Irq, handler,board,0,0) == -1) {return NULL;}
   
        board->Global_Interrupt_Control_Register.writeGlobal_Interrupt_Enable(1);
   
        while(1){
      
        counterValue1 = board->G0_Save_Registers.readRegister();
        counterValue2 = board->G0_Save_Registers.readRegister();
        if(counterValue1 != counterValue2)
            counterValue1 = board->G0_Save_Registers.readRegister();
        printf("counter value is now 0x%08lx\n",counterValue1);
   
        printf("G0_TC_STATUS: %x\n",board->G0_Status_1_Register.readG0_TC_St());   
       
        printf("\nWaiting for Interrupt...\n");

        InterruptWait(0, NULL);               //WAITS/BLOCKS until &event arrives

        printf("\nInterrupt recieved\n");
       
        counterValue1 = board->G0_Save_Registers.readRegister();
        counterValue2 = board->G0_Save_Registers.readRegister();
        if(counterValue1 != counterValue2)
            counterValue1 = board->G0_Save_Registers.readRegister();
        printf("counter value is now 0x%08lx\n",counterValue1);
   
        printf("G0_TC_STATUS: %x\n",board->G0_Status_1_Register.readG0_TC_St());
               
               
        //InterruptUnmask(4,NULL);
    }
       
        //Disarm
        board->G0_Command_Register.writeG0_Disarm(1);
       
        delete board;
        bus->destroyAddressSpace(Bar1);
        releaseBoard(bus);
   
    }
         
    //-------------------------------------------------------------------------------------------------
   
//this is the ISR      
    const struct sigevent* handler( void* board, int id ){
    struct sigevent event;
    event.sigev_notify=SIGEV_INTR; //interrupt event
   
    //InterruptMask(4,NULL);
   
    //Have a look, which Hardware generates the interrupt, if not our card then return NULL
   //my network card lies on the same irq, so have to check it
    if( ((tTIO*)(board))->Global_Interrupt_Status_Register.readCounter_0_Int() != 1)
    {
    return NULL;
    }
   
   //if it was our gptc0, then ack to clear the bit again
    if(((tTIO*)(board))->G0_Status_1_Register.readG0_TC_St() == 1)
    {
    ((tTIO*)(board))->Interrupt_G0_Ack_Register.writeG0_TC_Interrupt_Ack(1);
    return(&event);
    }
   
    return(NULL);  
    };

I hope this helps, it's just a modified example from the DDK. If you could help me with my second post, I would also appreciate this.

P.S.: saw you also in the QNX forum right now 😉
0 Kudos
Message 4 of 4
(8,479 Views)