X-016-KERNEL-串口驱动开发之驱动框架
作者:wowo 发布于:2016-11-10 22:12 分类:X Project
1. 前言
在过去的一段时间里,蜗窝上发表了一系列的关于内核各个子系统的分析文章,设备模型、device tree、中断子系统、clock framework、电源管理、GPIO、pinctrl等等,这些文章重理论、轻实践。随着“X Project”的进行,我们渐渐有机会把这些缺失的实践慢慢补回来。
串口驱动是进入Linux kernel之后最先遭遇的一个驱动,虽然不是很复杂,但要素齐全,使用到了kernel的各个子系统。因此我希望能借助串口驱动的开发过程,将这些子系统的使用一一串联起来,并记录为一份份单独的文章。
本文是这一系列文章的第一篇,借助串口驱动开发,学习Linux设备模型之下的驱动框架。
2. 驱动开发框架
Linux kernel中大部分设备可以归结为平台设备,因此大部分的驱动是平台驱动(patform driver)。得益于设备模型,Linux kernel平台驱动的开发有了一套非常固定的框架,总结如下(具体可参考[1][2]):
1)模块的入口和出口
用于注册/注销platform driver,这一部分的代码基本固定,包括函数和变量的命名方式也可固定,如下:
static int __init AAA_BBB_init(void)
{
int ret;
pr_info("%s\n", __func__);
ret = platform_driver_register(&AAA_BBB_platform_driver);
if (ret < 0) {
pr_err("AAA_BBB_platform_driver register failed, ret = %d\n", ret);
return ret;
}
return 0;
}
static void __exit AAA_BBB_exit(void)
{
pr_info("%s\n", __func__);
platform_driver_unregister(&AAA_BBB_platform_driver);
}module_init(AAA_BBB_init);
module_exit(AAA_BBB_exit);
MODULE_ALIAS("platform driver: AAA_BBB");
MODULE_DESCRIPTION("BBB driver for xxxx");
MODULE_AUTHOR("wowo");
MODULE_LICENSE("GPL v2");
其中AAA一般可以是厂商名、芯片名、芯片的系列名、等等,例如TI OMAP系列的芯片,AAA可以是omap。BBB一般是模块名,以本文的串口驱动为例,可以是serial或者uart。因此AAA_BBB可以替换为omap_serial。编写驱动的时候,直接将上面的copy出来,查找替换即可。
2)platform driver
基本的platform driver包含三要素:struct platform_driver变量、probe/remove函数、用于和device tree匹配的match table,如下:
static const struct of_device_id AAA_BBB_of_match[] = {
{
.compatible = "xxx,xxx-BBB",
},
{
},
};
MODULE_DEVICE_TABLE(of, AAA_BBB_of_match);
static int AAA_BBB_probe(struct platform_device *pdev)
{
int ret = 0;
const struct of_device_id *match;
dev_info(&pdev->dev, "%s\n", __func__);
match = of_match_device(AAA_BBB_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
return ret;
}
static int AAA_BBB_remove(struct platform_device *pdev)
{
dev_info(&pdev->dev, "%s\n", __func__);
return 0;
}
static struct platform_driver AAA_BBB_platform_driver = {
.probe = AAA_BBB_probe,
.remove = AAA_BBB_remove,
.driver = {
.name = "AAA_BBB",
.of_match_table = AAA_BBB_of_match,
},
};
同理,上面的AAA_BBB可以直接替换。另外有一点需要注意,AAA_BBB_of_match中的.compatible需要和DTS文件中的compatible对应,一般格式是“厂商名称,芯片系列-模块名”,例如“actions,s900-serial” 。
3)头文件包含
上面的代码,使用到了很多kernel API,需要包含如下头文件:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
4)设备描述
需要在dts文件中,增加platform driver所要驱动设备的描述,例如:
BBBx: BBB@xxxxxxxx {
compatible = "xxx,xxx-BBB";
};
其中BBBx为dts节点的别名,用于方便在它处引用,为可选项。@xxxxxxxx一般为该模块的I/O起始地址,如果没有,可以写任意名称(或者留空),compatible需要和上面AAA_BBB_of_match对应,例如“actions,s900-serial” 。
3. 串口驱动
基于上面描述,我们以Bubblegum-96平台的串口为例,编写如下代码(基本上都是使用查找替换操作,%s/AAA/owl/g, %s/BBB/serial/g):
https://github.com/wowotechX/linux/commit/ff4955f391cd211ff85588f46b05099065ddeb07
注1:由于代码非常简单,这里就不解释了,有疑问的同学,可以直接在github上指定的代码行添加评论。
注2:这里的串口驱动和serial early console[3]共用一份代码,为了方便调试,在串口驱动ready之前,我们暂时保留early console原封不动。
注3:开始写代码的时候,我们一般会为这个工作新建一个分支,在这个分支上工作OK的话,再merge回主分支,这也是代码开发的一个基本规则
pengo@DESKTOP-CH8SB7C:~/work/xprj/linux$ git fetch origin
pengo@DESKTOP-CH8SB7C:~/work/xprj/linux$ git branch -a
* x_integration
remotes/origin/HEAD -> origin/x_integration
remotes/origin/x_integration
pengo@DESKTOP-CH8SB7C:~/work/xprj/linux$ git rebase origin/x_integration
pengo@DESKTOP-CH8SB7C:~/work/xprj/linux$ git checkout -b serial_dev
Switched to a new branch 'serial_dev'
pengo@DESKTOP-CH8SB7C:~/work/xprj/linux$ git branch
* serial_dev
x_integration
完成代码后,编译并运行kernel,通过earlycon的打印,查看probe函数是否被执行。
4. 参考文档
[2] Linux设备模型(5)_device和device driver
[3] X-012-KERNEL-serial early console的移植
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
标签: driver serial 框架 串口 驱动 platform_driver

功能
最新评论
- wangjing
写得太好了 - wangjing
写得太好了! - DRAM
圖面都沒辦法顯示出來好像掛點了。 - Simbr
bus至少是不是还有个subsystem? - troy
@testtest:只要ldrex-modify-strex... - gh
Linux 内核在 sparse 内存模型基础上实现了vme...
文章分类
随机文章
文章存档
- 2025年4月(5)
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
发表评论: