这个是在有开发板情况下,进行驱动编写
1.环境准备
看清楚很重要
在Ubuntu虚拟机上,前提配置好相对应版本arm-linux-gcc(不是说越高版本越好,最好是开发板配套的版本)
①准备开发板相对应Linux内核源码
②打补丁
③编译内核
(网上教程很多)
我的情况:
我的开发板是韦东山老师的S3C2440,提供的内核版本是2.6.22.6。
内核源码内通过查看arch/arm/configs目录,可以查看到不同开发板所需的编译参数设置。
不同版本arm-linux-gcc配置的glibc版本不一样,像之前用的arm-linux-gcc4.4.3使用的glibc是2.4,开发板不支持2.4,如果要升级的话会很麻烦,我就用了配套的arm-linux-gcc3.4.5,它的glibc是2.3.6。
2.编写驱动
搭建驱动框架
①首先要有
file_operations:
{
.open
.write
.read
}
按照我的理解是连接用户态和内核态程序的一个结构体
②入口函数注册驱动
出口函数卸载驱动
module_init(first_drv_init);
module_exit(first_drv_exit);
③给内核更多信息
利用udev机制自动创建设备节点
/dev/firstdrv
firstdrv_class = class_create(THIS_MODULE,"firstdrv");
firstdrv_class_dev=class_device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"firstdrv");
完整驱动框架代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev;
//打开/dev设备对应的函数
static int first_drv_open(struct inode *inode,struct file *file)
{
printk("first_drv_open\n");
return 0;
}
//写入/dev设备对应的函数
static ssize_t first_drv_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos)
{
printk("first_drv_write\n");
return 0;
}
//用file_operations结构体保存对应的函数
static struct file_operations first_drv_fops={
.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,
};
//主设备号
int major;
//驱动注册
int first_drv_init(void)
{
//0是自动分配主设备号,把file_operations保存到内核主设备号中,/proc/devices文件可以查看
major=register_chrdev(0,"first_drv",&first_drv_fops);
//创建类
firstdrv_class = class_create(THIS_MODULE,"firstdrv");
if(IS_ERR(firstdrv_class))
{
return PTR_ERR(firstdrv_class);
}
//在/dev自动创建设备
firstdrv_class_dev=class_device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"firstdrv");
if(unlikely(IS_ERR(firstdrv_class_dev)))
{
return PTR_ERR(firstdrv_class_dev);
}
return 0;
}
//驱动注销
void first_drv_exit(void)
{
unregister_chrdev(major,"first_drv");
class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
3.编写Makefile
CURRENT_PATH:=$(shell pwd)
#内核源码所在位置
LINUX_KERNEL_PATH:=/home/chouti/linux-2.6.22.6
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules clean
rm -rf modules.order
obj-m += first_drv.o
直接
make
如果成功的话回生成ko文件。
#安装驱动
insmod first_drv.ko
#查看驱动
lsmod
#卸载驱动
rmmod first_drv.ko
3.使用驱动代码
#include
#include
#include
#include
int main(int argc,char **argv)
{
int fd;
int val=1;
fd=open("/dev/firstdrv",O_RDWR);
if(fd<0)
printf("open fail!\n");
write(fd,&val,4);
return 0;
}
用arm-linux-gcc 编译
arm-linux-gcc first_drv_test.c -o first_drv_test
./first_drv_test
#输出
first_drv_open
first_drv_write