1. 程式人生 > >Linux GPIO驅動分析

Linux GPIO驅動分析

<p>
</p><pre name="code" class="html"><pre name="code" class="html">#include<linux/string.h>
#include<linux/list.h>
#include<linux/pci.h>
#include<asm/uaccess.h>
#include<asm/atomic.h>
#include<asm/unistd.h>
#include<mach/map.h>
#include<mach/regs-clock.h>
#include<mach/regs-gpio.h>
#include<plat/gpio-cfg.h>
#include<mach/gpio-bank-e.h>
#include<mach/gpio-bank-k.h>
#include"s3c6410_gpio.h"
#defineDEVICE_NAME"leds"
staticlongsbc2440_leds_ioctl(structfile*filp,unsignedintcmd,unsignedlongarg)
{
	switch(cmd){
		unsignedtmp;
	case0:
	case1:
		if(arg>4){
			return-EINVAL;
		}

		tmp=readl(S3C64XX_GPKDAT);
		tmp&=~(1<<(4+arg));//把暫存器的該位清零
		tmp|=((!cmd)<<(4+arg));//將暫存器的該位復位或者置位,取決於cmd
		writel(tmp,S3C64XX_GPKDAT);//將tmp寫入暫存器
		//printk(DEVICE_NAME":%d%d\n",arg,cmd);
		return0;
	default:
		return-EINVAL;
	}
}
//該結構體中成員函式是字元裝置驅動與核心的介面
staticstructfile_operationsdev_fops={
	.owner			=THIS_MODULE,
	.unlocked_ioctl	=sbc2440_leds_ioctl,
};
//misdevice:雜項裝置,即主裝置號為10的特殊字元裝置。
staticstructmiscdevicemisc={
//MISC_DYNAMIC_MINOR來動態獲取次裝置號。
	.minor=MISC_DYNAMIC_MINOR,
	.name=DEVICE_NAME,
	.fops=&dev_fops,
};

staticint__initdev_init(void)
{
	intret;

	{
		unsignedtmp;
		tmp=readl(S3C64XX_GPKCON);
//GPKCON配置GPK4到GPK7配置為0001輸出模式。
		tmp=(tmp&~(0xffffU<<16))|(0x1111U<<16);
		writel(tmp,S3C64XX_GPKCON);
		
//燈滅
		tmp=readl(S3C64XX_GPKDAT);
		tmp|=(0xF<<4);
		writel(tmp,S3C64XX_GPKDAT);
	}
//註冊裝置
//該函式會自動建立裝置節點,即裝置檔案。
	ret=misc_register(&misc);

	printk(DEVICE_NAME"\tinitialized\n");

	returnret;
}

staticvoid__exitdev_exit(void)
{
	misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARMInc.");



該程式中與硬體的關聯性檔案是s3c6410_gpio.h,包含的方式是#include"s3c6410_gpio.h"

"#include<stdlib.h>”用於標準庫檔案或系統提供的標頭檔案,到儲存系統標準標頭檔案的位置查詢標頭檔案。

"#include"userdefined.h"用於使用者自定義的標頭檔案,先從當前目錄查詢是否有指定名稱的標頭檔案,若當前目錄未找到該標頭檔案,再從標準檔案目錄中查詢。這兩種方式有他們的本質區別。

採用第二種包含方式,直接在當前工程目錄下找到了該檔案,內容如下:

/******************************************Copyright(c)************************************************  
    ** 檔名稱: s3c6410_gpio.h  
    ** 作    者: tandesir  
    ** 版    本: v1.0  
    ** 說    明: s3c6410 gpio操作  
    ** 修改記錄: 2011-9-27建立  
    ** 最後修改時間: 2011-10-5  
    ******************************************************************************************************/  
    #ifndef __S3C6410_GPIO_H__  
    #define __S3C6410_GPIO_H__  
      
    #include <linux/kernel.h>  
    #include <linux/init.h>  
    #include <linux/module.h>  
    #include <linux/interrupt.h>  
    #include <linux/ioport.h>  
    #include <linux/gpio.h>  
    #include <linux/io.h>  
      
    #include <mach/hardware.h>  
    #include <mach/map.h>   
    #include <mach/regs-gpio.h>  
    #include <mach/gpio-bank-n.h>  
    #include <mach/regs-clock.h>   
    #include <asm/irq.h>  
      
    #include <plat/gpio-core.h>  
    #include <plat/gpio-cfg.h>  
      
    void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)  
    {  
        //s3c_gpio_cfgpin(pin,function);  
            unsigned int tmp;   
            tmp = readl(S3C64XX_GPNCON);   
            tmp = (tmp & ~(3<<pin*2))|(function<<pin*2);   
            writel(tmp, S3C64XX_GPNCON);   
    }  
    
    void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)  
    {  
            //s3c_gpio_setpull(pin,to);  
            unsigned int tmp;   
            tmp = readl(S3C64XX_GPNPUD);   
            tmp = (tmp & ~(3<<pin*2))|(to<<pin*2);   
            writel(tmp, S3C64XX_GPNPUD);   
    }  
      
    unsigned int s3c6410_gpio_getpin(unsigned int pin)   
    {   
            unsigned int tmp;  
        tmp = readl(S3C64XX_GPNDAT);   
        tmp = tmp & (1 << (pin));    
      
        return tmp;   
    }  
      
    void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)  
    {  
            unsigned int tmp;   
        tmp = readl(S3C64XX_GPNDAT);   
        tmp &= ~(1 << (pin));   
        tmp |= ( (dat) << (pin) );   
        writel(tmp, S3C64XX_GPNDAT); ;  
    }  
      
