正点原子ALPHA_字符设备驱动开发总结

linux分为内核态和用户态,他两不能直接访问,必须通过”中间商”联系,关系如下:

用户空间:应用程序

               |

               |系统调用(陷入)

               |  

内核:linux驱动

Linux驱动的重点就是驱动框架,驱动运行方式有两种:

①:将驱动编译进linux内核中,代码release或者驱动模块需要;

②:将驱动编译成模块(.ko文件),再人为insmod/modprobe加载驱动模块,一般在调试阶段。

接下来就讲讲字符设备驱动入门流程和注意事项。

目录

1. 加载与卸载驱动模块

注册函数模板:

2. 字符设备的注册和注销

3. 设备驱动框架

4. 编写测试APP

5. 编译

6. 运行测试

7. 其他


1. 加载与卸载驱动模块

注册函数模板:

static int __init xxx_init(void) //执行insmod的时候调用

static void __exit xxx_exit(void) //执行rmmod的时候调用

module_init(xxx_init); //起声明作用

module_exit(xxx_exit); //起声明作用

使用modprobe,因为modprobe更智能,能关联加载驱动所需的其他驱动模块(但是在简单驱动开发验证还是觉得insmod方便简单)

 

2. 字符设备的注册和注销

register_chrdev(major(主设备号), name(设备名称), fops(fileoperations类型指针))

unregister_chrdev(major(主设备号), name(设备名称))

在上面的init和exit两个函数中分别调用这两个函数,还有需要定义一个fileoperations结构体。

3. 设备驱动框架

Staitc chrtest_open 打开设备

Staitc chrtest_read 从设备读取

Staitc chrtest_write 向设备写入

Staitc chrtest_release 关闭、释放设备

 

/*定义一个file operations结构体*/

Static struct file_operations test_fops={

.owner = THIS_MODULE,

.open = chrtest_open,

.read = chrtest_read,

.write = chrtest_write,

.release = chrtest_release,

};

 

/*驱动入口函数*/

Staitc int __init xxx_init(void)

{

Int ret = 0;

ret = register_chrdev(200,”chrtest”,&test_fops);

If(ret < 0)

{

Return -1;/*注册失败*/

}

}

/*驱动出口函数*/

Static void __exit xxx_exit(void)

{

unregister_chrdev(200, “chrdev”);

}

module_init(xxx_init);

module_exit(xxx_exit);

 

MODULE_LICENSE(“GPL”);

 

4. 编写测试APP

以操作文件的形式open read write close,因为linux皆文件。

int(fd) open(const char *pathname, int flags)

Pathname:文件路径、设备

flags:O_RDONLY只读/WRONLY只写/RDWR读写......

ssize read(int fd, void * buf, size_t count)

ssize write(int fd,void *buf, size_t count)

int close(fd)

 

5. 编译

驱动模块的编译:编写一个Makefile,执行make 生成.ko模块。

测试app的编译:arm-linux-gnueabihf-gcc xxx.c -o xxx 因为编译出来的执行文件是要在arm内核下运行,所以使用交叉编译器。

 

6. 运行测试

①:加载模块:insmod xxx.ko/modprobe xxx.ko(执行不成功,要先执行depmod)

②:创建设备节点:在/dev目录下创建与之对应的设备节点文件,mknod /dev/xxx c 200 0

mknod /dev/xxx c(字符设备) 200(主设备号) 0(次设备号)

③:设备验证:./xxx(APP) /dev/xxx 1(参数)

④:卸载:rmmod xxx.ko

7. 其他

①.设备都有一个设备号(32位),分别由主设备号(12位 0-4095)和次设备号(20位)组成。主设备号是具体的驱动,像鼠标驱动;次设备号是主驱动的具体应用个数,像雷蛇、双飞燕啊这些鼠标插电脑会有几个鼠标设备一样,但是驱动的名字不一样。

②.静态分配设备号:查看当前系统所使用的设备号:cat /proc/devices,在确定未使用的设备号作为改驱动设备号。

动态分配设备号:int alloc_chrdev_region(dev_t *dev(设备号),unsigned baseminor(次设备号起始),unsigned count(申请设备个数), const char *name(设备名称))

注销设备:void unregister_chrdev_region(dev_t from(需要释放设备号), unsigned count(从from需要释放个数))

③.Linux内核没有printf,只有printk。因为printf是运行在用户态中(应该是为了做区别吧)。

printk可以根据宏定义,决定需要打印的信息。因为内核空间和用户空间不能直接操作,所以就会有从内核<==>用户的接口函数:copy_to_user(内核->用户read)和copy_from_user(用户write->内核),这两个函数都是站在用户态理解和调用。

 

参考:【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.4.pdf

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_38042083

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值