linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写

摘要:媒介 Device Tree是一种用去描绘硬件的数据布局,类似板级描绘说话,发源于OpenFirmware(OF)。正在现在遍及应用的kernel 2.6.x版本中,对分歧仄台、分歧硬件,往]

前言

Device Tree是一种用来描述硬件的数据结构,类似板级描述语言,起源于OpenFirmware(OF)。在目前广泛使用的Linux kernel 2.6.x版本中,对于不同平台、不同硬件,往往存在着大量的不同的、移植性差的板级描述代码,以达到对这些不同平台和不同硬件特殊适配的需求。但是过多的平台、过的的不同硬件导致了这样的代码越来越多,最终引发了LinuxLinus的不满,以及强烈呼吁改变。Device Tree的引入给驱动适配带来了很大的方便,一套完整的Device Tree可以将一个PCB摆在你眼前。Device Tree可以描述CPU,可以描述时钟、中断控制器、IO控制器、SPI总线控制器、I2C控制器、设备等任何现有驱动单位。对具体器件能够描述到使用哪个中断,内存映射是多少等等。

关于Device Tree的数据结构和详细使用方法,请大家查看宋宝华老师的一篇:

http://blog.csdn.net/airk000/article/details/2

1 基于Device Tree机制内核的驱动开发—实例讲解

这个章节,作者来讲讲基于Linux-3.2.X之后使用device tree机制的内核的驱动开发案例。本文的驱动开发案例是作者工作期间亲自写的驱动代码。CPU平台使用的是NXP(freescale)的i.MX6ul。概要信息描述如下:

硬件平台:NXP(freescale)—i.MX6ul

开发平台:-12.04

内核版本:Linux-3.14.38

编译环境:yocto project

1.1 基于Device Tree机制的驱动开发—系统如何加载和解析dtb文件

基于Device Tree机制的驱动开发,在驱动当中所使用到的硬件资源都在对应的CPU平台的dts文件上进行配置,然后编译生成dtb文件,放在u-boot分区之后,内核分区之前。这里顺便讲一下,内核是如何解析dtb文件的。其大致过程如下:

系统上电启动之后,u-boot加载dtb,通过u-boot和Linux内核之间的传参操作将dtb文件传给内核,然后内核解析dtb文件,根据device tree中的配置(dtb文件)去初始化设备的CPU管脚、各个外设的状态。device tree中的配置主要是起到了初始化硬件资源的作用,后期可以在驱动中修改设备的硬件资源的状态,比如在device tree中初始化某个GPIO的管脚为上拉状态,可以在驱动加载之后修改这个管脚的状态。

1.2 基于Device Tree机制的驱动开发—dts文件的配置和编译

本节开始以具体的驱动例子讲解如何在驱动开发中配置dts文件。这里使用i.MX6ul平台下的矩阵键盘驱动中使用到的几个GPIO口讲解如何配置dts文件和编译。本次讲解案例用于编译驱动的内核是Linux-3.14.38。首先我们先来看看如何在内核中找到自己相应CPU平台的dts文件:

1.dts文件位于内核的arch/arm/boot/dts/$(board).dts,其中的$(board)指的是对应的CPU平台,比如i.MX6ul平台的dts文件如下:

imx6ul/linux-3.14.38-v2$ vim arch/arm/boot/dts/imx6ul-14x14-evk.dts(部分内容)

#include #include "imx6ul.dtsi"

/ {

model = "Freescale i.MX6 UltraLite Ned Board";

compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";

chosen {

stdout-path = &uart1;

};

memory {

reg = <0x80000000 0x20000000>;

};

pxp_v4l2 {

compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";

status = "okay";

};

keyboard {

compatible = "max-keypad";

pinctrl-names = "default";

pinctrl-0 = ;

in-gpios = , //key_in0

, //key_in1

; //key_in2

out-gpios = , //key_out0

, //key_out1

, //key_out2

, //key_out3

; //key_out4

status = "okay";

};

};

&cpu0 {

arm-supply = ;

soc-supply = ;

};

&clks {

assigned-clocks = ;

assigned-clock-rates = <786432000>;

};

