Timer interrupt problems with CS-E9302

hi,

i am trying to write a module to use timer 2 interrupt. i am using Kenel 2.6.24-rc8.

i start my module by reading the current status of VIC registers(FIQStatus ans IRQSTatus).

        // First stage check
        r = __raw_readl ( EP93XX_VIC1_BASE + VIC_FIQ_STATUS); // check
        printk("FIQStatus = 0x%08X\n",r);
        r = __raw_readl ( EP93XX_VIC1_BASE + VIC_IRQ_STATUS); // check
        printk("IRQStatus = 0x%08X\n",r);

and i get :

  • FIQStatus = 0x00000000

    IRQStatus = 0x00000000


  • how come? at least system timer (irq=4, timer1) should be detected.(i have read other registers like for GPIOs or timers and work fine)

    is there any sort of protection that i cant access VIC register? or specila function? any hints?

    Thanks

    raedbenz:
    at least system timer (irq=4, timer1) should be detected.

    Now I understand your problem!

    From the chip’s docs I read that the status registers display the currently signaled interrupts.

    So they should be nonzero only in interrupt routines or when interrupts are masked in the CPSR.

    hi.

    i think it works now.

    but only as IRQ not FIQ .if i define it as FIQ the whole code hangs.

    do u have any idea y?

    thanks

    Please post some code

    //----------------select whether FIQ(1) or IRQ(0)  
    r = __raw_readl( EP93XX_VIC1_BASE + VIC_INT_SELECT); // preserve other bits
    __raw_writel (r | 0 , EP93XX_VIC1_BASE + VIC_INT_SELECT);//select interrupt 5 as FIQ
      
    // -------------------Enale VIC
    r = __raw_readl ( EP93XX_VIC1_BASE + VIC_INT_ENABLE); // preserve other bits
    __raw_writel ( r | TC2UI , EP93XX_VIC1_BASE + VIC_INT_ENABLE);	//enable interrupt of TC2
    

    then it goes into a while loop

    while(count>100)
    

    the count is incremented in ISR. with IRQ work, FIQ not.

    How do you set the FIQ handler?

    EDIT:

    while(count>100)
    

    the count is incremented in ISR.

    So you’re stuck in that loop for a few billion interrupts if it is entered with count == 101?

    denial:
    How do you set the FIQ handler?

    HI,
    	rv = request_irq( IRQ_EP93XX_TIMER2, tick_update, 0, "mytick", NULL); 
      	if ( rv ) 
      		{
        	printk(KERN_INFO "Can't get interrupt no %d\n", 5);
        	return 0;
      		}
    

    and the handler is

    irqreturn_t   tick_update(int irq, void *dev_id, struct pt_regs *regs)
    	{
      	count++;
      	__raw_writel(0x04 , EP93XX_TIMER2_CLEAR); //clear interrupt signal
    	return IRQ_HANDLED ;
    	}
    

    In Linux a FIQ handler can not be registered with request_irq.

    FIQs have highest priority and a lot of dedicated registers to guarantee low latency. Furthermore the ARM ARM says

    The FIQ vector is deliberately the last vector to allow the FIQ exception-handler software to be placed directly at address 0x0000001C or 0xFFFF001C, without requiring a branch instruction from the vector.

    FIQ handlers should therefore be very short. If you want to write the handler in C, you need to make sure the handler can be run from that address and has the correct prolog/epilog (see GCC documentation on attribute interrupt).

    There are functions in linux/arm/kernel/fiq.c that allow to claim the FIQ interrupt, copy a handler to the correct address, and get/set the dedicated registers for parameter exchange. You need to tell the copy function how long your function is. I don’t think there is a non-ugly way to determine this for a C function. Either use these functions or copy their behavior.

    For an example on how to use the functions take a look at the Linux floppy driver for RiscPC machines. They call the FIQ handler for every byte to/from the floppy.