Linux内核模块中的周期性任务

Linux内核模块中的周期性任务,linux,linux-kernel,task,kernel-module,gpio,Linux,Linux Kernel,Task,Kernel Module,Gpio,目前,我正在为friendlyarm Linux 2.6.32.2(mini2440)开发GPIO内核模块。我来自电子行业,刚接触Linux 启动时加载的内核模块和相关设备文件位于/dev的gpiofreq中 第一次写入设备文件时,GPIO引脚以50kHz的频率连续切换。在第二次写入时,停止切换。第三次,它会再次启动,以此类推 我已经编写了单独的内核模块来生成freq。但在第一次写入设备文件后,CPU会冻结。显示终端提示,但之后无法运行任何命令 以下是代码片段: //在gpio上生成连续频率的调

目前,我正在为friendlyarm Linux 2.6.32.2(mini2440)开发GPIO内核模块。我来自电子行业,刚接触Linux

启动时加载的内核模块和相关设备文件位于
/dev
gpiofreq

第一次写入设备文件时,GPIO引脚以50kHz的频率连续切换。在第二次写入时,停止切换。第三次,它会再次启动,以此类推

我已经编写了单独的内核模块来生成freq。但在第一次写入设备文件后,CPU会冻结。显示终端提示,但之后无法运行任何命令

以下是代码片段:

//在gpio上生成连续频率的调用函数
静态int发送频率(void*arg)
{
设置当前状态(任务可中断);
对于(;;)
{
gpio_设置_值(192,1);
乌德莱(10);
gpio_设置_值(192,0);
乌德莱(10);
}
返回0;
}
这是设备写入代码, 它以写入设备文件的任何数据开始或停止

if(切换==0)
{
printk(“起始频率”。\n”);
task=kthread_run(&send_freq,(void*)freq,“START”);
切换=1;
}
其他的
{
printk(“操作已终止。\n”);
i=kthread_stop(任务);
切换=0;
}

如果在内核线程中执行无限循环,那么就没有空间进行其他任何操作 除了IRQ和其他内核线程之外

你能做的就是

  • 在硬件上编程一个定时器,并在中断中切换pin

  • 用usleep_系列替换udelay

我建议循序渐进,从kHz范围开始,使用usleep_范围,最终转到cust om timer+ISR


在这两种情况下,您可能会有很多抖动,在DSP或PIC上执行这种gpio切换可能是一个好主意,但在ARM+Linux上是一种资源浪费,除非您使用支持pwm的gpio引擎进行硬件辅助。

为什么您希望您的任务完全在内核内运行?一般的看法是有一个用户级的助手进程…因为我希望频率高达100kHz。我已经尝试了一个shell脚本,它给了我750赫兹左右的切换频率。还有一个c程序,它给我的最大频率是900赫兹。两者都在“/sys/class/gpio/gpio192/value”设备文件上执行写入“1”和“0”操作。我认为您无法在不消耗大量资源的情况下实现如此高的频率。您可能还需要使用显著更高的
CONFIG_HZ
值重新编译内核,以提高计时器中断的速率。