Hardware Interrupt

Hy, i am trying to write a program in qnx, that will configure the Timer Counter of my ARM 9 controller, to generate a interrupt every 250 us. The problem is that i don’t know exactly how to attach a ISR to the timer intrerrupt? I read that there is a interruptAttach method that can help, but i don’t believe that i use it if i have a hardware interrupt (from the Timer counter). So i went on with trying to manualy link the ISR with the timer interrupt. That’s why I wrote in the interrupt vector address the address of the function witch i want to be a ISR. I am not sure that i have to mmap that functions address, but i read it on a site, so i tried it. Before I configure the timer i check to see what interrupts are enabled. After the configuration I recheck the interrupt and the 26’s interrupt(Timer counter 3) is enabled, so i think that the interrupt is generated. The problem must reside in the ISR, and the linkage with the interrupt. Can someone explain to me how can i attach the ISR to the timer interrupt, or any other interrupt, in Qnx?

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <hw/inout.h>
#include "at91sam9260.h"
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <errno.h>
#include <sched.h>
#include <sys/netmgr.h>
#include <sys/syspage.h>
#include <assert.h>
#include <time.h>
#include <sys/neutrino.h>


#define AIC_BASE 0xFFFFF000
#define TC_BASE 0xFFFDC000
#define TC_LENGHT 0x4000

void timerISR()
{
	printf("In the ISR");
}


uintptr_t aicHandle;

uintptr_t counterHandle,isrHandle;

int main(int argc, char *argv[]) {
	int i;
	printf("Welcome to the Irq \n");

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

	// mapping the memory zone to a handle

	aicHandle = mmap_device_io(AT91_AIC_SIZE,AT91_AIC_BASE);

	if(aicHandle==MAP_DEVICE_FAILED)
	{
		printf("Error in mapping the memory zone for AIC\n ERROR:%s\n",strerror(errno));
		return -1;
	}
	printf( "The vector adresses are:\n" );

	for (i = 0; i < 32; i++)
	printf("%d:%X   en:%X\n ",i,in32(aicHandle + AT91_AIC_SVR(i)),in32(aicHandle+AT91_AIC_IMR)&(1<<i));

	printf("Now trying to put a timer interupt");

	counterHandle = mmap_device_io(TC_LENGHT,TC_BASE);

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

	printf("Succesful map");


#define TC_BCR 0xC0
#define TC_BMR 0xC4
#define TC_CCR0 0x00// i am using timer 3 whitch has a MCK/32 clock = 1.5 MHz freqency
#define TC_CV  0x10  //counter value
#define TC_CMR0 0x04


#define TIMER_CLOCK3 0x2
#define WAVE 1<<15
	//timer value for a 1.5 MHz Clock with has a period of 0.66 microseconds => 380*0.66 = 250.8 us
#define TIMER_VALUE 31000
#define TC_IER0 0x24
#define TC_IMR0 0x2C


#define TIMER_INTERRUPT_VECT AT91_AIC_SVR(26)
#define TIMER_INTERRUPT_MODE_REG AT91_AIC_SMR(26)

	out32(counterHandle+TC_BCR,0x0);//sync off
	out32(counterHandle+TC_BMR,0x0);//block mode register set to activate internal clocks for all the timers
	out32(counterHandle+TC_CCR0,0x1);//chanel 0 control register set to activate clock
	//chanel 0 mode register clock = MCK/32= 1.5 MHz
	out32(counterHandle+TC_CMR0,TIMER_CLOCK3|WAVE);
	// timer value
	out32(counterHandle+TC_CV,TIMER_VALUE);
	//enableing the counter overflow intrerupt
	out32(counterHandle+TC_IER0,0x01);
	//enableing the counter overflow intrerupt from the mask registre
	out32(counterHandle+TC_IMR0,0x01);

	printf("Done with the timer configuration, should raise a intrerupt every 250 us\n");

	printf("Setting the intrerrupt addres for the ISR\n");

	printf("Mapping the interrupt handler \n");

	isrHandle = mmap_device_io(0x4000,&timerISR);

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



	//interrupt priority 5
	out32(aicHandle+TIMER_INTERRUPT_MODE_REG,0x5);
	//setting the ISR  address
	out32(aicHandle+TIMER_INTERRUPT_VECT,isrHandle);
	//enableing the interrupt
	out32(aicHandle+AT91_AIC_IECR,in32(aicHandle+AT91_AIC_IECR)|1<<26);


	int j;
	delay(2000);
	//;while(1){j=5;}
	for (i = 0; i < 32; i++)
		printf("%d:%X   en:%X\n ",i,in32(aicHandle + AT91_AIC_SVR(i)),in32(aicHandle+AT91_AIC_IMR)&(1<<i));

	out32(aicHandle+AT91_AIC_IECR,in32(aicHandle+AT91_AIC_IECR)&~(1<<26));
	return EXIT_SUCCESS;
}

You do not want to write to the vector, it will conflict with what ever is already there. You need to use InterruptAttach()/InterruptAttachEvent.

I tried adding the interrupt to qnx with the InterruptAtach() function but with no luck. I dont know what am i doing wrong. All i have to do is setup the peripheral to generate the interrupt and attach that interrupt to an the ISR. In the while(1) loop i wait for an interrupt and i dont get it(or i think o dont get it, because in the output of the pidin command my program is in the INTR state). Can someone give me a complete code that enables any hardware interrupt from a board?
If a run this final program with a out32(counterHandle+TC_CCR0,0x1|TC_SWTRG); command in at the end of the counter configuration, my board shuts down and restarts(prints the stack on the serial debug and reloads the kernel from SPI).I guess is the kernel gets an interrupt it encounters an error and restarts. Please help.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <hw/inout.h>
#include "at91sam9260.h"
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <errno.h>
#include <sched.h>
#include <sys/netmgr.h>
#include <sys/syspage.h>
#include <assert.h>
#include <time.h>
#include <sys/neutrino.h>