#endif  

這與在微控制器程式設計中所見到的標頭檔案不相同,裡面的內容是一些函式的實現方法。

但是在C檔案中並沒有用到這些函式。C檔案與該標頭檔案都是直接對暫存器進行操作。

所以關鍵的地方便是暫存器與地址的對映在什麼地方?可疑的標頭檔案是:

#include<mach/map.h>

#include<mach/regs-clock.h>

#include<mach/regs-gpio.h>

#include<plat/gpio-cfg.h>

#include<mach/gpio-bank-e.h>

#include<mach/gpio-bank-k.h>

這幾個檔案到底在什麼地方?

這就是在寫驅動檔案之前為什麼要編譯核心的原因了!在編譯核心的時候,會配置核心的環境,比如用的主晶片的型號,在裡面便會指定編譯驅動時所需要用到的檔案的路徑,比如該晶片的型號是S3c6410,那麼便會在原始碼樹的/linux-2.6.38/arch/arm/

mach-s3c64xx尋找相應檔案。所以以上標頭檔案的位置在/linux-2.6.38/arch/arm/

mach-s3c64xx中。


Map.h中定義了各種暫存器的對映


在regs-gpio.h檔案中

定義了一些基地址

在gpio-bank-n.h檔案中定義了程式中用到的一些暫存器


在mach檔案中,看到了很多類似的檔案:


這應該就是晶片的多組IO口,當使用哪一組IO便呼叫哪一個檔案。


相關推薦

Linux GPIO驅動分析

<p> </p><pre name="code" class="html"><pre name="code" class="html">#include<linux/string.h> #include<li

Linux 8250驅動分析

com for 目前 lin .html www. http ibm mat 1. 介紹 8250是IBM PC及兼容機使用的一種串口芯片; 16550是一種帶先進先出(FIFO)功能的8250系列串口芯片; 16550A則是16550的升級版本, 修復了FIFO相關BUG

S3C2440 linux LCD驅動分析

環境: 硬體平臺 TQ2440            東華3.5 inch  TFT LCD       

Linux I2C驅動分析與實現--例子

通過上篇《Linux I2C驅動分析與實現(二)》,我們對Linux子系統已經不陌生,那麼如何實現I2C驅動呢? 編寫客戶驅動的方法 在核心中有兩種方式的i2c客戶驅動的編寫方法,一種叫legacy傳統方式,另一種是newstyle方式. 前 一種legacy是一種舊式的方法,在2.

LInux裝置驅動分析—— kmalloc和kzalloc函式

       今晚在研究EVM5728開發板上面Linux系統的IIC裝置驅動程式,偶然之間看到驅動程式中有一處使用了kzalloc函式,本人之前都是使用Linux核心提供的kmalloc / kfree函式來給裝置相關結構體分配 / 釋放記憶體的,第一次看到kzall

轉:linux GPIO驅動

Linux 下驅動GPIO 其實不用自己寫,最近專案要用到開發板上的GPIO,搜尋了一番,發現linux 下實現GPIO 驅動實在是太方便了,有現成的framework 可用,基本上要做的事情就是定義一下 Linux 下通過框架實現LED 大致過程如下 1、實現框架要求的幾個

