Skip to content
Advertisement

Periodic task in a Linux kernel module

Currently I am developing GPIO kernel module for friendlyarm Linux 2.6.32.2 (mini2440). I am from electronics background and new to Linux.

The kernel module loaded at start-up and the related device file is located in /dev as gpiofreq.

At first time writing to device file, GPIO pin toggles continuously at 50kHz. At second time writing it stop toggling. At third time, it starts again, and so on.

I have wrote separate kernel module to generate freq. but CPU freezes after writing device file at first time. The terminal prompt is shown but I can not run any command afterwards.

Here is the code-snippet:

//calling function which generates continuous freq at gpio

static int send_freq(void *arg)
{
    set_current_state(TASK_INTERRUPTIBLE);
    for(;;)
    {
        gpio_set_value(192,1);
        udelay(10);
        gpio_set_value(192,0);
        udelay(10);
    }
    return 0;
}

Here is the device write code, which start or stop with any data written to device file.

if(toggle==0)
{
       printk("Starting Freq.n");
       task=kthread_run(&send_freq,(void *)freq,"START");
       toggle=1;
}
else
{
       printk("Operation Terminated.n");
       i = kthread_stop(task);
       toggle=0;
}

Advertisement

Answer

You are doing an infinite loop in a kernel thread, there is no room for anything else to happen, except IRQ and maybe other kernel thread.

What you could do is either

  • program a timer on your hardware and do your pin toggling in an interrupt

  • replace udelay with usleep_range

I suggest doing thing progressively, and starting in the kHz range with usleep_range, and eventually moving to cust om timer + ISR

in either case, you will probably have a lot of jitter, and doing such gpio toggling may be a good idea on a DSP or a PIC, but is a waste of resources on ARM + Linux, unless you are hardware assisted with pwm capable gpio engine.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement