Tarea periódica en un módulo de kernel de Linux
-
25-10-2019 - |
Pregunta
Actualmente estoy desarrollando el módulo de kernel GPIO para Friendlyarm Linux 2.6.32.2 (Mini2440). Soy de fondo electrónico y nuevo en Linux.
El módulo del núcleo cargado en el arranque y el archivo de dispositivo relacionado se encuentra en /dev
como gpiofreq
.
En la primera vez que escribe en el archivo del dispositivo, el pin GPIO se altera continuamente a 50 kHz. En la segunda vez escribiéndolo, deja de alternar. En tercera vez, comienza de nuevo, y así sucesivamente.
He escrito un módulo de kernel separado para generar frecuencias. Pero la CPU se congela después de escribir el archivo del dispositivo por primera vez. Se muestra el mensaje terminal, pero no puedo ejecutar ningún comando después.
Aquí está el código-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;
}
Aquí está el código de escritura del dispositivo, que se inicia o se detiene con los datos escritos en el archivo del dispositivo.
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;
}
Solución
Estás haciendo un bucle infinito en un hilo del núcleo, no hay espacio para que suceda nada más, excepto IRQ y tal vez otro hilo del núcleo.
Lo que podrías hacer es
Programe un temporizador en su hardware y realice su pin alternando en una interrupción
Reemplace Udelay con usleep_range
Sugiero hacer las cosas progresivamente y comenzar en el rango de KHZ con usleep_range, y finalmente pasar a Cust OM Timer + ISR
En cualquier caso, probablemente tendrá mucha fase, y hacer dicha alternativa GPIO puede ser una buena idea en un DSP o una foto, pero es un desperdicio de recursos en ARM + Linux, a menos que esté asistido por Hardware con PWM Capable GPIO motor.