&tsc {

pinctrl-names = "default";

pinctrl-0 = ;

status = "okay";

xnur-gpio = ;

measure_delay_time = <0xffff>;

pre_charge_time = <0xfff>;

};

&gpmi {

pinctrl-names = "default";

pinctrl-0 = ;

status = "okay";

nand-on--bbt;

};

&lcdif {

pinctrl-names = "default";

pinctrl-0 = ;

lcd_reset = ;

display = ;

status = "okay";

display0: display {

bits-per-pixel = <16>;

bus-width = <8>;

display-timings {

native-mode = ;

timing0: timing0 {

clock-frequency = <9200000>;

hactive = <240>;

vactive = <320>;

hfront-porch = <8>;

hback-porch = <4>;

hsync-len = <41>;

vback-porch = <2>;

vfront-porch = <4>;

vsync-len = <10>;

hsync-active = <0>;

vsync-active = <0>;

de-active = <1>;

pixelclk-active = <0>;

};

};

};

};

&iomuxc {

pinctrl-names = "default";

pinctrl-0 = ;

imx6ul-evk {

pinctrl_uart1: uart1grp {

fsl,pins = <

MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1

MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1

>;

};

pinctrl_tsc: tscgrp {

fsl,pins = <

MX6UL_PAD_GPIO1_IO01__GPIO1_IO010xb0

MX6UL_PAD_GPIO1_IO02__GPIO1_IO020xb0

MX6UL_PAD_GPIO1_IO03__GPIO1_IO030xb0

MX6UL_PAD_GPIO1_IO04__GPIO1_IO040xb0

>;

};

pinctrl_lcdif_dat: lcdifdatgrp {

fsl,pins = <

MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79

MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79

MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79

MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79

MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79

MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79

MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79

MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79

>;

};

pinctrl_lcdif_ctrl: lcdifctrlgrp {

fsl,pins = <

MX6UL_PAD_LCD_CLK__LCDIF_WR_RWN 0x79

MX6UL_PAD_LCD_ENABLE__LCDIF_RD_E 0x79

MX6UL_PAD_LCD_HSYNC__LCDIF_RS 0x79

MX6UL_PAD_LCD_RESET__LCDIF_CS 0x79

/* used for lcd reset */

MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x79

>;

};

pinctrl_keypad: keypadgrp {

fsl,pins = <

MX6UL_PAD_ENET1_RX_EN__GPIO2_IO02 0x70a0

MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03 0x70a0

MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04 0x70a0

MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x70a0

MX6UL_PAD_ENET1_TX_CLK__GPIO2_IO06 0x70a0

MX6UL_PAD_ENET1_RX_ER__GPIO2_IO07 0x70a0

MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x70a0

MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x70a0

>;

};

pinctrl_gpmi_nand_1: gpmi-nand-1 {

fsl,pins = <

MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1

MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1

MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1

MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000

MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1

MX6UL_PAD_NAND_CE1_B__RAWNAND_CE1_B 0xb0b1

MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1

MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1

MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1

MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1

MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1

MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1

MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1

MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1

MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1

MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1

>;

};

};

};

2.根据自己的开发需求配置dts文件,本文矩阵键盘驱动所使用到的GPIO管脚资源为:gpio2-2、gpio2-3、gpio2-4、gpio2-5、gpio2-6、gpio2-7、gpio4-25、gpio4-26。dts文件配置如下:

~/yangfile/imx6ul/linux-3.14.38-v2$ vim arch/arm/boot/dts/imx6ul-newland.dts

2.1 在dts文件中添加一个设备节点,比如我们是矩阵键盘驱动,那么就添加一个名为”keyboard“的设备节点;

2.2 compatible属性用于of_find_node_compatible函数获取设备节点用的,这个函数的通过”max-keypad“去遍历device tree,查找匹配的设备节点;

2.3 pinctrl-0 = 主要用于说明设备硬件资源在哪里获取,比如这里就是到iomuxc里面去获取IO资源

