注:在写Linux 内核驱动,并将这一过程发生的技术,和菜鸟们可能会碰的问题进行一次解释,希望对后来都有用,阅读此文需要一定Linux基础,或者不要浪费时间,好品德看完全文要顶一下,看完此文你应该肻定会开发自己的字符驱动,请注意注解部分。
我反着来讲整个过程,讲解是为让人更快明白,有些术语不是标准的哦,对于正在找这个朋友此文就是你的宝,如果你乐意你可以给我付费。
第一步:内核加入到你设备中,整个调用驱动过程代码以下
MyTest::MyTest(QWidget *parent, const char *name, WFlags f):led(parent, name, f)
{
/* 1.int m_fd 是句柄 WIN32的名词 类的私有变量。private: int m_fd;
2.:: 这是名字空间符
3.open Linux打开设备的系统function
4. "/dev/pwcs", 这句话的解释 /dev 表示linux系统驱动 可以指示 内核工程中 如图
/pwcs 自定义的设备名称
5. O_RDWR 系统标准备读写宏
*/
m_fd = ::open("/dev/pwcs", O_RDWR); //..打开设备.
if (m_fd < 0) {
//..没有打开设备
}
/*1.connect 系统函数
2.0,1,这些指驱动自定义要控制设备的系列号 ,
3.SIGNAL(什么事件)
4.this 这是什么呀,自己查去
5.SLOT(事件动作)
*/
connect(0, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) ); //..
connect(1, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) );
//.......可以有很多
checkBoxClicked();
}
MyTest::~MyTest()
{
::close(m_fd); //..关闭设备
}
void MyTest::checkBoxClicked()
{
/* ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的参数个数如下:int ioctl(int fd, int cmd, …);其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数控制设备的I/O通道。
*/
::ioctl(m_fd, int(m_pwc1->isChecked()), 0);
::ioctl(m_fd, int(m_pwc2->isChecked()), 1);
::ioctl(m_fd, int(m_pwc3->isChecked()), 2);
::ioctl(m_fd, int(m_pwc4->isChecked()), 3);
}
}
第二步:增加内核驱动控制代码
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#define DEVICE_NAME &quot;pwcs&quot; //..注意这里 m_fd = ::open(&quot;/dev/pwcs&quot;, O_RDWR); 打开设备.
/*
connect(0, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) ); //..
connect(1, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) );
S3C64XX_GPK(XX) 来自这里 \u-kernel\arch\arm\mach-s3c64xx\include\mach\gpio.h
*/
static int power_gpios[] = {
S3C64XX_GPK(0), //..设备中要控制CPU的GPIO :0 connect自定义要控制设备的系列号
S3C64XX_GPF(14), //.. :1 connect自定义要控制设备的系列号
S3C64XX_GPA(2), //.. :2 connect自定义要控制设备的系列号
S3C64XX_GPF(13), //.. :3 connect自定义要控制设备的系列号
S3C64XX_GPK(1), //.. :4 connect自定义要控制设备的系列号
};
#define PW_GPIO_NUM ARRAY_SIZE(power_gpios) //..数组大小
static long power_gpio_ctrls_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
switch(cmd) {
case 0:
case 1:
if (arg > PW_GPIO_NUM) {
return -EINVAL;
}
gpio_set_value(power_gpios[arg], cmd); //..\u-kernel\arch\arm\mach-s3c64xx\include\mach\gpio.h
//printk(DEVICE_NAME&quot;: %d %d\n&quot;, arg, cmd);
break;
default:
return -EINVAL;
}
return 0;
}
static struct file_operations power_gpio_ctrl_dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = power_gpio_ctrls_ioctl,
};
static struct miscdevice power_gpio_ctrl_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME, //..注意这里
.fops = &power_gpio_ctrl_dev_fops,
};
static int __init power_gpio_ctrl_dev_init(void) {
int ret;
int i;
for (i = 0; i < PW_GPIO_NUM; i++) {
ret = gpio_request(power_gpios<i>, &quot;PWC&quot;); //..用户控制符 “PWC”注册时用
if (ret) {
printk(&quot;%s: request GPIO %d for ctrl failed, ret = %d\n&quot;, DEVICE_NAME,
power_gpios<i>, ret);
return ret;
}
s3c_gpio_cfgpin(power_gpios<i>, S3C_GPIO_OUTPUT);
gpio_set_value(power_gpios<i>, 0);
}
ret = misc_register(&power_gpio_ctrl_dev); //..注册
printk(DEVICE_NAME&quot;\tinitialized\n&quot;);
return ret;
}
static void __exit power_gpio_ctrl_dev_exit(void) {
int i;
for (i = 0; i < PW_GPIO_NUM; i++) {
gpio_free(power_gpios<i>);
}
misc_deregister(&power_gpio_ctrl_dev); //..干掉它
}
module_init(power_gpio_ctrl_dev_init); //..模块初始化 给open用的
module_exit(power_gpio_ctrl_dev_exit); //..模块初退出 给close用的
MODULE_LICENSE(&quot;GPL&quot;); //..模块许可授权 注意这个是必须的或者注册不了,其它方式我不说了,
//..给钱告 诉你。
MODULE_AUTHOR(&quot;IFOCOOL@QQ.COM&quot;); //..作者信息
第三步:使用make menuconfig 可以看到.
source &quot;drivers/char/Kconfig&quot; 在内核配置菜单Kconfig文件中增加以下内容注意以下两个图
在drivers/char/Kconfig的文件 menu &quot;Character devices&quot; 菜单下增加以下内容
config POWER_CTRL #配置关键字
tristate &quot;GPIO Power On/Off Ctrl&quot; #这段菜单名称
depends on CPU_S3C6410 #depends on CPU_S3C6410 表示还要这个菜单项前“CPU_S3C6410”看我写的LINUX
#专题里面有讲到。
default y #默为y
在drivers/char/Makefile的文件 增加以下内容
obj-$(CONFIG_POWER_CTRL) += power_gpio_ctrl.o #C文件编绎后目标文件 power_gpio_ctrl.c的目标文件
#CONFIG_POWER_CTRL=CONFIG+POWER_CTRL(注:这来自
Kconfig)
第四步:必须完成第三步后执行这一步
linux 命令台中执行: make menuconfig
进行字符驱动选择菜单如图
最后一步make内核 |