Периодическая задача в модуле ядра Linux

В настоящее время я разрабатываю модуль ядра GPIO для friendlyarm Linux 2.6.32.2 (mini2440). Я из электроники и новичок в Linux.

Модуль ядра, загруженный при запуске, и соответствующий файл устройства находится в /dev как gpiofreq.

При записи в первый раз в файл устройства GPIO-контакт непрерывно переключается на 50 кГц. Во второй раз его запись прекращается. В третий раз он начинается снова и т.д.

Я написал отдельный модуль ядра для генерации частоты. но CPU замерзает после записи файла устройства в первый раз. Отображается подсказка терминала, но после этого я не могу выполнить какую-либо команду.

Вот фрагмент кода:

//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;
}

Вот код записи устройства, которые запускаются или останавливаются с любыми данными, записанными в файл устройства.

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;
}

Ответ 1

Вы делаете бесконечный цикл в потоке ядра, нет места ни для чего другого чтобы произойти, кроме IRQ и, возможно, другого потока ядра.

Что вы можете сделать, это либо

  • запрограммируйте таймер на вашем аппаратном обеспечении и переведите курсор в прерывание

  • заменить udelay на usleep_range

Я предлагаю постепенно делать что-то и начинать в диапазоне кГц с помощью usleep_range и, в конечном итоге, переходить к режиму cust om timer + ISR

в любом случае у вас, вероятно, будет много дрожания, и такое переключение gpio может быть хорошей идеей на DSP или PIC, но это пустая трата ресурсов на ARM + Linux, если только вы не аппаратно с pwm-совместимый движок gpio.