Linux GPIO驱动分析

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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”用于标准库文件或系统提供的头文件,到保存系统标准头文件的位置查找头文件。

"#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   
    #include   
    #include   
    #include   
    #include   
    #include   
    #include   
      
    #include   
    #include    
    #include   
    #include   
    #include    
    #include   
      
    #include   
    #include   
      
    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<

这与在单片机编程中所见到的头文件不相同,里面的内容是一些函数的实现方法。

但是在C文件中并没有用到这些函数。C文件与该头文件都是直接对寄存器进行操作。

所以关键的地方便是寄存器与地址的映射在什么地方?可疑的头文件是:

#include

#include

#include

#include

#include

#include

这几个文件到底在什么地方?

这就是在写驱动文件之前为什么要编译内核的原因了!在编译内核的时候,会配置内核的环境,比如用的主芯片的型号,在里面便会指定编译驱动时所需要用到的文件的路径,比如该芯片的型号是S3c6410,那么便会在源码树的/linux-2.6.38/arch/arm/

mach-s3c64xx寻找相应文件。所以以上头文件的位置在/linux-2.6.38/arch/arm/

mach-s3c64xx中。


Map.h中定义了各种寄存器的映射

Linux GPIO驱动分析_第1张图片

在regs-gpio.h文件中

定义了一些基地址

在gpio-bank-n.h文件中定义了程序中用到的一些寄存器

Linux GPIO驱动分析_第2张图片

在mach文件中,看到了很多类似的文件:

Linux GPIO驱动分析_第3张图片

这应该就是芯片的多组IO口,当使用哪一组IO便调用哪一个文件。


你可能感兴趣的:(Linux)