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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第五十五讲 插件设备树

發布時間:2023/12/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第五十五讲 插件设备树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第五十五講 插件設備樹

文章目錄

  • 第五十五講 插件設備樹
    • 一、概述
      • 1、概述
      • 2、使用前提
      • 3、編譯工具
    • 二、插件設備樹實驗
      • 1、環境準備
      • 2、實驗
      • 3、驗證實驗
    • 附錄
      • 驅動代碼
        • led.c
        • led.h
        • makefile

一、概述

1、概述

插件設備樹是在Linux4.4后引入的。

傳統的設備樹是批量管理硬件資源,如果需要添加或者刪除硬件資源,需要找出已經在設備中使用的的設備樹源文件然后在源文件上修改。這樣當硬件很多的時候會造成不便。

設備樹插件可以理解為主設備樹的“補丁”它動態的加載到系統中,并被內核識別。設備樹插件擁有相對固定的格式,甚至可以認為它只是把設備節點加了一個“殼”編譯后內核能夠動態加載它。 我們只需要根據格式編寫即可,格式如下:

/dts-v1/; /plugin/;/{fragment@0 {target-path = "/";__overlay__ {/*在此添加要插入的節點*/};}; }; /dts-v1/;用于指定dts的版本。
/plugin/;表示允許使用未定義的引用并記錄它們,設備樹插件中可以引用主設備樹中的節點, 而這些“引用的節點”對于設備樹插件來說就是未定義的,所以設備樹插件應該加上“/plugin/”。
target-path = “/”;指定設備樹插件的加載位置,默認我們加載到根節點下,既“target-path =“/”。
overlay { /在此添加要插入的節點/ };我們要插入的設備及節點或者要引用(追加)的設備樹節點放在__overlay__ {…};內。

2、使用前提

編譯內核需要打開的配置

  • CONFIG_OF_OVERLAY = y
  • CONFIG_OF_CONFIGFS = y

掛載ConfigFS

mount x /sys/kernel/config -t configfs

3、編譯工具

安裝:sudo apt install device-tree-compiler

編譯示例:dtc -I dts -O dtb -o overlay.dtbo overlay.dts

二、插件設備樹實驗

1、環境準備

  • 安裝設備樹編譯工具

    sudo apt install device-tree-compiler

    軟件使用方法查詢man dtc

