Linuxカーネルモジュールの定期タスク
-
25-10-2019 - |
質問
現在、Friendlyarm Linux 2.6.32.2 (mini2440) 用の GPIO カーネル モジュールを開発しています。私はエレクトロニクスの出身ですが、Linux は初めてです。
起動時にロードされるカーネル モジュールと関連デバイス ファイルは次の場所にあります。 /dev
として gpiofreq
.
デバイス ファイルに初めて書き込むとき、GPIO ピンは 50kHz で連続的に切り替わります。2 回目の書き込みではトグルが停止します。3 回目では再び開始され、以下同様に続きます。
周波数を生成するために別のカーネルモジュールを作成しました。ただし、最初にデバイスファイルを書き込んだ後、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;
}
解決
カーネルスレッドで無限のループを行っていますが、IRQや他のカーネルスレッドを除いて、他に何も発生する余地はありません。
あなたができることはどちらかです
ハードウェアにタイマーをプログラムし、割り込みでピンを切り替えます。
ulay を usleep_range に置き換えます
段階的に実行し、usleep_range を使用して kHz 範囲で開始し、最終的にはカスタム タイマー + ISR に移行することをお勧めします。
どちらの場合でも、おそらく多くのジッターが発生するでしょう。このような gpio 切り替えを DSP または PIC で行うことは良いアイデアかもしれませんが、pwm 対応 gpio でハードウェア支援されていない限り、ARM + Linux ではリソースの無駄になります。エンジン。