task periodico in un modulo del kernel di Linux
-
25-10-2019 - |
Domanda
Al momento sto sviluppando modulo GPIO del kernel per friendlyarm Linux 2.6.32.2 (mini2440). Sono da sfondo l'elettronica e la nuova a Linux.
Il modulo del kernel caricati all'avvio e il file relativo dispositivo si trova nella /dev
come gpiofreq
.
Al scrittura prima volta in file di dispositivo, pin GPIO alterna continuamente a 50kHz. A seconda volta a scrivere smettere commutazione. Alla terza volta, si avvia di nuovo, e così via.
Ho scritto modulo del kernel separato per generare freq. ma CPU blocca dopo file del dispositivo di scrittura a prima volta. Il terminale, è mostrata ma non può eseguire qualsiasi comando seguito.
Ecco il codice-frammento:
//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;
}
Ecco il codice di scrittura del dispositivo, che avviare o arresto con tutti i dati scritti al file 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;
}
Soluzione
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.