成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux驅(qū)動 | 手寫一個設(shè)備樹使用的實(shí)例

系統(tǒng) Linux
設(shè)備樹是每一個Linux驅(qū)動工程師都必須掌握的一個知識點(diǎn),有很多之前做單片機(jī)的朋友剛接觸Linux驅(qū)動時,會一臉懵!

一、前言

設(shè)備樹是每一個Linux驅(qū)動工程師都必須掌握的一個知識點(diǎn),有很多之前做單片機(jī)的朋友剛接觸Linux驅(qū)動時,會一臉懵!

其實(shí)設(shè)備樹的使用并沒有大家想像的那么復(fù)雜,對于大部分工程師來說,只要會修改即可。

很多粉絲留言說,希望彭老師提供一個設(shè)備樹到驅(qū)動解析的實(shí)例。

必須安排!

在學(xué)習(xí)設(shè)備樹之前,大家一定要搞清楚什么是platform總線,請?jiān)敿?xì)學(xué)習(xí)下面這篇文章:

《手把手教Linux驅(qū)動10-platform總線詳解》

關(guān)于設(shè)備樹理論部分內(nèi)容請學(xué)習(xí)下面這篇文章:

《手把手教linux驅(qū)動11-linux設(shè)備驅(qū)動統(tǒng)一模型》

關(guān)于驅(qū)動基礎(chǔ)文章,可以去B站學(xué)習(xí)一口君的入門視頻:

《從學(xué)Linux驅(qū)動入門視頻》

https://www.bilibili.com/video/BV1d5411A7VJ?spm_id_from=333.999.0.0

有了這些基礎(chǔ)知識后,我們就可以來編寫一個設(shè)備樹的實(shí)例,

下面彭老師就給大家講解如何自己添加一個設(shè)備樹節(jié)點(diǎn),并如何在驅(qū)動中提取出設(shè)備樹的信息。

老規(guī)矩,代碼從0開始編寫,并且全部驗(yàn)證通過,并分享給大家。

二、測試平臺

本次測試在開發(fā)板上操作,操作環(huán)境如下:

1. 編譯環(huán)境

  1. ubuntu 16.04 

2. 交叉編譯工具

  1. root@ubuntu:/home/peng/linux-3.14# arm-none-linux-gnueabi-gcc -v 
  2. Using built-in specs. 
  3. COLLECT_GCC=arm-none-linux-gnueabi-gcc 
  4. COLLECT_LTO_WRAPPER=/home/peng/toolchain/gcc-4.6.4/bin/../libexec/gcc/arm-arm1176jzfssf-linux-gnueabi/4.6.4/lto-wrapper 
  5. Target: arm-arm1176jzfssf-linux-gnueabi 
  6. ……………… 
  7. gcc version 4.6.4 (crosstool-NG hg+default-2685dfa9de14 - tc0002) 

3. 開發(fā)板

  1. 開發(fā)板:fs4412 
  2. soc:exynos4412 

4. 內(nèi)核版本

  1. Linux kernel 3.14.0 

三、內(nèi)核解析設(shè)備樹一般過程

系統(tǒng)啟動后,uboot會從網(wǎng)絡(luò)或者flash、sd卡中讀取設(shè)備樹文件(具體由uboot命令給出),

引導(dǎo)linux內(nèi)核啟動后,會把設(shè)備樹鏡像保存到的內(nèi)存地址傳遞給Linux內(nèi)核,Linux內(nèi)核會解析設(shè)備樹鏡像,從設(shè)備樹中提取硬件信息并逐一初始化。

其中設(shè)備樹信息會被轉(zhuǎn)換成struct platform_device類型變量。

而驅(qū)動要解析設(shè)備樹,必須定義 struct platform_driver類型結(jié)構(gòu)體變量,并通過函數(shù)platform_driver_register()注冊。

