色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

pinctrl與gpio子系統下的字符設備驅動框架

CHANBAEK ? 來源:嵌入式攻城獅 ? 作者:安迪西 ? 2023-04-13 15:19 ? 次閱讀

pinctrl與gpio子系統下的字符設備驅動框架

點亮Linux驅動開發路上的第一個燈一文中將與外設有關的寄存器信息,定義到驅動代碼中,直接操作寄存器來控制外設。缺點是當芯片的寄存器發了變動,就要對底層的驅動進行重寫。

設備樹下的字符設備驅動框架一文中將與外設有關的寄存器信息,寫到了設備樹文件中,通過設備樹API函數獲取外設信息。當外設的信息有變化時,只需要修改設備樹文件即可,無需修改底層驅動,提高了驅動代碼的復用能力,但仍需要直接操作寄存器來控制外設。

本文介紹的pinctrl和gpio子系統實現了對寄存器的操作,我們只需要使用子系統提供的API函數即可,而無需再直接操作寄存器了。

1. pinctrl與gpio子系統介紹

1.1 pinctrl子系統

pinctrl子系統就是管理PIN引腳的一個系統,在設備樹里設置PIN的配置信息,pinctrl會根據提供的信息來配置PIN功能。其主要工作內容如下:

  • 獲取設備樹中的PIN信息
  • 設置獲取到的PIN的復用功能
  • 設置獲取到的PIN的電氣特性

打開設備樹文件imx6ull-andyxi-emmc.dts,其中iomuxc節點就是I.MX6ULL的外設節點。代碼中的pinctrl_hog_1子節點就是和熱插拔有關的PIN集合

&iomuxc {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_hog_1>;
    imx6ul-evk {
        pinctrl_hog_1: hoggrp-1 {
            fsl,pins = <
                MX6UL_PAD_UART1_RTS_B__GPIO1_IO19        0x17059 
                MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT     0x17059 
                MX6UL_PAD_GPIO1_IO09__GPIO1_IO09         0x17059 
                MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID     0x13058
           >;
        };
        ......
    };
};

下面以UART1_RTS_B這個PIN為例,介紹如何添加PIN的配置信息:

MX6UL_PAD_UART1_RTS_B__GPIO1_IO19     0x17059

前半部分:設置UART1_RTS_B引腳的復用功能

//MX6UL_PAD_UART1_RTS_B__GPIO1_IO19宏定義在文件arch/arm/boot/dts/imx6ul-pinfunc.h中
#define MX6UL_PAD_UART1_RTS_B__UART1_DCE_RTS          0x0090 0x031C 0x0620 0x0 0x3
#define MX6UL_PAD_UART1_RTS_B__UART1_DTE_CTS          0x0090 0x031C 0x0000 0x0 0x0
#define MX6UL_PAD_UART1_RTS_B__ENET1_TX_ER            0x0090 0x031C 0x0000 0x1 0x0
#define MX6UL_PAD_UART1_RTS_B__USDHC1_CD_B            0x0090 0x031C 0x0668 0x2 0x1
#define MX6UL_PAD_UART1_RTS_B__CSI_DATA05             0x0090 0x031C 0x04CC 0x3 0x1
#define MX6UL_PAD_UART1_RTS_B__ENET2_1588_EVENT1_OUT  0x0090 0x031C 0x0000 0x4 0x0
#define MX6UL_PAD_UART1_RTS_B__GPIO1_IO19             0x0090 0x031C 0x0000 0x5 0x0
#define MX6UL_PAD_UART1_RTS_B__USDHC2_CD_B            0x0090 0x031C 0x0674 0x8 0x2

上面代碼中共有8個UART1_RTS_B引腳的宏定義,分別對應該引腳的8個復用IO。宏定義的值,被分為了5段,每段的值都有具體的含義:

圖片

  • mux_reg:mux_reg寄存器偏移地址 (見下圖1)
  • conf_reg:conf_reg寄存器偏移地址 (見下圖2)
  • input_reg:input_reg寄存器偏移地址 (此處無效)
  • mux_mode:mux_reg寄存器的值,用于設置復用功能 (見下圖3)
  • input_val:input_reg寄存器值 (此處無效)

圖片

圖片

圖片

后半部分:此值就是conf_reg寄存器的值,用于設置UART1_RTS_B引腳的電氣特性

1.2 gpio子系統

