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

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

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

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

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

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

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

person Jaydeep Dhrangdhariya    schedule 29.11.2011    source источник
comment
Почему вы хотите, чтобы ваша задача полностью выполнялась внутри ядра? Здравый смысл состоит в том, чтобы иметь вспомогательный процесс на уровне пользователя....   -  person Basile Starynkevitch    schedule 29.11.2011
comment
потому что я хочу частоту до 100 кГц. Я уже пробовал сценарий оболочки, который дает мне частоту переключения около 750 Гц. а также программа c, которая дает мне максимум 900 Гц. оба выполняют операции записи «1» и «0» в файле устройства /sys/class/gpio/gpio192/value.   -  person Jaydeep Dhrangdhariya    schedule 29.11.2011
comment
Я не думаю, что вы сможете достичь такой высокой частоты, не потребляя много ресурсов.   -  person shodanex    schedule 29.11.2011


Ответы (1)


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

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

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

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

Я предлагаю делать это постепенно, начиная с диапазона кГц с usleep_range и в конечном итоге переходя к пользовательскому таймеру + ISR.

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

person shodanex    schedule 29.11.2011
comment
Вам также может понадобиться перекомпилировать ядро ​​со значительно более высоким значением CONFIG_HZ, чтобы увеличить скорость прерывания таймера. - person caf; 01.12.2011