2.4 iomuxc设备节点里面定义了CPU所有的IO资源,包括每个IO口的初始化状态都定义好了,比如:MX6UL_PAD_ENET1_RX_EN_GPIO2_IO02  0x70a0,这里的MX6UL_PAD_ENET1_RX_EN_GPIO2_IO02宏表示的是GPIO2-2这个IO口的寄存器组(IO复用寄存器、IO方向控制寄存器、IO输入输出值设置寄存器),0x70a0这个值根据自己的驱动开发需求,查阅CPU手册定义,不唯一。

keyboard {

compatible = "max-keypad";

pinctrl-names = "default";//这个设置成默认default就可以了,没什么特别要求

pinctrl-0 = ;//到iomuxc里面去获取相应IO资源的初始化状态

in-gpios = , //“in-gpios”字符串可以自己随便定义,主要是为了获取gpio资源的时候匹配用的

, //GPIO_ACTIVE_HIGH:逻辑高电平有效

; //key_in2

out-gpios = , //“out-gpios”字符串可以自己随便定义,主要是为了获取gpio资源的时候匹配用的

, //key_out1

, //key_out2

, //key_out3

; //key_out4

status = "okay";//使能要使用的gpio资源

};

};

&iomuxc {

pinctrl-names = "default";

pinctrl-0 = ;

。。。。。。。。

pinctrl_keypad: keypadgrp {

fsl,pins = <

MX6UL_PAD_ENET1_RX_EN__GPIO2_IO02 0x70a0

MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03 0x70a0

MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04 0x70a0

MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x70a0

MX6UL_PAD_ENET1_TX_CLK__GPIO2_IO06 0x70a0

MX6UL_PAD_ENET1_RX_ER__GPIO2_IO07 0x70a0

MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x70a0

MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x70a0

>;

};

3.编译dts文件,在内核下执行以下命令:

~/yangfile/imx6ul/linux-3.14.38-v2$ make ARCH=arm CROSS_COMPILE=arm-linux-gcc imx6ul-newland.dtb

(这里的arm-Linux-gcc只是个代表交叉的标识,具体的根据实际情况而定)

4.将配置、编译后的dtb文件烧录到设备flash(或者SD卡)的dtb分区中。

2 驱动代码中如何注册dts文件中的设备

接触了device tree机制的驱动开发后,其实device tree机制就是Linux-2.6.x中的platform 总线机制的优化版本。OK,我们来说说基于device tree机制的驱动开发中注册设备的过程,这里以我写的矩阵键盘驱动代码的设备注册过程为例:1.在probe函数中调用of_get_**或者of_find_**函数从dtb中获取设备资源:

static int max_keypad_probe(struct platform_device *pdev)

{

int i,ret;

struct device *dev;

struct device_node *dev_node = NULL; //add by zengxiany

dev = &pdev->dev;

。。。。。。

//省略部分代码

dev_node = of_find_compatible_node(NULL,NULL,"fsl,imx6ul-gpio");

if(!of_device_is_compatible(dev_node,"fsl,imx6ul-gpio"))

{

printk("get keypad device node error!\n");

return -EINVAL;

}

dev_node = of_find_compatible_node(dev_node,NULL,"max-keypad");

if(!of_device_is_compatible(dev_node,"max-keypad"))

{

printk("failure to find max-keypad device node!\n");

return -EINVAL;

}

for(i=0; i< KEYPAD_ROWS; i++)

{

gpio_map_rowkey[i] = of_get_named_gpio(dev_node,"in-gpios",i);

set_key_input(gpio_map_rowkey[i]);

}

for(i=0; i< KEYPAD_COLS; i++)

{

gpio_map_colkey0[i] = of_get_named_gpio(dev_node,"out-gpios",i);

set_key_input(gpio_map_colkey0[i]);

}

}

2.在init函数中注册设备:

//add by zengxiany for platform device register

static struct of_device_id max_keypad_of_match[] = {

{ .compatible = "max-keypad", },

{ },

};

static struct platform_driver max_keypad_device_driver = {

.probe= max_keypad_probe,

.remove= max_keypad_remove,

.driver= {

.name= "max-keypad",

.owner= THIS_MODULE,

.of_match_table = of_match_ptr(max_keypad_of_match),

}

};

static int __init keypad_module_init(void)

{

int ret;

ret = platform_driver_register(&max_keypad_device_driver);//modify by zengxiany

if(ret < 0)

{

printk("max_keypad_device driver init error!\n");

return -ENODEV;

}

return 0;

}

static void __exit keypad_module_exit(void)

{

platform_driver_unregister(&max_keypad_device_driver);

}

OK,这样就完成了设备的注册!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gRPC .NET Core跨平台学习

前些天发布gRPC C# 学习&#xff0c;在.NET Framework 中使用gRPC &#xff0c;今天来学习 .NET Core gRPC。 gRPC 的.NET Core 包在NuGet 上发布了&#xff0c;结合.NET Core 实现gRPC 完美跨平台。 本篇主要讲解 .NET Core 版gRPC客户端运行在Ubuntu系统上&#xff0c;与局域…

IDEA导入Maven项目,pom.xml文件中 有inspects a maven model for resolution problems报错 !!!!!!!!!!有用

IDEA导入Maven项目&#xff0c;pom.xml文件中 有inspects a maven model for resolution problems报错 2018年08月06日 22:13:09 东方不能败 阅读数&#xff1a;4616 我是导入一个已经写好的Maven工程&#xff0c;导入后返现在pom.xml文件中有inspects a maven model for res…

Windows Server 2016提供Docker原生运行的企业级支持

Windows Server 2016已原生支持Docker&#xff0c;这使得Windows应用可运行在容器中。该评估版目前已经可用&#xff0c;期望于本月底之前&#xff0c;Microsoft将提供从评估版到RTM的升级路径。该评估版发布于上周的Microsoft Ignite大会上&#xff0c;同时还发布了Microsoft和…

arm linux串口控制led,通信程序设计 - Linux下ARM和单片机的串口通信设计

3 通信程序设计ARM 与单片机的串口通信程序包括两方面&#xff1a; 一方面是作为上位机的ARM 的串口通信程序&#xff0c;另一方面是作为下位机的单片机的串口通信程序。在通信之前必须制定合理的通信协议以保证通信的可靠性和成功率。现约定双方通信协议如下&#xff1a;( 1) …

为什么我强烈建议大家使用枚举来实现单例

转载自 为什么我墙裂建议大家使用枚举来实现单例 关于单例模式&#xff0c;我的博客中有很多文章介绍过。作为23种设计模式中最为常用的设计模式&#xff0c;单例模式并没有想象的那么简单。因为在设计单例的时候要考虑很多问题&#xff0c;比如线程安全问题、序列化对单例的…

idea @Data 不起作用找不到 相关的注解

idea中Data标签getset不起作用(这个有用&#xff0c;下面的没用) 2017年06月08日 11:22:40 seapeak007 阅读数&#xff1a;25816 spring cloud中使用Data标签&#xff0c;不用手动添加get set方法&#xff0c;但是如果项目中其他类中使用getset方法&#xff0c;如果报错&…

搭建分布式 ASP.NET Core Web

单台Web处理用户请求的能力是有限的&#xff0c;因此我们可能会需要搭建分布式的Web服务器。 当前市面上&#xff0c;可能用的比较多的是会话保持&#xff0c;这种模式下&#xff0c;开发者只需将先前开发好的、不支持会话共享的程序部署在多台服务器上&#xff0c;负载均衡提供…

五分钟了解CDN

转载自 五分钟了解CDN一、什么是CDN&#xff1f; CDN全称Content Delivery Network&#xff0c;即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输的更快、更稳定。 通过在网络各处放置节点服务器所构成的在现…

Eclipse导入他人的Maven工程报错

一.什么是maven? Maven是一个项目管理工具&#xff0c;它包含了一个项目对象模型 (Project Object Model)&#xff0c;一组标准集合&#xff0c;一个项目生命周期(Project Lifecycle)&#xff0c;一个依赖管理系统(Dependency Management System)&#xff0c;和用来运行定义在…

拼图游戏C语言课设实验报告,C语言拼图游戏实验报告.doc

C语言拼图游戏实验报告课程设计实验报告班级&#xff1a;光电104—2 姓名&#xff1a;刘云龙 学号&#xff1a;201058501220一、实验题目&#xff1a;使用C语言编写一个小游戏(拼图游戏)二、实验目的&#xff1a;C语言是每一个通信学生的必修课之一&#xff0c;此次课程设计要求…

.Net开源微型ORM框架测评

什么是ORM? 对象关系映射&#xff08;英语&#xff1a;Object Relation Mapping&#xff0c;简称ORM&#xff0c;或O/RM&#xff0c;或O/R mapping&#xff09;&#xff0c;是一种程序技术&#xff0c;用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说&am…

大家都在说的分布式系统到底是什么

转载自 大家都在说的分布式系统到底是什么随着大型网站的各种高并发访问、海量数据处理等场景越来越多&#xff0c;如何实现网站的高可用、易伸缩、可扩展、安全等目标就显得越来越重要。为了解决这样一系列问题&#xff0c;大型网站的架构也在不断发展。提高大型网站的高可用架…

2015c语言9月答案,2015年9月计算机二级C语言预测题答案

2015年9月计算机二级C语言预测题答案一、 选择题1、B 2、C 3、D 4、C 5、C 6、D 7、C 8、D 9、C 10、D11、D 12、D 13、B 14、B 15、A 16、D 17、B 18、B 19、C 20、D二、 阅读程序题(1) 6&#xff0c;8 (2) 3.141593,3.1416,3.142 (3) 4 (4) 2&#xff0c;4 (5) 8三、 程序填空…

Redis集群~StackExchange.Redis(10月6号版1.1.608.0)连接Twemproxy支持Auth指令了

对于StackExchange.Redis这个驱动来说&#xff0c;之前的版本在使用Proxy为Twemproxy代理时&#xff0c;它是不支持Password属性的&#xff0c;即不支持原始的Auth指令&#xff0c;而我也修改过源代码&#xff0c;为CommandMap添加了Auth但最后测试的结果还是失败了&#xff0c…

使用JDOM2.0.4 操作/解析xml

转载自 使用JDOM2.0.4 操作/解析xml一、解析xml内容 xml文件内容:<?xml version"1.0" encoding"utf-8"?> <RETVAL successtrue> <Shop><sid>1</sid><name>北京鑫和易通贸易有限公司</name></Shop> &l…

c语言关于计算的函数,问个c语言题目,关于一个计算器的有参有返回函数!!!...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼printf("toM");scanf("%d",&toM);if(toM0)printf("错误&#xff0c;除数不能为0\n");else{resultarith_compliment(toN,toM);printf("\n%d",toN);printf("%%");printf(&quo…

TypeScript 2.0 已发布

微软最近发布了TypeScript 2.0&#xff0c;该版本提供了简化的声明文件获取、Non-nullable类型&#xff0c;以及Readonly修饰符。 TypeScript项目经理Daniel Rosenwasser称&#xff0c;他们团队对于该版本“紧随ECMAScript规范&#xff0c;为JavaScript库和工具提供了更广泛的支…

springboot创建项目2 开发环境的搭建

我也学习了一下 才想着去写个对应的服务器 前端已经全部搭建好了 有很多的坑 你们就不用再次采坑了 我只讲其中的 服务器部分 中间有好多 以后补充吧。。。。

XML解析(二),DOM解析XML

转载自 XML解析&#xff08;二&#xff09;&#xff0c;DOM解析XML上篇文章向大家介绍了SAX解析XML,为了这篇文章理解起来更加方便&#xff0c;所以还没看过SAX解析XML文章的&#xff0c;请戳这【XML解析&#xff08;一&#xff09;】SAX解析XML &#xff0c;这次给大家带来X…

如何通过反射将字符串转换为类

package org.entity; /*** 本案例演示如何通过反射将字符串转换为类* */ public class Test {public static void main(String[] args) {String user "org.entity.User";//字符串是该类的全限定名try {Class clzz Class.forName(user);Object classObjclzz.newInst…