gpio子系統就是管理gpio功能的一個系統,其作用是初始化gpio,并提供對外的API接口。使用gpio子系統后,就無需自己操作寄存器,通過調用相關API函數即可實現對gpio的控制。

仍以熱插拔節點為例,pinctrl子系統已經將UART1_RTS_B復用為GPIO1_IO19,并設置好了電氣屬性。驅動程序通過讀取其高低電平來判斷SD卡有沒有插入。

那驅動程序怎么知道CD引腳連接的是GPIO1_IO19呢 ?這就需要設備樹來告訴驅動了,在設備樹的SD卡節點下添加一個描述CD引腳的屬性:

&usdhc1 {
    pinctrl-names = "default", "state_100mhz", "state_200mhz";
    pinctrl-0 = <&pinctrl_usdhc1>;
    pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
    pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
    pinctrl-3 = <&pinctrl_hog_1>;
    cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
    keep-power-in-suspend;
    enable-sdio-wakeup;
    vmmc-supply = <®_sd1_vmmc>;
    status = "okay";
};

上面代碼中pinctrl-3指定了CD引腳的pinctrl信息,cd-gpios屬性描述了CD引腳使用哪個IO,屬性值共有三個,具體含義如下:

  • &gpio1 表示CD引腳所使用的IO屬于GPIO1組
  • 19 表示GPIO1組的第19號IO
  • GPIO_ACTIVE_LOW 表示低電平有效

設置好設備樹后就可使用gpio子系統提供的API函數來操作指定的GPIO,gpio子系統向開發人員屏蔽了具體的讀寫寄存器過程。下圖中有常用的API函數介,此外還有pinctrl和gpio子系統的使用模板:

圖片

**2. **pinctrl與gpio子系統字符設備驅動框架

下圖為pinctrl與gpio子系統下的字符設備驅動框架:

圖片

接下來根據上面的框架圖,以驅動LED (GPIO1_IO03) 為例,分步介紹具體的代碼編寫流程

2.1 修改設備樹文件

添加pinctrl節點:在iomuxc節點的imx6ul-evk子節點下創建pinctrl_led節點,復用GPIO1_IO03

pinctrl_led: ledgrp {
    fsl,pins = <
        MX6UL_PAD_GPIO1_IO03__GPIO1_IO03    0x10B0
    >;
};
//MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 復用GPIO1_IO03
//0x10B0 設置pin的電氣特性

添加LED設備節點:在根節點下創建LED設備節點,指定對應的pinctrl節點,指定所使用的GPIO

gpioled {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "alpha-gpioled";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_led>;
    led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
    status = "okay";
};

檢查PIN是否沖突:檢查pinctrl和設備節點中指定的引腳有沒有被別的外設占用

//檢查GPIO_IO03這個PIN有沒有被其他的pinctrl節點使用
pinctrl_tsc: tscgrp {
    fsl,pins = <
        MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
        MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
        //GPIO_IO03被pinctrl_tsc節點占用,因此需要屏蔽掉
        /* MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0 */ 
        MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
    >;
};
//檢查"gpio1 3"有沒有被其他設備節點占用
&tsc {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_tsc>;
    //"gpio1 3"被tsc設備節點占用,因此需要屏蔽掉
    /* xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; */
    measure-delay-time = <0xffff>;
    pre-charge-time = <0xfff>;
    status = "okay";
};

編譯設備樹:使用make dtbs命令編譯設備樹,并使用該設備樹啟動Linux系統

#在內核根目錄下
make dtbs                #編譯設備樹
#啟動Linux系統后
cd /proc/device-tree     #查看"gpioled"節點是否存在

2.2 編寫驅動程序

創建驅動程序文件gpioled.c,添加如下代碼

宏定義及設備結構體定義

struct gpioled_dev{
    dev_t devid;                //設備號
    struct cdev cdev;           //cdev字符設備
    struct class *class;        //類
    struct device *device;      //設備
    int major;                  //主設備號
    int minor;                  //次設備號
    struct device_node *nd;     //設備節點
    int led_gpio;               //所使用的gpio編號
};

struct gpioled_dev gpioled;     //定義led設備

編寫設備操作函數:write函數中,直接使用gpio子系統提供的API函數操作GPIO

