串口的linux驱动开发,X-016-KERNEL-串口驱动开发之驱动框架

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

#include

#include

#include

#include

#include

#include

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):

注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. 参考文档

原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。c6a6308114f401be7df747ae46f2b4db.png

发表评论:

昵称

邮件地址 (选填)

个人主页 (选填)

d4e3789769c8ad44c7e403863bfc3822.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值