這兩者都會注冊到platform總線,當(dāng)驅(qū)動和設(shè)備樹節(jié)點(diǎn)匹配成功后,就調(diào)用 struct platform_driver中.probe方法。

其中設(shè)備樹節(jié)點(diǎn)會封裝在struct device_node結(jié)構(gòu)體變量中 各個屬性信息會封裝在 struct property結(jié)構(gòu)體變量中, 他們與struct platform_device結(jié)構(gòu)體之間關(guān)系如下:

四、驅(qū)動架構(gòu)

以下是一口君編寫的驅(qū)動架構(gòu),

我們只需要將測試代碼填充到hello_probe()中即可:

  1. static int hello_probe(struct platform_device *pdev) 
  2.  printk("match ok \n"); 
  3.   
  4. //解析代碼編寫 
  5.  return 0; 
  6. static  int hello_remove(struct platform_device *pdev) 
  7.  printk("hello_remove \n"); 
  8.  return 0; 
  9. static struct of_device_id beep_table[] = { 
  10.   {.compatible = "yikoulinux"}, 
  11. }; 
  12. static struct platform_driver hello_driver = 
  13.  .probe = hello_probe, 
  14.  .driver.name = "duang"
  15.  .remove = hello_remove, 
  16.  .driver = { 
  17.   .name = "yikoupeng"
  18.   .of_match_table = beep_table, 
  19.  }, 
  20. }; 
  21. static int hello_init(void) 
  22.  printk("hello_init \n"); 
  23.  return platform_driver_register(&hello_driver); 
  24. static void hello_exit(void) 
  25.  printk("hello_exit \n"); 
  26.  platform_driver_unregister(&hello_driver); 
  27.  return
  28. MODULE_LICENSE("GPL"); 
  29. module_init(hello_init); 
  30. module_exit(hello_exit); 

五、設(shè)備樹節(jié)點(diǎn)

下面是給出的設(shè)備樹信息:

  1. yikou_node{ 
  2.        compatible = "yikoulinux"
  3.        reg = <0x114000a0 0x4 0x139D0000 0x20>; 
  4.        reg-names = "peng"
  5.        interrupt-parent=<&gpx1>; 
  6.        interrupts =<1 2>,<2  2>; 
  7.     
  8.        csm_gpios=<&gpx2 3 0 &gpx2 4 0 &gpx2 5 0 &gpx2 6 0>; 
  9.         
  10.        crl0_gpio=<&gpx0 5 0>; 
  11.        crl1_gpio=<&gpx0 6 0>; 
  12.        rst_gpio=<&gpx0 7 0>; 
  13.        cfg_gpio=<&gpx0 4 0>; 
  14.   
  15.  phy_ref_freq = <26000>;  /* kHz */   
  16.  suspend_poweroff; 
  17.   
  18.  clock-names = "xusbxti"
  19.   "otg"
  20.  yikou_node { 
  21.   compatible = "leadcore,dsi-panel"
  22.   panel_name = "lcd_rd_rm67295"
  23.   refresh_en = <1>; 
  24.   bits-per-pixel = <32>;  
  25.  }; 
  26.    }; 

其中包括常見reg、中斷、整型值、bool值、字符串、子節(jié)點(diǎn)、時鐘等屬性。

一定要注意,很多屬性的給出會因?yàn)槭褂玫腟OC平臺的不同有所差異, 下面介紹下GPIO和中斷編寫原理:

1. GPIO

gpio信息的給出有以下兩種方法:

  1. csm_gpios=<&gpx2 3 0 &gpx2 4 0 &gpx2 5 0 &gpx2 6 0>; 
  1. crl0_gpio=<&gpx0 5 0>; 
  2. crl1_gpio=<&gpx0 6 0>; 
  3. rst_gpio=<&gpx0 7 0>; 
  4. cfg_gpio=<&gpx0 4 0>; 

第1種是公用同一個名字,第2種是每一個gpio單獨(dú)使用1個名字。

