RK3288開發板PopMetal上的GPIO驅動實例

樓主在這邊給你們介紹下如何使用PopMetal的GPIO。先講過程,再講原理吧,php

該驅動須要涉及到的知識點:1,DTS設備樹的做用,2,platform虛擬總線驅動的編寫。html

第一步,添加DTS節點node

在/kernel/arch/arm/boot/dts/rockchip.dts下添加以下內容。linux

下圖rockchip-leds-gpio這部分的內容,修改保存,ios

  

第二步,在kernel/drivers下建立個LED文件夾,而後加入以下幾個文件驅動文件leds.c,Makefile和Kconfig.以下圖函數

源碼:spa

/***********************************************************************************orm

* driver for led0htm

blog

**********************************************************************************/

#include <linux/miscdevice.h>

#include <linux/input.h>

#include <linux/clk.h>

#include <linux/delay.h>

#include <asm/io.h>

#include <asm/uaccess.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/of_gpio.h>

#include <linux/gpio.h>

#include <linux/of_platform.h>

static int leds_probe(struct platform_device *pdev)

{  int ret =-1

int i 

int led

enum of_gpio_flags flag

struct device_node *led_node = pdev->dev.of_node

led = of_get_named_gpio_flags(led_node,"led-gpios",0,&flag)

printk("get gpio id successful\n")

if(!gpio_is_valid(led)){ 

  printk("invalid led-gpios: %d\n",led) 

  return -1 

}

if(gpio_request(led,"led_gpio")){

printk("led gpio request failed!\n")

return ret 

  gpio_direction_output(led,1)

for(i=0 i < 10 i++)

{

  gpio_set_value(led,1)

  mdelay(500)

  gpio_set_value(led,0)

  mdelay(500)

  printk("it's %d\n",i)

}

return 0


}

static int leds_remove(struct platform_device *pdev)

{

        return 0

}


static struct of_device_id leds_of_match[] = {

        { .compatible = "rockchip-leds-gpio" },

        { }

}

MODULE_DEVICE_TABLE(of, leds_of_match)

static struct platform_driver leds_driver = {

        .driver         = {

                .name           = "leds-drivers",

                .owner          = THIS_MODULE,

                .of_match_table = of_match_ptr(leds_of_match),

        },

        .probe          = leds_probe,

        .remove         = leds_remove,

};


/*static int __init leds_init(void)

{

    printk(KERN_INFO "Enter %s\n", __FUNCTION__)

    return platform_driver_register(&leds_driver)

    return 0

}


static void __exit leds_exit(void)

{

platform_driver_unregister(&leds_driver)

    printk("close leds\n")

}*/module_platform_driver(leds_driver)

module_platform_driver(leds_driver)


MODULE_DESCRIPTION("leds Driver")

MODULE_LICENSE("GPL")

MODULE_ALIAS("platform:leds-drivers")

/***********************************************************************************

* driver for led0

**********************************************************************************/

Kconfig:

  

Makefile:

  

第三步,修改drivers下的Kconfig和Makefile,修改內容以下

在Kconfig末尾添加:source 「drivers/led/Kconfig」

在Makefile末尾添加: obj-$(CONFIG_LED0_TEST)  +=led/

第四步,編譯新的kernel與resource並燒寫進板子裏,

而後DTS中定義的引腳就會按照驅動的內容,進行高低電平的變化。

須要源碼可下載:  led.zip

好了,如今咱們來介紹下原理,首先是DTS,和另外一塊開發板PX2不同,PopMetal並無寫相應的mach-*****文件,而是經過設備樹的方式獲取引腳的編號,設備樹的引入可減小了內核爲支持新硬件而須要的改變,提升代碼重用,加速了Linux支持包的開發,使得單個內核鏡像能支持多個系統。簡單來講,它就是給內核的一個參數,這些參數會啓動相應的驅動,這樣參數不同,內核源碼支持的系統就不同。

而在這裏咱們要清楚的是咱們要用相應的引腳就必須建立相應的節點,而且賦上一些參數。

而驅動又是怎麼識別到這些參數的呢?這裏咱們先講講platform虛擬總線驅動,這個總線跟IIC,SPI等總線不同,是由內核虛擬出來的,咱們就以上面的代碼爲例,給你們講講他是怎麼工做的,

首先這個驅動的核心是:

static struct platform_driver leds_driver = {

        .driver         = {

                .name           = "leds-drivers",//驅動名

                .owner          = THIS_MODULE,

                .of_match_table = of_match_ptr(leds_of_match),//匹配設備樹

        },

        .probe          = leds_probe,//探測函數,檢測硬件上是否存在設備,檢測到便執行

        .remove         = leds_remove,//移除函數,硬件移除時,執行

};

在這裏咱們只給部份內容賦予了值,自己這個結構體還有別的子項,須要瞭解的同窗能夠在這編博客看看:http://blog.sina.com.cn/s/blog_53c733350100zdav.html

在這個結構體中,咱們就是經過.of_match_table = of_match_ptr(leds_of_match),來匹配設備樹上的參數,而即系統會根據設備樹種定義的compatible參數比較驅動中的leds_of_match中定義的 .compatible 參數,

來爲參數找到相應的驅動,而定義的probe和remove函數則是對探測到設備作出反應,及移除設備時作出反應,而module_platform_driver(leds_driver)是將驅動掛到總線上去,

如今咱們看看probe是怎麼獲取到GPIO的值的,其中它的主要函數以下:

struct device_node *led_node = pdev->dev.of_node

led = of_get_named_gpio_flags(led_node,"led-gpios",0,&flag)

功能就是將led_node節點上的led-gpios的值取下,而咱們以前在rockchip.dts中隊led-gpios的定義以下:

led-gpios=&GPIO6 GPIO_A6 GPIO_ACTIVE_LOW,意思就是選擇引腳gpio6_a6,且該引腳低電平有效。

上面這句賦值便已經將引腳的編號賦給了led-gpios,故接下來咱們就能夠用GPIO_requset_one GPIO_set_value,等函數去操做這個GPIO了,像gpio_set_value(led-gpios,1)將該引腳設置爲高電平。

固然這些操做只是相對於引腳沒複用的GPIO口,引腳若是有複用功能,咱們還得進行一些別的操做把引腳的功能選好。

相關文章
相關標籤/搜索