static ssize_t led_write(struct file *filp, char __user *buf, size_t cnt, loff_t *offt){
    int retvalue;
    unsigned char databuf[1];
    unsigned char ledstat;
    struct gpioled_dev *dev = filp->private_data;
    retvalue = copy_from_user(databuf, buf, cnt); 
    if(retvalue < 0){
        printk("kernel write failed!\\r\\n");
        return -EFAULT;
    }

    ledstat = databuf[0];
    if(ledstat == LEDON){
        gpio_set_value(dev->led_gpio, 0);
    }else if(ledstat == LEDOFF){
        gpio_set_value(dev->led_gpio, 1);
    }
    return 0;
}

驅動入口函數中:獲取GPIO編號后初始化

/* 設置 LED 所使用的 GPIO */
/* 1、獲取設備節點:gpioled */
gpioled.nd = of_find_node_by_path("/gpioled");
if(gpioled.nd == NULL) {
    printk("gpioled node cant not found!\\r\\n");
    return -EINVAL;
} else {
    printk("gpioled node has been found!\\r\\n");
}
/* 2、 獲取設備樹中的 gpio 屬性,得到 LED 所使用的 LED 編號 */
gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0);
if(gpioled.led_gpio < 0) {
    printk("can't get led-gpio");
    return -EINVAL;
}
printk("led-gpio num = %d\\r\\n", gpioled.led_gpio);
/* 3、設置 GPIO1_IO03 為輸出,并且輸出高電平,默認關閉 LED 燈 */
ret = gpio_direction_output(gpioled.led_gpio, 1);
if(ret < 0) {
    printk("can't set gpio!\\r\\n");
}

驅動入口函數中:注冊字符設備驅動,代碼與Linux點燈中一樣

驅動出口函數中:注銷設備驅動,刪除類和設備,代碼可參考Linux點燈一文

2.3 編寫測試程序

實現操作驅動文件對外設進行控制的功能。創建測試程序文件gpioledApp.c,代碼內容與Linux點燈一文中的測試程序代碼一致,此處不再贅述

2.4 編譯測試

編譯驅動程序:當前目錄下創建Makefile文件,并make編譯

KERNELDIR := /home/andyxi/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_andyxi
CURRENT_PATH := $(shell pwd)
obj-m := gpioled.o

build: kernel_modules

kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

編譯測試程序:無需內核參與,直接編譯即可

arm-linux-gnueabihf-gcc gpioledApp.c -o gpioledApp

運行測試:啟動開發板后,加載驅動模塊,之后使用應用程序測試驅動是否正常工作

depmod                         #第一次加載驅動的時候需要運行此命令
modprobe gpioled.ko            #加載驅動
./gpioledApp /dev/gpioled 1    #打開LED燈
./gpioledApp /dev/gpioled 0    #關閉LED燈
rmmod gpioled.ko               #卸載驅動模塊
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5342

    瀏覽量

    120317
  • Linux
    +關注

    關注

    87

    文章

    11303

    瀏覽量

    209435
  • 子系統
    +關注

    關注

    0

    文章

    109

    瀏覽量

    12398
  • 字符
    +關注

    關注

    0

    文章

    233

    瀏覽量

    25205
  • GPIO
    +關注

    關注

    16

    文章

    1204

    瀏覽量

    52086