gpio需要指明父節(jié)點(diǎn),關(guān)于gpio父節(jié)點(diǎn)的說明下說明文檔(通常linux-3.14\Documentation下有關(guān)于該內(nèi)核版本的一些模塊說明,很重要):

  1. linux-3.14\Documentation\devicetree\bindings\gpio.txt 
  1. For example, the following could be used to describe gpios pins to use 
  2. as chip select lines; with chip selects 0, 1 and 3 populated, and chip 
  3. select 2 left empty: 
  4.  
  5.  gpio1: gpio1 { 
  6.   gpio-controller 
  7.    #gpio-cells = <2>; 
  8.  }; 
  9.  gpio2: gpio2 { 
  10.   gpio-controller 
  11.    #gpio-cells = <1>; 
  12.  }; 
  13.  [...] 
  14.   chipsel-gpios = <&gpio1 12 0>, 
  15.     <&gpio1 13 0>, 
  16.     <0>, /* holes are permitted, means no GPIO 2 */ 
  17.     <&gpio2 2>; 
  18. Note that gpio-specifier length is controller dependent.  In the 
  19. above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2 
  20. only uses one. 
  21.  
  22. gpio-specifier may encode: bank, pin position inside the bank, 
  23. whether pin is open-drain and whether pin is logically inverted. 
  24. Exact meaning of each specifier cell is controller specific, and must 
  25. be documented in the device tree binding for the device. 
  26.  
  27. Example of the node using GPIOs: 
  28.  
  29.  node { 
  30.   gpios = <&qe_pio_e 18 0>; 
  31.  }; 
  32.  
  33. In this example gpio-specifier is "18 0" and encodes GPIO pin number, 
  34. and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. 

翻譯總結(jié)成如下幾點(diǎn):

gpio父節(jié)點(diǎn)需要包含屬性

  1. gpio-controller、    表示是gpi控制器 
  2. #gpio-cells = <2>;    表示子節(jié)點(diǎn)包括2個屬性 

對于子節(jié)點(diǎn)是2個屬性的函數(shù) 比如:

  1. gpios = <&qe_pio_e 18 0>; 

父節(jié)點(diǎn)是qe_pio_e 其中18表示GPIO pin值,就是gpio下面管理的pin腳序號,該pin值一般就需要查詢用戶手冊&電路圖。

2. 中斷

中斷屬性節(jié)點(diǎn)如下:

  1. interrupt-parent=<&gpx1>; 
  2.   interrupts =<1 2>,<2  2>; 

其中

  1. interrupt-parent=<&gpx1>;: 該中斷信號所述的中斷控制器 
  2. interrupts =<1 2>,<2  2>;  :描述中斷屬性,其中<>中第一個值表示該中斷所述中斷控制器index,第二個值表示中斷觸發(fā)方式 

中斷子節(jié)點(diǎn)格式如下:

  1. linux-3.14\Documentation\devicetree\bindings\gpio.txt 
  1. Example of a peripheral using the GPIO module as an IRQ controller: 
  2.  
  3.  funkyfpga@0 { 
  4.   compatible = "funky-fpga"
  5.   ... 
  6.   interrupt-parent = <&gpio1>;   #父節(jié)點(diǎn) 
  7.   interrupts = <4 3>;     #節(jié)點(diǎn)屬性 
  8.  }; 

中斷子節(jié)點(diǎn)說明文檔如下:

  1. linux-3.14\Documentation\devicetree\bindings\interrupt-controller\interrupts.txt 
  1. b) two cells 
  2. ------------ 
  3. The #interrupt-cells property is set to 2 and the first cell defines the 
  4. index of the interrupt within the controller, while the second cell is used 
  5. to specify any of the following flags: 
  6.   - bits[3:0] trigger type and level flags 
  7.       1 = low-to-high edge triggered          上升沿 
  8.       2 = high-to-low edge triggered    下降沿 
  9.       4 = active high level-sensitive      高電平有效 
  10.       8 = active low level-sensitive          低電平有效 