#define AIC_BASE 0xFFFFF000
#define TC_BASE 0xFFFDC000
#define TC_LENGHT 0x4000

int interrupt_id;


const struct sigevent *isr_handler(void *arg, int id)
{  printf("In the Interrupt Handler\n");

	if(InterruptMask( 26,interrupt_id) <0){
		printf( "Error while masking interrupt number 26\n" );
		exit(1);
	};
	printf("In the Interrupt Handler!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\n");

	return NULL;
}

uintptr_t aicHandle;

uintptr_t counterHandle,isrHandle;

int main(int argc, char *argv[]) {
	int i;
	printf("Welcome to the Irq \n");

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

	// mapping the memory zone to a handle

	aicHandle = mmap_device_io(AT91_AIC_SIZE,AT91_AIC_BASE);

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

	printf("Now trying to put a timer interupt");

	counterHandle = mmap_device_io(TC_LENGHT,TC_BASE);

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

	printf("Succesful map");


#define TC_BCR 0xC0
#define TC_BMR 0xC4
#define TC_CCR0 0x00// i am using time 3 whitch has a MCK/32 clock = 1.5 MHz freqency
#define TC_CV  0x10  //counter value
#define TC_CMR0 0x04

//defines for Timmer Counter 3, whitch is chanel 0 for the second group
#define TIMER_CLOCK3 0x2
#define WAVE 1<<15
	//timer value for a 1.5 MHz Clock with has a period of 0.66 microseconds => 380*0.66 = 250.8 us
#define TIMER_VALUE 31000
#define TC_IER0 0x24
#define TC_IMR0 0x2C
#define TC_SWTRG 1<<2


#define TIMER_INTERRUPT_VECT AT91_AIC_SVR(26)
#define TIMER_INTERRUPT_MODE_REG AT91_AIC_SMR(26)

	out32(counterHandle+TC_BCR,0x0);//sync off
	out32(counterHandle+TC_BMR,0x0);//block mode register set to activate internal clocks for all the timers
	//chanel 0 mode register clock = MCK/32= 1.5 MHz
	out32(counterHandle+TC_CMR0,TIMER_CLOCK3|WAVE);
	// timer value

	//here the TC_CV is read only out32(counterHandle+TC_CV,TIMER_VALUE);
	//enableing the counter overflow intrerupt

	out32(counterHandle+TC_IER0,0x01);
	//enable-ing the counter overflow intrerupt from the mask registre
	//out32(counterHandle+TC_IMR0,0x01);

	out32(counterHandle+TC_CCR0,0x1);//chanel 0 control register set to activate clock

	printf("Done with the timer configuration, should raise a intrerupt every 250 us\n");

	printf("Setting the intrerrupt addres for the ISR\n");

	/*printf("Mapping the interrupt handler \n");

	isrHandle = mmap_device_io(0x4000,&timerISR);

		if(counterHandle==MAP_DEVICE_FAILED)
		{
			printf("Error in mapping the memory zone for Timer \n ERROR:%s\n",strerror(errno));
			return -1;
		}
	//interrupt priority 5
	out32(aicHandle+TIMER_INTERRUPT_MODE_REG,0x5);
	//setting the ISR  address
	out32(aicHandle+TIMER_INTERRUPT_VECT,isrHandle);
	//enableing the interrupt

*/
	/*		for (i = 0; i < 32; i++)
			printf("%d:%X   en:%X\n ",i,in32(aicHandle + AT91_AIC_SVR(i)),in32(aicHandle+AT91_AIC_IMR)&(1<<i));
	*/

	out32(aicHandle+AT91_AIC_IECR,in32(aicHandle+AT91_AIC_IECR)|1<<26); //activating the interrupt

	//InterruptEnable();

	printf( "The vector adresses are2\n" );
    printf("Setting Interrupts\n");

  interrupt_id = InterruptAttach (26, isr_handler, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK);
  printf("Interrupt id:%d\n",interrupt_id);
  if(interrupt_id < 0){
		printf( "Error in ataching interrupt 26\n" );
		exit(1);
	};

  printf("Now waiting for interrupts\n");

  while (1)
     {
         InterruptWait (NULL, NULL);
         printf("Out of intr\n");
         exit(1);

         /*if(InterruptUnmask(26,interrupt_id) <0){
         		printf( "Error while unmasking interrupt number 26\n" );
         		exit(1);
         	};
         	*/

     }

	//delay(2000);
	//;while(1){j=5;}

	for (i = 0; i < 32; i++)
		printf("%d:%X   en:%X\n ",i,in32(aicHandle + AT91_AIC_SVR(i)),in32(aicHandle+AT91_AIC_IMR)&(1<<i));

	out32(aicHandle+AT91_AIC_IECR,in32(aicHandle+AT91_AIC_IECR)&~(1<<26));
	return EXIT_SUCCESS;
}

BelieverX,

Printf is not interrupt safe (look at the help doc’s on printf). So it’s very likely that the printf’s in your interrupt handler are causing problems.

That’s one reason most people use interruptAttachEvent instead of InterruptAttach so that it is easier to debug because you don’t have a pure ISR routine.

Tim