This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Example for FIQ interrupt kernel module

Hi,

I'm using AM335x with PSP04.08.00.07 (Arago). How to write a code of FIQ interrupt request and FIQ handler for GPIO input in kernel space ?

Any simple example or tutorial link i can refer?

Thanks and Regards

keldy

  • Keldy,

    It might not be possible to access kernel data structures in FIQ mode. This will create some overhead. You won't be able use FIQ the same ways as you use IRQ. 

    Why do you need to use FIQ? How many interrupts are you expecting and what is the expected turn around time?

  • Hi,

    i want a fast response of interrupt, after detecting a rising edge of input logic high signal (GPIO), i need to output logic low to a GPIO pin. The time between rising edge of input and falling edge of output must be within 150ns, and the time of rising edge of input until next rising edge of input is 4.8us. that mean i need to toggle my output pin every 4.8us.

    Is it the IRQ possible to do that?

    Thanks and Regards

    Keldy      

  • Keldy,

    You wont be able to achieve this latency using IRQ. FIQ is what is required. But there will be another problem, if you've to toggle the output logic within 150ns, it will be real tough to achieve that. 

    Can you try a simple call to toggle a GPIO and observe the best latency you can achieve?

  • Keldy,

    Sorry, I didnt see your other post related to GPIO toggle. Looks like if that is not possible, how are you going to achieve 150ns interrupt latency?

  • Hi,

    The continuous toggle speed of a GPIO is 270ns.

    i not gonna to toggle a GPIO output in 150ns, i just need to toggle a GPIO output in 150ns after a rising edge of a GPIO input. From scope, i saw my GPIO output only will toggle after 500ns, after a rising edge of a GPIO input.

    Thanks and Regards

    Keldy  

  • Keldy,

    How did you achieve 500ns? Is it using FIQ/IRQ or just by polling?

  • Hi,

    By polling.

    Thanks

    Keldy 

  • Keldy,

    To enable FIQ you have to write a small handler function and pass on the function pointer and length to the function set_fiq_handler(). This will replace the FIQ vector at the offset 0xffff_001c in the exception vector table. Also you have to enable FIQ in Interrupt controller registers for the GPIO bank that you are using. Then you've to enable FIQ in CPSR register. This can be done using the function enable_fiq()

  • Hi,

    Any simple example of FIQ that i can refer ?

    By the way, i discover that i need more time in detecting a input signal, around 450ns, is there a way to increase the detecting input time?

    how to read certain bit of register instead of read the whole register?

    Thanks and Regards

    Keldy

  • All,

    please read this thread before digging deeper into FIQ usage: http://e2e.ti.com/support/dsp/sitara_arm174_microprocessors/f/791/t/212173.aspx

    Basically you can't use FIQ as it is reserved for secure devices.

    Regards.

  • Keldy,

    Grep for the FIQ functions in arch/arm/mach-omap2/ . You'll find sample implementations.

  • Hi,

    can you specify the file name? i cant found any related example.

    by the way, why my GPIO need around 450ns to read an input signal? while i can toggle my GPIO output in 270ns ?

    Thanks

    Keldy

  • Keldy,

    In my 2.6.37 code base the file arch/arm/mach-rpc/dma.c has fiq implementation. 

    You are reading a GPIO register and then writing it. So there are at least two read/write operations performed on GPIO registers. Each of them might be taking a good amount of time, which is reflecting clearly.

  • Hi,

    which file is the fiq-handler for dma.c ?

    Thanks

    Keldy

  • Keldy,

    The actual handler is written in assembly in the file arch/arm/lib/floppydma.S. Search for set_fiq_handler() in dma.c file.

  • Hi,

    i got error message "linux/linkage.h no such file and directory" when compiling the fig.c and fiq.S file, my Makefile is as following:

    KERNELDIR = /home/chunchoon/ti-sdk-am335x-evm-05.03.00.00/board-support/linux-04.06.00.07/
    INCLUDEDIR = /home/chunchoon/ti-sdk-am335x-evm-05.03.00.00/board-support/linux-04.06.00.07/include
    CROSS_COMPILE=arm-arago-linux-gnueabi-
    AS      =$(CROSS_COMPILE)as
    LD      =$(CROSS_COMPILE)ld
    CC      =$(CROSS_COMPILE)gcc
    CPP     =$(CC) -E
    AR      =$(CROSS_COMPILE)ar
    NM      =$(CROSS_COMPILE)nm
    STRIP   =$(CROSS_COMPILE)strip
    OBJCOPY =$(CROSS_COMPILE)objcopy
    OBJDUMP =$(CROSS_COMPILE)objdump
    CFLAGS +=  -O2 -Wall -D__KERNEL__ -DMODULE -I$(INCLUDEDIR)
    AFLAGS = -I$(INCLUDEDIR) -D__ASSEMBLY__ -x assembler-with-cpp
    all: fiq-example.o

    fiq-example.o: fiq-driver.c fiq-handler.S
    arm-arago-linux-gnueabi-gcc $(AFLAGS) -c -o fiq-handler.o fiq-handler.S
    arm-arago-linux-gnueabi-gcc $(CFLAGS) -o fiq-driver.o -c fiq-driver.c
    arm-arago-linux-gnueabi-ld -r -o fiq-example.o fiq-driver.o fiq-handler.o

    clean: rm -f *.o *~ core
     
    do my Makefile correct ?
     
    Thanks and Regards
    Keldy
  • Keldy,

    Why are you compiling this as a separate module. You can make this as part of your kernel build itself. Check for the Makefile/Kconfig files and include the files in your kernel build by adding required configs in your .config file using menuconfig, if required.

  • Hi,

    can i compile separately ?

    what is the command if i want to compile manually without makefile ?

    Thanks and Regards

    Keldy

  • Keldy,

    I'm not really sure about how modular the code is to make it as kernel module and insert it. Instead, the simplest way is to build the kernel by following the instructions below.

    http://processors.wiki.ti.com/index.php/AM335x_PSP_User's_Guide

    http://processors.wiki.ti.com/index.php/AMSDK_Linux_User%27s_Guide

  • Hi,

    Here my code for fiq kernel module (fiq-example.c):

    #include <linux/mman.h>
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/sched.h>
    #include <linux/slab.h>
    #include <linux/interrupt.h>
    #include <linux/io.h>
    #include <asm/page.h>
    #include <asm/fiq.h>
    #include <asm/irq.h
     
    #define GPIO_INT_NUMBER  99 //base on table 6-1 TRM
    #define GPIO1_BASE  0x4804C000
    #define GPIO_OE   0x0134
    #define GPIO_DATAIN  0x0138
    #define GPIO_DATAOUT  0x013C
    #define GPIO_CLEARDATAOUT 0x0190
    #define GPIO_SETDATAOUT  0x0194
     
    static struct fiq_handler fh = {  name: "fiq-testing" };
    static int __init toggle_init(void)
     {  
          void *fiqhandler_start;  
          unsigned int fiqhandler_length;  
          struct pt_regs regs;  
          extern unsigned char gpio_intr_start, gpio_intr_end;  
          fiqhandler_start = &gpio_intr_start;  
          fiqhandler_length = &gpio_intr_end - &gpio_intr_start;
           if (claim_fiq(&fh))  
          {   
                printk("couldn't claim FIQ.\n");   
                return -1;  
          }
         regs.ARM_r10 = GPIO1_BASE;
         set_fiq_handler(fiqhandler_start, fiqhandler_length);  
         set_fiq_regs(&regs);  
         enable_fiq(GPIO_INT_NUMBER);  
         return 0;
    }
     
    static void __exit toggle_exit(void)
    {  
          disable_fiq(GPIO_INT_NUMBER);  
          release_fiq(&fh);
    }
     
    module_init(toggle_init);
    module_exit(toggle_exit);
     
    Here the code for fiq handler(fiq-handler.S) :
     
    #include <linux/linkage.h>
    #include <asm/assembler.h>
    #define GPIO_CLEARDATAOUT 0x0190
    #define GPIO_SETDATAOUT  0x0194   
                                         .text
                                        .global gpio_intr_end
    ENTRY(gpio_intr_start)                
                                       ldr   r3, [r10, #GPIO_CLEARDATAOUT]   
                                       str   ip, [r3] 
    gpio_intr_end:
     

    Any advise to my code ?

    I have problem in writing the assembly code, i just refer the disassemble file to write, but i feel very weird of my assembly code. in my assembly code, i want to set bit 24th in register GPIO_CLEARDATAOUT of GPIO1. Any correction that i need to do?

    For my FIQ kernel module, what else i have miss for initialize the FIQ interrupt ? 

    Thanks and Regards

    Keldy

     

  • Keldy,

    I don't think your assembly code is proper. You are not specifying the value to be written to the GPIO_CLEARDATAOUT anywhere. Also, you are not doing any return from FIQ routine. You should write a "MOVS PC,R14" to switch back to the previous mode of execution.

  • Hi,
     
    #include <linux/linkage.h>
    #include <asm/assembler.h>
    #define GPIO_CLEARDATAOUT 0x0190
    #define GPIO_SETDATAOUT 0x0194
                                         .text
                                        .global gpio_intr_end
    ENTRY(gpio_intr_start)                
                                       ldr   r3, [r10, #GPIO_CLEARDATAOUT]  
                                       str   ip, [r3]
                                       movs pc,R14
    gpio_intr_end:
     
    what instruction i should write so that i can write value to the GPIO_CLEARDATAOUT ?
     
    Thanks and Regards
    Keldy
  • Keldy,

    Whatever value you want to write, you do a mov to any of the FIQ banked register. 

    e.g. "mov r9, #2" where value 2 will be written to r9.  

    Or else an efficient way will be:

    regs.ARM_r10 = (GPIO1_BASE + GPIO_CLEARDATAOUT);

    regs.ARM_r9 = 0xvalue; // Value you want to write

    And change the assembly like this. 

    ENTRY(gpio_intr_start)                
                                       str   r9, [r10]
                                       movs pc,R14
    gpio_intr_end:


  • Hi,

    Thanks for the reply.

    For compile, is it i need to modify the Makefile and Kconfig in "/board-support/linux-04.06.00.07/" ?

    Thanks and Regards

    Keldy

  • Keldy,

    If you open arch/arm/kernel/Makefile you'll see the line like this. 

    obj-$(CONFIG_FIQ)               += fiq.o

    This means that you should have "CONFIG_FIQ=y" line inside your .config file for present in the "board-support/linux-04.06.00.07" directory. 

    If this is present it will compile fiq.c. Similarly if you want to add your custom handler you've to add an entry in your Makefile and Kconfig file, to do it in a proper manner. Then you've to include the corresponding macro in the .config file. Since .config file is a generated file while running the defconfig or menuconfig step, it will be better you add it inside your defconfig file later. 

    Please refer to kernel build structure related documentation. You'll be able to understand better. 

    http://free-electrons.com/doc/training/linux-kernel/slides.pdf

  • Hi,

    in "board-support/linux-04-06.00.07/arch/arm/kernel", the Makefile have something like

    obj-$(CONFIG_FIQ)                += fiq.o fiqasm.o

    do i need to remove the "fiqasm.o" ?

    and in "board-support/linux-04-06.00.07/arch/arm/configs", the "am335x_evm_defconfig" file,  i cant found the "CONFIG_FIQ"

    Thanks and Regards

    Keldy

  • Keldy,

    For time being you can modify the fiqasm.S file with your code and change the required function names. 

    You've to add CONFIG_FIQ=y in your defconfig file and make sure that it is present in the .config file generated and also double check the fiq.c and fiqasm.S is also getting compiled.

  • Hi,

    is it mean that i have to compile separately the fiq-example.c and fiq-handler ?

    how to compile the fiq-example.c ?

    Thanks and Regards

    Keldy

  • Hi,

    when i try to compile fiq.c and fiqasm.S, it come out with error "FIQ_START" undeclared.

    do i need to define a value for FIQ_START in fiq.c?

    Thanks and Regards

    Keldy

  • Keldy,

    Can you fix these issues yourself? I'm actually busy with lot of other work. If there is anything critical, I can help you out.

  • Hi,

    Sorry for disturbing you.

    Thanks for your help.

    Keldy