忙 好久没更新,SINA31s开始吃灰了 晚上写了个简单的字符设备驱动 发现不少的坑
芯灵思的环境搭得有点坑 譬如 如果需要编译应用程序,还得先执行一次lunch 配置好后,才能执行envsetup.sh进行配置 最后才能mmm编译应用 还有就是,琢磨了半天makefile 头都绕晕了 还是不知道怎么对单个驱动编译ko 只能把驱动加入Kconfig,编译整个内核,生成ko 可能是看代码的水平太次 最大的一个坑 Make menuconfig后,内核的配置丢失了…丢失了…失了…了… 居然还没有备份的deconfig文件 只能解压源码,换个姿势再来一次…… 楼主也彻底湿了
磕磕绊绊,最终还是调试好了简单的驱动 - #include "test.h"
- static int test_major = 0;
- static int test_minor = 0;
- int user_data;
- static struct class *test_class = NULL;
- static struct device *test_dev = NULL;
- static struct class_device *test_classdev[4];
- static int test_drv_open(struct inode *inode, struct file *file)
- {
- test_minor = MINOR(inode -> i_rdev);//取出次设备号
- printk(KERN_EMERG"test_drv_open,major=%d,minor=%d.....\n",test_major,test_minor);//大坑,用最高的打印优先级
- return 0;
- }
- static int test_drv_write(struct file *file,const char __user *buf,size_t count,loff_t* ppos)
- {
- int fd;
- printk(KERN_EMERG"test_drv_write.....\n");
- fd = copy_from_user(&user_data,buf,count); // copy_to _user();
- if(fd)
- {printk(KERN_EMERG"Got Nothings....\n");}
- else {printk(KERN_EMERG"Got val = %d..\n",user_data);}
- switch (test_minor)
- {
- case 0 : printk(KERN_EMERG"test_drv[%d] got the val = %d.\n",test_minor,user_data);
- break;
- case 1 : printk(KERN_EMERG"test_drv[%d] got the val = %d.\n",test_minor,user_data);
- break;
- case 2 : printk(KERN_EMERG"test_drv[%d] got the val = %d.\n",test_minor,user_data);
- break;
- case 3 : printk(KERN_EMERG"test_drv[%d] got the val = %d.\n",test_minor,user_data);
- break;
- default:
- break;
- }
- return 0;
- }
- static int test_drv_release(struct inode* inode, struct file* filp)
- {
- printk("test_drv_release.....\r\n");
- return 0;
- }
- static struct file_operations test_drv_fops = {
- .owner = THIS_MODULE,
- .open = test_drv_open,
- .write = test_drv_write,
- .release = test_drv_release,
- };
- static int test_drv_init(void)
- {
- int err;
- test_major = register_chrdev(0, "test_drv", &test_drv_fops);//动态分配系统主设备号
- if(test_major == -EBUSY)
- {
- printk(KERN_EMERG"Device registed failed...\n");
- }
- else{
- printk(KERN_EMERG"Device registed sucess,major = %d\n",test_major );
- }
- test_class = class_create(THIS_MODULE,"test_drv_class");//创建设备类
- if(!IS_ERR(test_class)) {
- err = PTR_ERR(test_class);
- printk(KERN_ALERT"Sucess to create test class,ERR=%d.\n",err);
- }
- /*
- test_dev = device_create(test_class,NULL,MKDEV(test_major,0),NULL,"test_drv");//创建设备 (单个设备)
- if(!IS_ERR(test_dev)) {
- err = PTR_ERR(test_dev);
- printk(KERN_ALERT"Sucess to create test device,ERR=%d.\n",err);
- }
- */
- for(test_minor = 0; test_minor < 4; test_minor++){
- test_classdev[test_minor] = device_create(test_class,NULL,MKDEV(test_major,test_minor),NULL,"test_drv[%d]",test_minor);//创建设备 (多个设备)
- if(!IS_ERR(test_classdev[test_minor])) {
- err = PTR_ERR(test_classdev[test_minor]);
- printk(KERN_ALERT"Sucess to create test device[%d],ERR=%d.\n",test_minor,err);
- }
- }
- return 0;
- }
- static void test_drv_exit(void)
- {
- unregister_chrdev(test_major, "test_drv");//注销系统设备号
- //device_destroy(test_class, MKDEV(test_major,0));//注销设备 单个
-
- for(test_minor = 0; test_minor < 4; test_minor++){
- device_destroy(test_class, MKDEV(test_major,test_minor));//注销设备 多个
- }
-
- class_destroy(test_class);//注销设备类
- printk(KERN_EMERG"test_drv_exit.....\n");
- printk("...................\n");//普通优先级,毛都不出
- }
- module_init(test_drv_init);
- module_exit(test_drv_exit);
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_AUTHOR("ljj3166");
复制代码Push进单板 Insmod安装一下驱动
打印提示,1个设备类,四个设备,创建成功
ls dev/tes* -l
主设备号、次设备号俱全
cat /proc/devices
设备创建成功
ls /sys/class/test_drv_class/
test_drv_class下的4个设备
试试卸载驱动
卸载也正常
写个应用程序testapp来测试一下驱动吧
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- void print_usage(char *file)//用法
- {
- printf("Usage:\n");
- printf("%s <dev> <hi|bye>\n",file);
- printf("eg. \n");
- printf("%s /dev/test_drv[0] hi\n", file);
- printf("%s /dev/test_drv[0] bye\n", file);
- printf("%s /dev/test_drv[1] hi\n", file);
- printf("%s /dev/test_drv[1] bye\n", file);
- }
- int main(int argc,char** argv)
- {
- int fd;
- int val = 1;
- char* filename;
- printf("hello,world!\n");//测试应用
- if (argc != 3) //判断入口参数个数,错误则打印使用方法
- {
- print_usage(argv[0]);
- return 0;
- }
- filename = argv[1];
- fd = open(filename,O_RDWR); //打开对应设备
- if(fd == -1)
- {
- printf("can't open %s , fd = %d......!\n",filename,fd);//打开失败,打印错误名称
- perror("ERROR:");
- }
- else {
- printf(" open %s OK!\n",filename);
- }
- if(strcmp(argv[2] ,"hi") == 0) //第三个入口参数判断
- {
- val = 1;
- }
- else if(strcmp(argv[2],"bye") == 0){val = 0;}
- else {print_usage(argv[0]);}
- write(fd, &val, 4);//向驱动程序写入值
- return 0;
- }
复制代码Push进单板运行一下 不过首先得设置testapp的权限 可能是编译的时候没配置好
执行正常
在调试测试程序的时候 有个天坑 内核打印函数,必须使用优先级较高的参数 直接printk是没有任何信息出现的 可能芯灵思为了串口不那么吵闹,调整了printk的打印级别 刚开始调试的时候 怎么也打印不出语句 一直还以为驱动写得有问题 折腾了2个小时 才发现这个坑 官方文档上居然没见有说明 再一次湿了…… 驱动框架先搭到这吧 后面有时间,把硬件的操作也加进来
|