自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

一、前言

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

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

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

必須安排!

在學習設備樹之前,大家一定要搞清楚什么是platform總線,請詳細學習下面這篇文章:

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

關于設備樹理論部分內(nèi)容請學習下面這篇文章:

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

關于驅(qū)動基礎文章,可以去B站學習一口君的入門視頻:

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

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

有了這些基礎知識后,我們就可以來編寫一個設備樹的實例,

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

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

二、測試平臺

本次測試在開發(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)核解析設備樹一般過程

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

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

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

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

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

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

四、驅(qū)動架構

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

我們只需要將測試代碼填充到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); 

五、設備樹節(jié)點

下面是給出的設備樹信息:

  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é)點、時鐘等屬性。

一定要注意,很多屬性的給出會因為使用的SOC平臺的不同有所差異, 下面介紹下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單獨使用1個名字。

gpio需要指明父節(jié)點,關于gpio父節(jié)點的說明下說明文檔(通常linux-3.14\Documentation下有關于該內(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é)成如下幾點:

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

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

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

  1. gpios = <&qe_pio_e 18 0>; 

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

2. 中斷

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

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

其中

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

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

  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é)點 
  7.   interrupts = <4 3>;     #節(jié)點屬性 
  8.  }; 

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

  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é)點gpx1定義如下(該文件由三星廠家出廠定制好):

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

可見三星的exynos4412平臺中gpx1,既可以做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ā)方式

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

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

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

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

七、編譯(ubuntu中操作)

驅(qū)動編譯:

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

設備樹編譯:

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

除此之外驅(qū)動模塊文件、設備樹文件如何導入給開發(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

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

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

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

 

責任編輯:姜華 來源: 一口Linux
相關推薦

2022-05-10 08:49:46

設備驅(qū)動Linux

2022-03-09 09:43:01

工具類線程項目

2022-10-31 08:27:53

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

2021-02-22 17:17:38

Proxy緩存代碼

2021-10-25 16:01:01

Linux設備樹字符串

2020-12-03 08:59:06

Linux設備驅(qū)動

2020-11-02 08:19:18

RPC框架Java

2021-03-18 08:04:54

AQS工具CAS

2021-12-07 06:55:17

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

2017-10-24 17:03:48

Linux驅(qū)動程序編譯

2021-07-30 14:55:06

Linuxkernel設備樹

2022-01-26 15:20:00

配置微服務架構

2009-07-15 13:41:00

JDBC實例

2017-02-10 15:32:47

2018-01-22 09:56:24

2017-11-06 17:16:55

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

2023-05-15 08:58:41

塊設備驅(qū)動Linux

2021-12-09 10:57:19

防抖函數(shù) Debounce

2017-03-02 13:31:02

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

2021-04-12 12:00:13

Linux運維Linux系統(tǒng)
點贊
收藏

51CTO技術棧公眾號