收藏 人收藏

    評論

    相關推薦

    一文搞懂Linux pinctrl/gpio子系統

    GPIO的寄存器操作。分享給剛剛接觸外設bsp的小伙伴們。當然后面有時間還會分享GPIO子系統框架pinctrl
    發表于 06-09 09:52 ?2710次閱讀

    「正點原子Linux連載」第四十五章 pinctrlgpio子系統實驗(一)

    驅動分離與分層其實就是按照面向對象編程的設計思想而設計的設備驅動框架,關于驅動的分離與分層我們后面會講。本來
    發表于 03-19 14:58

    「正點原子Linux連載」第四十五章 pinctrlgpio子系統實驗(二)

    =5};第4行,test設備所使用的gpio。關于pinctrl子系統gpio子系統就講解到
    發表于 03-19 14:59

    字符設備驅動 —— 字符設備驅動框架

    1、概述:linux中一切皆文件,設備也如此,并且以操作文件即文件IO的方式訪問設備。  應用程序只能通過庫函數中的系統調用來操作硬件,對于每個系統調用,
    發表于 10-19 17:08

    基于GPIO子系統的LED驅動程序分享

    Pinctrl 子系統把引腳的復用、配置抽出來,做成 Pinctrl 子系統,給 GPIO、I2C 等模塊使用。讓我們在使用某個引腳功能時不
    發表于 12-16 07:16

    怎樣去使用linux的pintcrl和gpio子系統

    pinctrlgpio內部的原理是如何實現的?怎樣去使用linux的pintcrl和gpio子系統呢?
    發表于 03-07 13:38

    RK3399開發板的pinctrlgpio子系統相關資料介紹

    驅動工程師只做驅動,應用工程師專注做應用。  linux的pintcrl和gpio子系統就類似于ST的“BSP庫”,但是linux的
    發表于 09-16 17:27

    更新 | 持續開源 迅為RK3568驅動指南第十一篇-pinctrl子系統

    篇 熱插拔 第11篇 pinctrl子系統 未完待續,持續更新中... 視頻教程更新至十二期 第一期_驅動基礎 第二期_字符設備基礎 第三期
    發表于 10-18 11:12

    gpiopinctrl子系統的關系與區別

    gpiopinctrl 子系統在內核里的使用率非常高,和嵌入式產品的關聯非常大。從這兩個子系統開始學習驅動開發是個不錯的入門選擇。
    的頭像 發表于 03-15 11:40 ?4958次閱讀

    嵌入式驅動開發兩大子系統的使用

    本文的關注點是 gpio driver --> gpio subsystem core -> gpio consumer 這一路徑,讀者如果想更深入地了解 pinctrl
    的頭像 發表于 03-15 13:41 ?1809次閱讀

    【i.MX6ULL】驅動開發6——GPIO子系統點亮LED

    本篇介紹了使用**Pinctrl子系統GPIO子系統**的方式來點亮LED,與之前的寄存器版點亮LED與設備樹版點亮LED的最大區別在于不
    的頭像 發表于 05-21 21:50 ?3186次閱讀
    【i.MX6ULL】<b class='flag-5'>驅動</b>開發6——<b class='flag-5'>GPIO</b><b class='flag-5'>子系統</b>點亮LED

    使用pinctrlgpio子系統實現LED燈驅動

    前邊已經學了兩種點燈,本質依然還是通過配置寄存器;在學習STM32的時候除了學習配置一寄存器,基本都是使用庫來開發,那么在i.MX6ULL還使用寄存器開發明顯是不太適合,那么i.MX6ULL有更方便的開發呢,這篇就來學習一使用 pi
    的頭像 發表于 04-03 10:17 ?1359次閱讀

    RK3568pinctrlgpio 子系統詳解

    如果 pinctrl 子系統將 PIN 復用為 GPIO,那么接下來就要配置 gpio 子系統,且 gp
    的頭像 發表于 12-20 10:22 ?2790次閱讀
    RK3568<b class='flag-5'>pinctrl</b> 和 <b class='flag-5'>gpio</b> <b class='flag-5'>子系統</b>詳解

    Linux中pinctrl操作GPIO只需要幾步

    pinctrl 子系統 API pinctrl 子系統的 API 有很多,對于驅動工程師來說,pinct
    的頭像 發表于 09-27 17:24 ?3673次閱讀

    瑞芯微RK3568-iomuxc和pinctrl子系統初窺

    pinctrl子系統作用:從設備樹中獲取PIN的描述信息來設置PIN的復用和電氣屬性,PIN可復用為I2C、SPI、GPIOgpio
    發表于 12-20 10:10 ?54次下載
    主站蜘蛛池模板: 福利社影院| 在线自拍亚洲视频欧美| 飘雪在线观看免费高清完整版韩国| 精品一区二区三区免费观看 | 天天影视香色欲综合网| 亲胸吻胸添奶头GIF动态图免费 | 国产av在在免费线观看美女| wankz tv videos国产| 97午夜理论片影院在线播放| 97免费视频在线| 2021精品乱码多人收藏| 3D漫画H精品啪啪无码| 97午夜精品| www.伊人| 国产99精品视频| 国产乱人伦AV麻豆网| 国产在线视频分类精品| 好爽好深太大了再快一点| 精品国产品在线18年| 久久精品中文騷妇女内射| 久久人妻熟女中文字幕AV蜜芽| 久久永久影院免费| 免费 高清 中文在线观看| 欧美三级aaa| 日韩精品人成在线播放| 视频成人永久免费下载| 亚洲成人国产| 在线观看99| CHINSEFUCKGAY无套| 丰满女友bd高清在线观看| 国产热久久精| 久久免费精品视频| 欧美另类摘花hd| 午夜插插插| 伊人国产视频| a在线观看视频| 国产三级在线免费| 久久看片网| 人人艹人人| 亚洲日韩国产成网站在线| 99国产精品偷窥熟女精品视频|