2、實驗

  • 編寫 overlay 代碼

    /dts-v1/;/plugin/;/ {fragment@0{target-path = "/";__overlay__{gunzai_led{#address-cells = <1>;#size-cells = <1>;compatible = "fire,rgb_led";ranges;rgb_led_red@0x020C406C{reg = <0x020C406C 0x000000040x020E006C 0x000000040x020E02F8 0x000000040x0209C000 0x000000040x0209C004 0x00000004>;status = "okay";};rgb_led_green@0x020C4074{reg = <0x020C4074 0x000000040x020E01E0 0x000000040x020E046C 0x000000040x020A8000 0x000000040x020A8004 0x00000004>;status = "okay";};rgb_led_blue@0x020C4074{reg = <0x020C4074 0x000000040x020E01DC 0x000000040x020E0468 0x000000040x020A8000 0x000000040x020A8004 0x00000004>;status = "okay";};};};};};
  • 編譯 overlay 設備樹

    dtc -I dts -O dtb -o overlay.dtbo overlay.dts

    overlay.dtbo: Warning (ranges_format): /fragment@0/__overlay__/gunzai_led has empty "ranges" property but its #address-cells (1) differs from /fragment@0/__overlay__ (2) overlay.dtbo: Warning (unit_address_vs_reg): Node /fragment@0 has a unit name, but no reg property overlay.dtbo: Warning (unit_address_format): Node /fragment@0/__overlay__/gunzai_led/rgb_led_red@0x020C406C unit name should not have leading "0x" overlay.dtbo: Warning (unit_address_format): Node /fragment@0/__overlay__/gunzai_led/rgb_led_red@0x020C406C unit name should not have leading 0s overlay.dtbo: Warning (unit_address_format): Node /fragment@0/__overlay__/gunzai_led/rgb_led_green@0x020C4074 unit name should not have leading "0x" overlay.dtbo: Warning (unit_address_format): Node /fragment@0/__overlay__/gunzai_led/rgb_led_green@0x020C4074 unit name should not have leading 0s overlay.dtbo: Warning (unit_address_format): Node /fragment@0/__overlay__/gunzai_led/rgb_led_blue@0x020C4074 unit name should not have leading "0x" overlay.dtbo: Warning (unit_address_format): Node /fragment@0/__overlay__/gunzai_led/rgb_led_blue@0x020C4074 unit name should not have leading 0s overlay.dtbo: Warning (avoid_default_addr_size): Relying on default #address-cells value for /fragment@0/__overlay__/gunzai_led overlay.dtbo: Warning (avoid_default_addr_size): Relying on default #size-cells value for /fragment@0/__overlay__/gunzai_led
  • 將 dtbo 復制到開發板上

    通過連接虛擬機 sftp 用戶名@IP地址 示例:sftp dragon@192.168.3.41

    進入代碼目錄cd 編譯好的 dtbo 目錄

    下載 overlay.dtbo 到開發板 get overlay.dtbo

    退出ftp exit

  • 進入開發板,找到剛才傳輸過來的文件

  • 將 dtbo 文件移到目錄 設備樹目錄下sudo cp overlay.dtbo /usr/lib/linux-image-4.19.35-imx6/overlays/

  • 修改 uEnv.txt 文件

    新增dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/overlay.dtbo

    #Docs: https://embed-linux-tutorial.readthedocs.io/zh_CN/latest/README.htmluname_r=4.19.35-imx6 #uuid= mmc_dtb=imx6ull-mmc-npi.dtb nand_dtb=imx6ull-nand-npi.dtb###U-Boot Overlays### ###Documentation: https://embed-linux-tutorial.readthedocs.io/zh_CN/latest/linux_driver/device_tree_rgb_led.html ###Master Enable enable_uboot_overlays=1 #overlay_startdtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c1.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c2.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-74hc595.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-485r1.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-485r2.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-adc1.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-hdmi.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-cam.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-btwifi.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-can1.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-can2.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-dht11.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-ecspi3.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-key.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-lcd.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-goodix.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-led.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-sound.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-uart2.dtbo #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-uart3.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-mpu6050.dtbo dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/overlay.dtbo#overlay_endcmdline=coherent_pool=1M net.ifnames=0 vt.global_cursor_default=0#In the event of edid real failures, uncomment this next line: #cmdline=coherent_pool=1M net.ifnames=0 vt.global_cursor_default=0 video=HDMI-A-1:1024x768@60e#Use an overlayfs on top of a read-only root filesystem: #cmdline=coherent_pool=1M net.ifnames=0 vt.global_cursor_default=0 overlayroot=tmpfs##flash_firmware=continued #flash_firmware=once
  • 重啟開發板 sudo reboot

  • 登錄開發板

  • 查看設備

    ls /proc/device-tree

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eAqmIQd4-1665421762193)(C:\Users\Dragon\Desktop\學習\學習筆記\野火linux學習筆記\第四期\第五十五講 插件設備樹.assets\image-20221011001922804.png)]

  • 試驗成功

3、驗證實驗

  • 將之前的 led 驅動程序拷貝到開發板(這里就不具體說明了)

  • 加載驅動程序 sudo insmod rgb_led.ko

    debian@npi:~/ftp$ sudo insmod rgb_led.ko [sudo] password for debian: Sorry, try again. [sudo] password for debian: [ 81.163173] rgb_led: loading out-of-tree module taints kernel. [ 81.175548] <1> path is shadowrain_led [ 81.179411] DriverState is 0
  • 查看 dev 設備加載是否成功

    ls /dev/

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LOQ6aTjD-1665421762200)(C:\Users\Dragon\Desktop\學習\學習筆記\野火linux學習筆記\第四期\第五十五講 插件設備樹.assets\image-20221011010527408.png)]

  • 點燈

    綠燈

    sudo sh -c "echo 'green on'>/dev/shadowrain_led"

    其他的燈自己點哈,就不演示了

  • 附錄

    驅動代碼

    led.c

    /** @LastEditors: 夜雨* @Date: 2022-03-17 20:56:32* @LastEditTime: 2022-03-19 13:15:37* @FilePath: \code\kernel\012rgb_led\rgb_led.c*/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/platform_device.h>#include "rgb_led.h"int rgbLedOpen (struct inode *node, struct file *file){printk("\n open form driver \n");return 0;}ssize_t rgbLedWrite (struct file *file, const char __user *usr, size_t size, loff_t *loff){char lRecvBuf[10] = {0};int lRegData = 0;printk("<1> Led write");if(size >= 10){printk("<1> size error!");return -1;}if(copy_from_user(lRecvBuf, usr, size) < 0){printk("<1> copy error!");return -1;}printk("<1> recv is %s", lRecvBuf);if(strstr(lRecvBuf, "red on") != NULL){printk("red on");lRegData = ioread32(gRGBLedStr[0].virtual_DR);lRegData &= ~(0x01 << 4);iowrite32(lRegData, gRGBLedStr[0].virtual_DR);}else if(strstr(lRecvBuf, "red off") != NULL){lRegData = ioread32(gRGBLedStr[0].virtual_DR);lRegData |= (0x01 << 4);iowrite32(lRegData, gRGBLedStr[0].virtual_DR);}else if(strstr(lRecvBuf, "green on") != NULL){lRegData = ioread32(gRGBLedStr[1].virtual_DR);lRegData &= ~(0x01 << 20);iowrite32(lRegData, gRGBLedStr[1].virtual_DR);}else if(strstr(lRecvBuf, "green off") != NULL){lRegData = ioread32(gRGBLedStr[1].virtual_DR);lRegData |= (0x01 << 20);iowrite32(lRegData, gRGBLedStr[1].virtual_DR);}else if(strstr(lRecvBuf, "blue on") != NULL){lRegData = ioread32(gRGBLedStr[2].virtual_DR);lRegData &= ~(0x01 << 19);iowrite32(lRegData, gRGBLedStr[2].virtual_DR);}else if(strstr(lRecvBuf, "blue off") != NULL){lRegData = ioread32(gRGBLedStr[2].virtual_DR);lRegData |= (0x01 << 19);iowrite32(lRegData, gRGBLedStr[2].virtual_DR);}else{printk("error data %s", lRecvBuf);lRegData = ioread32(gRGBLedStr[0].virtual_DR);lRegData |= (0x01 << 4);iowrite32(lRegData, gRGBLedStr[0].virtual_DR);lRegData = ioread32(gRGBLedStr[1].virtual_DR);lRegData |= (0x01 << 20);iowrite32(lRegData, gRGBLedStr[1].virtual_DR);lRegData = ioread32(gRGBLedStr[2].virtual_DR);lRegData |= (0x01 << 19);iowrite32(lRegData, gRGBLedStr[2].virtual_DR);}return size;}struct cdev gRGBLedCdev = {.owner = THIS_MODULE,};struct file_operations gRGBLedFp = {.open = rgbLedOpen,.write = rgbLedWrite,};static int rgbProbe(struct platform_device *pdv){struct device_node *lRGBLedDeviceNode;int lRegData = 0;/*查找設備樹節點*/printk("<1> path is "DEVICE_NAME"");lRGBLedDeviceNode = of_find_node_by_path("/"DEVICE_NAME"");if(lRGBLedDeviceNode == NULL){printk("<1> Find node by path failed! \n");return -1;}/*獲取rgb_led節點的燈子節點*/gRGBLedStr[0].device_node = of_find_node_by_name(lRGBLedDeviceNode, "rgb_led_red");if(gRGBLedStr[0].device_node == NULL){return -1;}/*獲取 reg 屬性并轉化為虛擬地址*/gRGBLedStr[0].virtual_CCM_CCGR = of_iomap(gRGBLedStr[0].device_node, 0);gRGBLedStr[0].virtual_IOMUXC_SW_MUX_CTL_PAD = of_iomap(gRGBLedStr[0].device_node, 1);gRGBLedStr[0].virtual_IOMUXC_SW_PAD_CTL_PAD = of_iomap(gRGBLedStr[0].device_node, 2);gRGBLedStr[0].virtual_DR = of_iomap(gRGBLedStr[0].device_node, 3);gRGBLedStr[0].virtual_GDIR = of_iomap(gRGBLedStr[0].device_node, 4);// 初始化rgb端口/*---------------------------------------------------------------------------------*/lRegData = ioread32(gRGBLedStr[0].virtual_CCM_CCGR);iowrite32(lRegData | (3 << 26), gRGBLedStr[0].virtual_CCM_CCGR);lRegData = ioread32(gRGBLedStr[0].virtual_IOMUXC_SW_MUX_CTL_PAD);lRegData &= ~(0xf << 0);lRegData |= (0x05 << 0);iowrite32(lRegData, gRGBLedStr[0].virtual_IOMUXC_SW_MUX_CTL_PAD);lRegData = ioread32(gRGBLedStr[0].virtual_IOMUXC_SW_PAD_CTL_PAD);lRegData = (0x10B0);iowrite32(lRegData, gRGBLedStr[0].virtual_IOMUXC_SW_PAD_CTL_PAD);lRegData = ioread32(gRGBLedStr[0].virtual_GDIR);lRegData |= (0x01 << 4);iowrite32(lRegData, gRGBLedStr[0].virtual_GDIR);lRegData = ioread32(gRGBLedStr[0].virtual_DR);lRegData |= (0x01 << 4);iowrite32(lRegData, gRGBLedStr[0].virtual_DR);/*---------------------------------------------------------------------------------*/gRGBLedStr[1].device_node = of_find_node_by_name(lRGBLedDeviceNode, "rgb_led_green");if(gRGBLedStr[1].device_node == NULL){return -1;}/*獲取 reg 屬性并轉化為虛擬地址*/gRGBLedStr[1].virtual_CCM_CCGR = of_iomap(gRGBLedStr[1].device_node, 0);gRGBLedStr[1].virtual_IOMUXC_SW_MUX_CTL_PAD = of_iomap(gRGBLedStr[1].device_node, 1);gRGBLedStr[1].virtual_IOMUXC_SW_PAD_CTL_PAD = of_iomap(gRGBLedStr[1].device_node, 2);gRGBLedStr[1].virtual_DR = of_iomap(gRGBLedStr[1].device_node, 3);gRGBLedStr[1].virtual_GDIR = of_iomap(gRGBLedStr[1].device_node, 4);lRegData = ioread32(gRGBLedStr[1].virtual_CCM_CCGR);lRegData |= (0x03 << 12);iowrite32(lRegData, gRGBLedStr[1].virtual_CCM_CCGR);lRegData = ioread32(gRGBLedStr[1].virtual_IOMUXC_SW_MUX_CTL_PAD);lRegData &= ~(0xf << 0);lRegData |= (0x05 << 0);iowrite32(lRegData, gRGBLedStr[1].virtual_IOMUXC_SW_MUX_CTL_PAD);lRegData = ioread32(gRGBLedStr[1].virtual_IOMUXC_SW_PAD_CTL_PAD);lRegData = (0x10B0);iowrite32(lRegData, gRGBLedStr[1].virtual_IOMUXC_SW_PAD_CTL_PAD);lRegData = ioread32(gRGBLedStr[1].virtual_GDIR);lRegData |= (0x01 << 20);iowrite32(lRegData, gRGBLedStr[1].virtual_GDIR);lRegData = ioread32(gRGBLedStr[1].virtual_DR);lRegData |= (0x01 << 20);iowrite32(lRegData, gRGBLedStr[1].virtual_DR);/*---------------------------------------------------------------------------------*/gRGBLedStr[2].device_node = of_find_node_by_name(lRGBLedDeviceNode,"rgb_led_blue");if (gRGBLedStr[2].device_node == NULL){printk(KERN_ERR "\n get rgb_led_blue_device_node failed ! \n");return -1;}/*獲取 reg 屬性并轉化為虛擬地址*/gRGBLedStr[2].virtual_CCM_CCGR = of_iomap(gRGBLedStr[2].device_node, 0);gRGBLedStr[2].virtual_IOMUXC_SW_MUX_CTL_PAD = of_iomap(gRGBLedStr[2].device_node, 1);gRGBLedStr[2].virtual_IOMUXC_SW_PAD_CTL_PAD = of_iomap(gRGBLedStr[2].device_node, 2);gRGBLedStr[2].virtual_DR = of_iomap(gRGBLedStr[2].device_node, 3);gRGBLedStr[2].virtual_GDIR = of_iomap(gRGBLedStr[2].device_node, 4);/*初始化藍燈*/lRegData = ioread32(gRGBLedStr[2].virtual_CCM_CCGR);lRegData |= (0x03 << 12);iowrite32(lRegData, gRGBLedStr[2].virtual_CCM_CCGR); //開啟時鐘lRegData = ioread32(gRGBLedStr[2].virtual_IOMUXC_SW_MUX_CTL_PAD);lRegData &= ~(0xf << 0);lRegData |= (0x05 << 0);iowrite32(lRegData, gRGBLedStr[2].virtual_IOMUXC_SW_MUX_CTL_PAD); //設置復用功能lRegData = ioread32(gRGBLedStr[2].virtual_IOMUXC_SW_PAD_CTL_PAD);lRegData = (0x10B0);iowrite32(lRegData, gRGBLedStr[2].virtual_IOMUXC_SW_PAD_CTL_PAD); //設置PAD 屬性lRegData = ioread32(gRGBLedStr[2].virtual_GDIR);lRegData |= (0x01 << 19);iowrite32(lRegData, gRGBLedStr[2].virtual_GDIR); //設置GPIO4_IO19 為輸出模式lRegData = ioread32(gRGBLedStr[2].virtual_DR);lRegData |= (0x01 << 19);iowrite32(lRegData, gRGBLedStr[2].virtual_DR); //設置 GPIO4_IO19 默認輸出高電平if( alloc_chrdev_region(&rgbDev, 0, 1, DEVICE_NAME) < 0){printk("<1> alloc_chrdev_region failed \n");return -1;} cdev_init(&gRGBLedCdev, &gRGBLedFp);cdev_add(&gRGBLedCdev, rgbDev, 1);rgbClass = class_create(THIS_MODULE, DEVICE_NAME);device_create(rgbClass, NULL, rgbDev, NULL, DEVICE_NAME);return 0;}static const struct of_device_id rgbLed[] = {{.compatible = "fire,rgb_led"},{/* sentinel */}};struct platform_driver rgbPlatformDriver = {.probe = rgbProbe,.driver = {.name = "rgb_led_platform",.owner = THIS_MODULE,.of_match_table = rgbLed,},};static __init int RGBInit(void){int driverState;driverState = platform_driver_register(&rgbPlatformDriver);printk(KERN_ALERT "\tDriverState is %d\n", driverState);return 0;}static __exit void RGBExit(void){}module_init(RGBInit);module_exit(RGBExit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Yeyu");MODULE_DESCRIPTION("RGBModule");MODULE_ALIAS("RGBModule");

    led.h

    /** @LastEditors: 夜雨* @Date: 2022-03-17 22:41:17* @LastEditTime: 2022-03-19 12:23:54* @FilePath: \code\kernel\012rgb_led\rgb_led.h*/#include <linux/of.h>#include <asm/io.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/kernel.h>#include <linux/uaccess.h>#include <linux/string.h>#include <linux/of_gpio.h>#include <linux/io.h>#include <linux/of_address.h>#define DEVICE_NAME "shadowrain_led"typedef struct {struct device_node *device_node;void __iomem *virtual_CCM_CCGR;void __iomem *virtual_IOMUXC_SW_MUX_CTL_PAD;void __iomem *virtual_IOMUXC_SW_PAD_CTL_PAD;void __iomem *virtual_DR;void __iomem *virtual_GDIR;}rgbLedStr;dev_t rgbDev;struct class * rgbClass;rgbLedStr gRGBLedStr[3];

    makefile

    KERNEL_DIR=../../ebf_linux_kernel/build_image/build/ARCH=armCROSS_COMPILE=arm-linux-gnueabihf-export ARCH CROSS_COMPILEobj-m := rgb_led.oall:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules.PHONE:clean copyclean:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean copy:sudo cp *.ko /home/dragon/nfsshare

    參考資料

    EBF_6ULL開發板快速使用手冊

    設備樹

    總結

    以上是生活随笔為你收集整理的第五十五讲 插件设备树的全部內容,希望文章能夠幫你解決所遇到的問題。

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