Cannot get FIQ to work properly on raspberry zero

Sietse Achterop s.achterop at rug.nl
Wed Jun 17 09:03:13 EDT 2020


   Hello List,
I have asked this before on several mailing lists, but still no solution,
so I am trying again here.

I'm having trouble with using FIQ interrupts with the ARM timer on raspberypi zero, (BCM2835 chip).
I created a kernel module, and the test version of this driver can be found in

   https://github.com/SietseAchterop/Batradio/blob/master/batradio_module/fiqtest_4.c

I made sure that FIQ is not used by USB by adding
    dwc_otg.fiq_fsm_enable=0 dwc_otg.fiq_enable=0 dwc_otg.nak_holdoff=0
to cmdline.txt in /boot

I first tried to use the regular sequence of functions to use.
In the init function:
   claim_fiq, set_fiq_regs, enable_fiq
In the exit function
   disable_fiq, release_fiq.

But I cannot find which irq number to use, e.g. using irq_of_parse_and_map
I tried several values. 0, 64, but nothing works.
So instead of the enable/disable functions I directly set the timer interrupt via the IRQFIQ register.

This works; a bit.
The fiq_handler only resets the ARM timer, increments a timer and toggles a LED.
I see the timer counting, the fiq being called.
But the rpi fairly quickly crashes.
In the, sometimes, 10 seconds that it runs I see the led flashing very irregular.

What is wrong here?
Has the irregularity something to do with suspend/resume?
Please find below the relevant snippets from the init and exit function of the driver.
And also the fiq_handler.

    Thanks in advance,
        Sietse

====== init_bat
       .....
   // directly set ARM timer registers
   TIMCNTR = 0x0000000;   // stop timer
   TIMLOAD = 100000-1;    // load value
   TIMCINT = 0;           // clear interrupt

   ret = claim_fiq(&bat_fh);
   if (ret) {
     printk("batradio: claim_fiq failed.\n");
     return ret;
   }
   
   set_fiq_handler(&batradio_handler, &batradio_handler_end - &batradio_handler);

   regs.ARM_r8  = (long)gpiospi;
   regs.ARM_r9  = (long)irqtimer;
   regs.ARM_r10 = (long)0;
   set_fiq_regs(&regs);

   TIMCNTR = 0x000000A2;   // start timer with interrupt, 23 bit counter
   IRQFIQ = 0xC0;          // timer interrupt to fiq directly via register
   //enable_fiq(64);
       ....

======  exit_bat
	....
   IRQFIQ  = 0x00;         // stop fiq interrupts
   TIMCNTR = 0x003E0000;   // stop ARM timer
   //disable_fiq(64);
         ....
	
======  batradio fiq handler
	.text
	.global batradio_handler
	.global batradio_handler_end

batradio_handler:
	stmdb sp!, {r6-r7}
	mov  r6, #0
	str r6, [r9, #0x40C]	// TIMCINT = 0 // clear interrupt

	mov r7, #0x2000		// 1 << CNVST
	add r10, r10, #1
	ands r6, r10, #0x0001	// set toggle speed
	bne off
	str r7, [r8, #40]	// led on
	ldmia sp!, {r6-r7}
	subs pc, lr, #4
off:	str r7, [r8, #28]	// led off
	ldmia sp!, {r6-r7}
	subs pc, lr, #4
batradio_handler_end:



More information about the Kernelnewbies mailing list