Linux spi驅動分析(一)----匯流排驅動

一、SPI匯流排驅動介紹         SPI匯流排總共需要四根線,包括MOSI、MISO、CLK和CS。本文首先從SPI設備註冊開始來講述SPI匯流排驅動。 二、設備註冊         在系統啟動的時候,會按照順序執行一些初始化程式,比如device_initcall和module_i

Linux spi驅動分析(三)----spiddev分析

static longspidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){    int            err = 0;    int            retval = 0;    struct spid

Linux spi驅動分析(二)----SPI核心(bus、device_driver和device)

struct device {     struct device        *parent;     struct device_private    *p;     struct kobject kobj;     const char        *init_name; /* init

Linux uvc驅動分析

本文基於AM6C平臺Linux3.0.8核心。 一、ioctl呼叫流程 1.common/drivers/media/video/uvc/uvc_driver.c module_init(uvc_init); static int __init uvc_init(voi

Linux裝置驅動分析之熱拔插

                   /*輔助函式uevent_helper(/sbin/mdev,mdev是busybox的傑作)用於對熱拔插裝置進行建立及刪除 */if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {char *a

linux通用GPIO驅動

決定 輸入輸出 gpio 發現 文件導出 寫入 echo direction linux開發 Linux開發平臺實現了通用GPIO的驅動,用戶通過,SHell或者系統調用能控制GPIO的輸出和讀取其輸入值。其屬性文件均在/sys/class/gpio/目錄下,該目錄下有ex

19.Linux-USB總線驅動分析

kmalloc 開發 硬件 ctrl 地址 allow end 處理 interface 如下圖所示,以windows為例,我們插上一個沒有USB設備驅動的USB,就會提示你安裝驅動程序 為什麽一插上就有會提示信息? 是因為windows自帶了USB總線驅動程序

linux音頻alsa-uda134x驅動分析之二(時鐘)

lin pen play 個數 inter and 文本 ted word Audio Clocking音頻時鐘==============This text describes the audio clocking terms in ASoC and digital au

Linux核心啟動過程分析(十)-----RTC驅動分析

參考https://blog.csdn.net/xuao20060793/article/details/46433263這篇博文 RTC驅動分析: Class.c (drivers\rtc):subsys_initcall(rtc_init); static int __init

04-Linux裝置樹系列-GPIO驅動實踐

1. 前言 GPIO驅動開發可能算是Linux核心裝置驅動開發中最為簡單、最常見的一個方向,對於開發板的按鍵、LED、蜂鳴器、電源控制等模組,可能都是使用GPIO實現的。Linux核心的GPIO子系統在核心不斷的演進過程中進行了多次的重構,本文的第二

Linux SD/MMC/SDIO驅動分析

一、SD/MMC/SDIO概念區分 SD(SecureDigital)與 MMC(MultimediaCard) SD 是一種 flash memory card 的標準,也就是一般常見的 SD 記憶卡,而 MMC 則是較早的一種記憶卡標準,目前已經被 SD 標準所取代。

10. LCD驅動程式 ——框架分析 第017課 LCD原理詳解及裸機程式分析 15.linux-LCD層次分析(詳解)

引言: 由LCD的硬體原理及操作(可參看韋哥部落格:第017課 LCD原理詳解及裸機程式分析) 我們知道只要LCD控制器的相關暫存器正確配置好,就可以在LCD面板上顯示framebuffer中的內容。 若應用程式需要在LCD螢幕上顯示文字或影象時,只需要把相應的顯示內容以正確的格式寫到Framebuff

Linux--核心---I2C匯流排驅動分析 以linux3.10.0 RK3288為例

Linux 3.10.0 iic匯流排註冊過程 I2C匯流排驅動包括I2C介面卡驅動載入與解除安裝以及I2C匯流排通訊方法 I2C核心提供了i2c_adapter的增加和刪除函式、i2c_driver的增加和刪除函式、i2c_client的依附和脫離函式 以及i2c傳輸、傳送

Linux裝置驅動程式架構分析之一個I2C驅動例項

作者:劉昊昱  核心版本:3.10.1 編寫一個I2C裝置驅動程式的工作可分為兩部分,一是定義和註冊I2C裝置,即i2c_client;二是定義和註冊I2C裝置驅動,即i2c_driver。下面我們就以mini2440的I2C裝置at24c08 EEPROM為例,介紹如