Forum Discussion
Altera_Forum
Honored Contributor
13 years agouclinux PIO device driver interrupt handler not execute
Hi,
Thanks in advance for any help I can get. I have a NIOS2 w/MMU running uClinux v3.7. It's a DE2-115 development kit with Cyclone IV FPGA. I use the PIO megafunction to monitor input rising edge from the SMA pin and generate interrupt IRQ. I developed an uClinux device driver in the misc folder. All seem correct and compile, but the handler function doesn't seem like it was executed when I generate a pulse signal to the SMA. Here is my device driver code: in the probe function call - res_mem = platform_get_resource(pdev, IORESURCE_MEM, 0) - request_mem_region(res_mem->start, resource_size(res_mem), "GPIO_NAME") - of_iomap(pdev->dev.of_node, 0); - irq = irq_ofparse_and_map(pdev->dev.of_node, 0) - request_irq(irq, pps_gpio_irq_handler, 1, "GPIO_NAME", NULL); in the interrupt handler call static irqreturn_t pps_gpio_irq_handler(int irq, void *dev_id) { printk(KERN_ALERT "Trigger"); return IRQ_HANDLED; } If I execute command "cat /proc/interrupt", the driver was successful requested. 2: 0 NIOS2-INTC GPIO_NAME As you can see, the interrupt count didn't get incremented and "Trigger" was never print out after I apply a pulse signal to the SMA port. Is there a function call I am missing? or anything that I miss?14 Replies
- Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- All seem correct and compile, but the handler function doesn't seem like it was executed when I generate a pulse signal to the SMA. --- Quote End --- At first, please check whether the interrupt signal (irq No.2 in this case?) is asserted or not. This check is easily done by using your Signal Tap II. Kazu - Altera_Forum
Honored Contributor
--- Quote Start --- Hi, At first, please check whether the interrupt signal (irq No.2 in this case?) is asserted or not. This check is easily done by using your Signal Tap II. Kazu --- Quote End --- Hi Kazu, You are right about the irq signal isn't asserted. I took a screen shot of the signaltap II (attached) and find out the chip select and input clock isn't either. I use the PIO IP in the QSYS and configure it as follow. clk -> 50Mhz PLL s1 -> clock crossing bridge ->NIOS2 CPU data master bus reset -> clock and jtag reset lines external_connection -> ext_pins The PIO configuration are Width: 1 Input Edge Capture regiser -> Synchronously capture (check) Edge Type: Rising Interrupt: Generate IRQ (check) IRQ Type: Edge Any help is greatly appreciated. Thanks, Yeung - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- You are right about the irq signal isn't asserted. I took a screen shot of the signaltap II (attached) and find out the chip select and input clock isn't either. --- Quote End --- Did you set the 'interruptmask register' of your PIO core ? And how many frequencies did you use for capturing of Signal Tap II ? Kazu - Altera_Forum
Honored Contributor
Hi,
Thank you very much. I think this may causing the problem, but please correct me if I am mistaken, isn't interrupt mask register select enabled when the "Generate IRQ" is check in the QSYS? Yeung - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- isn't interrupt mask register select enabled when the "Generate IRQ" is check in the QSYS? --- Quote End --- In general, you must prepare functions to set and reset the bits of interrupt mask register in your driver, because let the kernel make it enable or disable. And you can also observe the status of interrupt mask register bits by your Signal Tap II. Kazu - Altera_Forum
Honored Contributor
I tried to do couple things in my uClinux device driver to enable the interrupt.
1) Enabling the PIO Core interrupt: Because my PIO base address is 0x00000060 on the a clock_crossing_bridge w/ base address of 0x08200000, my driver define base address is 0x082000060 (<-Is this correct?) # define ALTERA_PIO_BASE_ADDRESS 0x08200060 # define ALTERA_OFFSET_DATA 0x00 # define ALTERA_OFFSET_DIRECTION 0x01 # define ALTERA_OFFSET_IRQ_MASK 0x02 # define ALTERA_OFFSET_EDGE_CAPTURE 0x03 ... in probe function I have volatile int *base_addr = (int *) ALTERA_PIO_BASE_ADDRESS; ... *(base_addr + ALTERA_OFFSET_IRQ_MASK) = 0x01; //One input PIO from the SMA pin in the DE2-115, rising edge interrupt generator 2) __builtin_wrctl(3, 3); //irq2, write into ienable register (3) __builtin_wrctl(0, 1); //write 1 into status register (0) to enable PIE I got Kernel panic - not syncing: Oops Unable to handle kernel paging request at virtual address 08200000 ea = c70e418c, ra = c70e4178, cause =15 Did I write into or enable the wrong interrupt? my irq_mask is definite not turn on showing in the signaltapII. Any help is greatly appreciated. Yeung - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- 1) Enabling the PIO Core interrupt: Because my PIO base address is 0x00000060 on the a clock_crossing_bridge w/ base address of 0x08200000, my driver define base address is 0x082000060 (<-Is this correct?)# define ALTERA_PIO_BASE_ADDRESS 0x08200060# define ALTERA_OFFSET_DATA 0x00# define ALTERA_OFFSET_DIRECTION 0x01# define ALTERA_OFFSET_IRQ_MASK 0x02# define ALTERA_OFFSET_EDGE_CAPTURE 0x03 ... in probe function I have volatile int *base_addr = (int *) ALTERA_PIO_BASE_ADDRESS; ... *(base_addr + ALTERA_OFFSET_IRQ_MASK) = 0x01; //One input PIO from the SMA pin in the DE2-115, rising edge interrupt generator 2) __builtin_wrctl(3, 3); //irq2, write into ienable register (3) __builtin_wrctl(0, 1); //write 1 into status register (0) to enable PIE I got Kernel panic - not syncing: Oops Unable to handle kernel paging request at virtual address 08200000 ea = c70e418c, ra = c70e4178, cause =15 --- Quote End --- At first, please don't forget the existence of MMU. All cpu's memory accesses are filtered by it. So you must convert the virtual address 0x08200000 to I/O memory space one. According to the formal way, you should use the function 'ioremap' like
but for the convenience test, please try next codevolatile int *base_addr = ioremap(ALTERA_PIO_BASE_ADDRESS, 16);
And because cpu's control registers are controlled by the kernel core, you don't need to tamper those likevolatile int *base_addr = (int *) (ALTERA_PIO_BASE_ADDRESS | 0xe0000000);
There is also a formal way to set or reset these bits, so you should not touch control registers directly except the case you are sure what you do. Kazu__builtin_wrctl(3, 3); //irq2, write into ienable register (3) __builtin_wrctl(0, 1); //write 1 into status register (0) to enable PIE - Altera_Forum
Honored Contributor
Hi Kazu,
You are right. I have left out the virtual memory to be part of the base address. After I included the MMU, the interrupt handler function trigger when there is a rising edge. You have mentioned there is a formal way to set and reset the ienable and status register without implementing directly into the control registers. Which function call are you referring to? I apologize for another dope question regarding clearing the interrupt flag. Do I have to clear the "edge_capture" register in the interrupt handler function? *(ALTERA_BASE_ADDRESS + 0x03) = 0x00 Thanks again, Yeung - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- You have mentioned there is a formal way to set and reset the ienable and status register without implementing directly into the control registers. Which function call are you referring to? --- Quote End --- Please refer the file 'linux-*.*/include/linux/irqflags.h'. For example, 'local_irq_disable()' reset the PIE bit. --- Quote Start --- Do I have to clear the "edge_capture" register in the interrupt handler function? *(ALTERA_BASE_ADDRESS + 0x03) = 0x00 --- Quote End --- Please refer the data sheet of Altera's PIO core. How can you de-assert the interrupt signal for NiosII cpu ? In general, NiosII uses level triggered interruption. Kazu - Altera_Forum
Honored Contributor
Got it! Thanks for your help.
Do you know a good way to get time(second/usecond)? I tried to use the do_gettimeofday function call in the interrupt handler but with random timestamp return. Sometime it jump back time as well. If you may know, can you kindly point me to a right direction? Yeung