我們所填寫的中斷父節(jié)點(diǎn)gpx1定義如下(該文件由三星廠家出廠定制好):

  1. linux-3.14\arch\arm\boot\dts\exynos4x12-pinctrl.dtsi 
  1. gpx1: gpx1 { 
  2.  gpio-controller;        #gpio控制器 
  3.  #gpio-cells = <2>;      #子節(jié)點(diǎn)有2個屬性 
  4.  
  5.  interrupt-controller;  #中斷控制器 
  6.  interrupt-parent = <&gic>;    #父節(jié)點(diǎn)gic 
  7.  interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,   #子節(jié)點(diǎn)屬性約束 
  8.        <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; 
  9.  #interrupt-cells = <2>; 
  10. }; 

可見三星的exynos4412平臺中g(shù)px1,既可以做gpio控制器又可以做中斷控制器,而gpx1作為中斷控制器則路由到gic上。其中interrupts屬性說明如下:

  1. linux-3.14\Documentation\devicetree\bindings\arm\gic.txt 

  1. Main node required properties: 
  2.  
  3. - compatible : should be one of
  4.  "arm,gic-400" 
  5.  "arm,cortex-a15-gic" 
  6.  "arm,cortex-a9-gic" 
  7.  "arm,cortex-a7-gic" 
  8.  "arm,arm11mp-gic" 
  9. - interrupt-controller : Identifies the node as an interrupt controller 
  10. - #interrupt-cells : Specifies the number of cells needed to encode an 
  11.   interrupt source.  The type shall be a <u32> and the value shall be 3. 
  12.  
  13.   The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI 
  14.   interrupts. 
  15.  
  16.   The 2nd cell contains the interrupt number for the interrupt type. 
  17.   SPI interrupts are in the range [0-987].  PPI interrupts are in the 
  18.   range [0-15]. 
  19.  
  20.   The 3rd cell is the flags, encoded as follows: 
  21.  bits[3:0] trigger type and level flags. 
  22.   1 = low-to-high edge triggered 
  23.   2 = high-to-low edge triggered 
  24.   4 = active high level-sensitive 
  25.   8 = active low level-sensitive 
  26.  bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of 
  27.  the 8 possible cpus attached to the GIC.  A bit set to '1' indicated 
  28.  the interrupt is wired to that CPU.  Only valid for PPI interrupts. 

翻譯總結(jié):

  1. interrupts = <0 24 0> 

第1個0 表示該中斷是SPI類型中斷,如果是1表示PPI類型中斷

24表示中斷號(通過查詢電路圖和datasheet獲得)

第三個0表示中斷觸發(fā)方式

再強(qiáng)調(diào)一遍 不同的平臺gpio、中斷控制器管理可能不一樣,所以填寫方法可能會有差異,不可教條

六、驅(qū)動提取設(shè)備樹信息方法

驅(qū)動解析代碼與設(shè)備樹節(jié)點(diǎn)之間關(guān)系如下,代碼與屬性用相同顏色框出:

of開頭的函數(shù)請參考《手把手教linux驅(qū)動11-linux設(shè)備驅(qū)動統(tǒng)一模型》

七、編譯(ubuntu中操作)

驅(qū)動編譯:

注意,內(nèi)核必須提前編譯好

設(shè)備樹編譯:

編譯設(shè)備樹命令,各個廠家的SDK都不盡相同,本例制作參考。

除此之外驅(qū)動模塊文件、設(shè)備樹文件如何導(dǎo)入給開發(fā)板,差別也比較大,本文不再給出步驟。

八、加載模塊(開發(fā)板上操作)

