How to add a periodic timer callback to a Linux kernel module

I am working on a Linux kernel module that registers a callback for interrupts that come from the user board and puts the received data in a queue behind the char device interface that should be processed by the application. This module must constantly monitor and measure interrupts and data coming from the board, even if the interrupt does not come from the board, so it has another callback that starts according to time.

The current implementation uses the RTC interrupt as a constant timer source. I disable the RTC kernel drivers ( CONFIG_RTC_DRV_CMOS ) and request IRQ 8 and attach a timer callback as an RTC interrupt handler. Interrupts are generated every second from the RTC chip.

The problem is that we have to lose some of the Linux time management features in this way, because only one of the rtc-cmos or the board module can be downloaded right away (and obviously we chose the board module).

Target architecture - i386 PC.

I am not a kernel developer and therefore do not have a big picture in developing a kernel module, but I'm trying to find my way, and this is the closest to the solution that comes to my mind:

  • Somehow to share IRQ 8 between both modules (maybe like request_irq(8, rtc_handler, IRQF_SHARED, rtc_handler) ?) Or IRQ handlers with a chain.
  • Finding another way to bind a handler from the kernel module to an RTC interrupt, rather than registering for IRQ 8.
  • Searching for another source of 1-second timer events that can be used from the kernel module, perhaps there is a standard kernel API for this. I dont know.

I suggest that there might be a simple and standard way to do this, and I would be glad if someone commented on one of these solutions or suggested the others.

+7
linux interrupt linux-kernel embedded-linux linux-device-driver
source share
2 answers

The hrtimer Linux kernel high-resolution hrtimer is an option. http://lwn.net/Articles/167897/

That's what I'm doing:

 #include <linux/interrupt.h> #include <linux/hrtimer.h> #include <linux/sched.h> static struct hrtimer htimer; static ktime_t kt_periode; static void timer_init(void) { kt_periode = ktime_set(0, 104167); //seconds,nanoseconds hrtimer_init (& htimer, CLOCK_REALTIME, HRTIMER_MODE_REL); htimer.function = timer_function; hrtimer_start(& htimer, kt_periode, HRTIMER_MODE_REL); } static void timer_cleanup(void) { hrtimer_cancel(& htimer); } static enum hrtimer_restart timer_function(struct hrtimer * timer) { // @Do your work here. hrtimer_forward_now(timer, kt_periode); return HRTIMER_RESTART; } 
+10
source share

You probably want to use the tasklet, see linux/interrupt.h .

+1
source share

All Articles