Forum Discussion
Altera_Forum
Honored Contributor
11 years agoHi there, for those of you who are having trouble getting interrupts from the FPGA through to Linux, here are some pointers:
1. Qn: I've written a custom Linux driver to catch interrupts on the FPGA IRQ line with GIC offset of 72. I see no interrupts happening. What is going on?? Ans: If you are using a PIO core in Qsys to generate an interrupt, you need to manually enable the interrupts! Otherwise, the PIO core will never ever generate any interrupts (http://www.altera.co.uk/literature/ug/ug_embedded_ip.pdf pg.12-3) The Interrupt bit mask register (fancy name for the register to enable interrupts) is on offset 0x8 w.r.t PIO register base address. 2. Qn: The IRQ handler gets repeatedly called! This locks up the system as you cannot do a normal CTRL+C to the terminal since it is loaded as a Linux Kernel Device driver. Ans: By default, interrupts on the ARM are level based (logic high) and not edge triggered. When an interrupt is generated by a PIO core, you need to reset the interrupts on the PIO core manually or else the interrupt line will stay high forever (you can confirm this via SignalTap). Since the IRQ line from the FPGA is always high unless you reset it, the ARM gets interrupted repeatedly! The IRQ reset register is located on offset 0xc. Writing any value to this register would reset the interrupts on the PIO core and the IRQ signal would return back to logic low. 3. You can write to the IRQ bit mask register and IRQ reset register of the PIO core via SystemConsole. A more elegant method is to have your custom kernel driver write to the PIO registers directly (see http://zhehaomao.com/blog/fpga/2013/12/29/sockit-4.html)! 4. Qn: How do you make a custom Linux Kernel Driver?? Ans: -Check out these great tutorials to get you started: http://www.tldp.org/ldp/lkmpg/2.6/html/lkmpg.html ,http://zhehaomao.com/blog/fpga/2014/05/24/sockit-10.html -You can only build your custom Linux Kernel Driver on a Linux machine -Set up your terminal environment variables to point to the correct cross compiler: export PATH=.../altera-linux/linaro/gcc-linaro-arm-linux-gnueabihf-4.7-2012.11-20121123_linux/bin:$PATH -Locate the Linux kernel source code that you used to build your Linux kernel. If you are using a Yocto build flow, the path looks like: .../yocto/build/tmp/work/socfpga_cyclone5-poky-linux-gnueabi/linux-altera-dist-1.0-r1/linux-socfpga -The above step is crucial as Linux really really does not like it if you use a different kernel version to build your driver. For example, if you are using a 3.12 linux source code to build your kernel driver and try to load that kernel module on a 3.9 Linux version, it will throw errors that are extremely confusing to debug. -Use insmod <your kernel driver.ko> to load your custom Linux driver to your Linux kernel -Likewise, use rmmod <your kernel driver.ko> to unload your custom Linux driver -I have a simple example project where a custom written Linux driver registers interrupts from the FPGA user buttons. PM me for the Quartus Project, custom linux driver code and Makefile if you would like a simple example to get you started quickly. 5. One last tip, Linux kernel driver development is very different from that of a userspace linux program. It can get very frustrating at times! Hell, it took me 2 full days just to set up my environment to build a simple hello_world kernel driver!! But persevere through and don't be discouraged!