加載模塊后執(zhí)行結(jié)果如下:

  1. [root@peng test]# insmod driver.ko  
  2. [   26.880000] hello_init  
  3. [   26.880000] match ok  
  4. [   26.880000] mem_res1 : [0x114000a0]  mem_res2:[0x139d0000]  
  5. [   26.885000] irq_res1 : [168]  irq_res2:[169]  
  6. [   26.890000] mem_resp:[114000a0] 
  7. [   26.890000]  
  8. [   26.895000] phy_ref_freq:26000 
  9. [   26.900000] suspend_poweroff [true
  10. [   26.900000] suspend_poweroff_test [false
  11. [   26.900000]  
  12. [   26.905000] csm_gpios :[231][232][233][234] 
  13. [   26.910000] CTL0:[217] CTL1:[218] RST:[219] CFG:[216] 
  14. [   26.915000] bits_per_pixel:32 
  15. [   26.920000] panel_name:lcd_rd_rm67295 
  16. [   26.925000] refresh_en [true

其中打印的信息就是最終我們解析出的設(shè)備樹里的硬件信息, 我們就可以根據(jù)這些信息進(jìn)行相關(guān)資源申請、初始化。

同時設(shè)備樹中的信息,會以文件節(jié)點(diǎn)形式創(chuàng)建在一下目錄中:

本文轉(zhuǎn)載自微信公眾號「一口Linux」

 

責(zé)任編輯:姜華 來源: 一口Linux
相關(guān)推薦

2022-05-10 08:49:46

設(shè)備驅(qū)動Linux

2022-03-09 09:43:01

工具類線程項(xiàng)目

2021-02-22 17:17:38

Proxy緩存代碼

2022-10-31 08:27:53

Database數(shù)據(jù)數(shù)據(jù)庫

2021-10-25 16:01:01

Linux設(shè)備樹字符串

2020-12-03 08:59:06

Linux設(shè)備驅(qū)動

2021-03-18 08:04:54

AQS工具CAS

2021-12-07 06:55:17

節(jié)流函數(shù)Throttle

2020-11-02 08:19:18

RPC框架Java

2017-10-24 17:03:48

Linux驅(qū)動程序編譯

2021-07-30 14:55:06

Linuxkernel設(shè)備樹

2022-01-26 15:20:00

配置微服務(wù)架構(gòu)

2009-07-15 13:41:00

JDBC實(shí)例

2017-02-10 15:32:47

2017-11-06 17:16:55

Linux設(shè)備驅(qū)動并發(fā)控制

2023-05-15 08:58:41

塊設(shè)備驅(qū)動Linux

2021-04-12 12:00:13

Linux運(yùn)維Linux系統(tǒng)

2018-01-22 09:56:24

2017-03-02 13:31:02

監(jiān)控系統(tǒng)

2021-12-09 10:57:19

防抖函數(shù) Debounce
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产精品国产精品国产专区不卡 | 国产在线观看网站 | 国产精品久久久久久久久久久久 | 精品视频一区二区 | 国产农村妇女精品一区 | 欧美精品久久 | 黄在线免费观看 | 国产一区二区三区 | 黄一区二区三区 | 瑟瑟免费视频 | 日韩欧美成人一区二区三区 | 成av在线| 亚洲一区导航 | 亚洲国产aⅴ成人精品无吗 综合国产在线 | 久久国产婷婷国产香蕉 | 亚洲欧美日韩在线不卡 | 日韩一级电影免费观看 | 日韩精品视频一区二区三区 | 国产高清一区二区三区 | 91视频免费黄 | 伊人伊成久久人综合网站 | 黑人精品xxx一区一二区 | 精品综合| 欧美激情国产日韩精品一区18 | 午夜精品一区二区三区三上悠亚 | 97伦理| 日韩精品一区二区三区在线观看 | 国产日韩视频在线 | 久久精品视频免费观看 | 欧美日韩1区2区 | 久一精品 | 一区二区福利视频 | 在线播放中文字幕 | 日韩在线中文 | 久久久久久国产精品免费免费狐狸 | 波多野吉衣久久 | 亚洲综合无码一区二区 | 亚洲www.| 欧美精品1区2区 | 91视频免费 | 久久精品成人一区 |