日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發布時間:2023/12/3 linux 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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,這樣就完成了設備的注冊!

總結

以上是生活随笔為你收集整理的linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。