25_ioremap控制GPIO寄存器

itop4412学习记录

本章目标:将GPL2(0)设置为输出,将GPC0(3)和GPX0(6)设置为输出,分别完成3个IO口的读或写实验。

 

1. 地址映射

1.1ioremap介绍

void *ioremap(unsigned long phys_addr, unsigned long size)

phys_addr:要映射的起始的IO地址

size:要映射的空间的大小,单位是字节

应用举例:

gpfcon = (volatile unsigned long *)ioremap(0x56000050,   16);

gpfdat = gpfcon + 1;

1. 从上面我们映射的起始地址为0x56000050也就是寄存器GPFCON的地址

2. 映射长度为16字节,也就是映射地址从:0x56000050~0x5600005C 地址全部映射完了

3. gpfdat = gpfcon + 1;的意思是 0x56000050 + 4 = 0x56000054 其地址是寄存器GPFDAT的地址

4. 为什么是加4呢,因为这个是指针加1,unsigned long的字节长度为4,指针加1,其地址就加4

25_ioremap控制GPIO寄存器_第1张图片

参考:006_linux驱动之_ioremap函数使用

1.2 使用ioremap

	GPL2_phy = 0x11000100;
	GPC0_phy = 0x11400060;
	GPX0_phy = 0x11000c00;
	
	GPL2_virt =(unsigned long)ioremap(GPL2_phy,16);
	GPC0_virt =(unsigned long)ioremap(GPC0_phy,16);
	GPX0_virt =(unsigned long)ioremap(GPX0_phy,16);
	
	//GPL2
	GPL2CON = (unsigned long *)(GPL2_virt);
	GPL2DAT = (unsigned long *)(GPL2_virt+0x04);
	GPL2PUD = (unsigned long *)(GPL2_virt+0x08);
	//GPC0
	GPC0CON = (unsigned long *)(GPC0_virt);
	GPC0DAT = (unsigned long *)(GPC0_virt+0x04);
	GPC0PUD = (unsigned long *)(GPC0_virt+0x08);

	//GPX0
	GPX0CON = (unsigned long *)(GPX0_virt);
	GPX0DAT = (unsigned long *)(GPX0_virt+0x04);
	GPX0PUD = (unsigned long *)(GPX0_virt+0x08);

 

2. GPIO寄存器

2.1 GPL2

(1)GPL2CON: 0x11000100

GPL2共8个IO口,GPL2CON寄存器共32bit,每4bit控制一个IO脚。

GPL2(0)对应的控制位为bit0~bit3,设置为输出时需要使bit0=1,bit1=bit2=bit3=0。

25_ioremap控制GPIO寄存器_第2张图片

(2)GPL2DAT:0x11000104

GPL2DAT共8bit,控制的bit0的值,即可完成GPL2(0)的输出状态:

bit0=1,GPL2(0)输出高电平

bit0=0,GPL2(0)输出低电平

25_ioremap控制GPIO寄存器_第3张图片

(3)GPL2PUD:0x11000108

GPL2PUD共16bit,每2bit控制一个IO的上下拉状态。GPL2(0)对应bit0~bit1,当bit0=bit1=1时,GPL2(0)设置为上拉。

注意,下图0x3 = Disables Pull-up需要改成Enable Pull-up

25_ioremap控制GPIO寄存器_第4张图片

 

2.2 GPC0

(1)GPC0CON:0x11400060

GPC0共5个IO口,GPC0CON寄存器共20bit,每4bit控制一个IO脚。

GPC0(3)对应的控制位为bit12~bit15,设置为输入时需要使bit12=bit13=bit14=bit15=0。

25_ioremap控制GPIO寄存器_第5张图片

(2)GPC0DAT:0x11400064

GPC0DAT的bit3对应IO口GPC0(3)的数据大小

25_ioremap控制GPIO寄存器_第6张图片

(3)GPC0PUD:0x11400068

GPC0PUD共10bit,每2bit控制一个IO的上下拉状态。

GPC0(3)默认为下拉(0x1),当bit6=bit7=0时,设置为非上下拉。

25_ioremap控制GPIO寄存器_第7张图片

2.3 GPX0

(1)GPX0CON:0x11000C00

GPX0共5个IO口,GPX0CON寄存器共32bit,每4bit控制一个IO脚。

GPX0(6)对应的控制位为bit24~bit27,设置为输入时需要使bit24=bit25=bit26=bit27=0。

25_ioremap控制GPIO寄存器_第8张图片

25_ioremap控制GPIO寄存器_第9张图片

(2)GPX0DAT:0x11000C04

GPX0DAT的bit6对应IO口GPX0(6)的数据大小

25_ioremap控制GPIO寄存器_第10张图片

(3)GPX0PUD:0x11000C08

GPX0PUD共10bit,每2bit控制一个IO的上下拉状态。

GPX0(6)默认为下拉(0x1),当bit12=bit13=0时,设置为非上下拉。

25_ioremap控制GPIO寄存器_第11张图片

 

3 GPIO配置

3.1 设置CON

	//设置输入输出
	//GPL2(0)设置为输出
	*GPL2CON &= ~(0xF<<(0*4)); //bit0~bit3清零
	*GPL2CON |= 0x1<<(0*4); //bit0~bit3写入0x1
	//GPC0(3)设置为输入
	*GPC0CON &= ~(0xF<<(3*4)); //bit12~bit15清零
	*GPC0CON |= 0x0<<(3*4); //bit12~bit15写入0x0
	//GPX0(6)设置为输入
	*GPX0CON &= ~(0xF<<(6*4)); //bit24~bit27清零
	*GPX0CON |= 0x0<<(6*4); //bit24~bit27写入0x0

3.2 设置上下拉

    //设置上下拉
	//GPL2(0)设置为上拉
	*GPL2PUD &= ~(0x3<<(0*2)); //bit0~bit1清零
	*GPL2PUD |= 0x3<<(0*2); //bit0~bit1写入0x3
	//GPC0(3)设置为非上下拉
	*GPC0PUD &= ~(0x3<<(3*2)); //bit6~bit7清零
	*GPC0PUD |= 0x0<<(3*2); //bit6~bit7写入0x0
	//GPX0(6)设置为非上下拉
	*GPX0PUD &= ~(0x3<<(6*2)); //bit12~bit13清零
	*GPX0PUD |= 0x0<<(6*2); //bit12~bit13写入0x0

3.3 DAT的读或写

	if(cmd == 0){
		if(arg==0){
			*GPL2DAT &= 0xfe;
			}
		if(arg==1){
			*GPL2DAT |= 0x01;
			}
	}
	
	if(cmd ==1){
		return((*GPC0DAT&0x0008) ?1:0);		
	}
	
	if(cmd ==2){
		return((*GPX0DAT&0x0008) ?1:0);		

4. 驱动调试

(1)加载模块

[root@iTOP-4412]# insmod ioremap_gpio.ko
[ 6857.553529]  start gpio init!
[ 6857.571112] device state is 0 
[ 6857.573046]  gpio initialized
[ 6857.608349]  gpio init OK,DriverState is 0!

(2)IO读与写

GPL2(0)作为输出脚测试:

[root@iTOP-4412]# ./user_ioremap_gpio 0 0
[ 7050.720774] gpio open
[ 7050.721666] cmd is 0,arg is 0
[ 7050.724991] gpio release
LED is OFF!
[root@iTOP-4412]# ./user_ioremap_gpio 0 1
[ 7056.399529] gpio open
[ 7056.400387] cmd is 0,arg is 1
[ 7056.403354] gpio release
LED is ON!

GPC0(3)和GPX0(6)作为输入脚测试:

开关3接1.8V:

[root@iTOP-4412]# ./user_ioremap_gpio 1 0
[ 7149.445054] gpio open
[ 7149.445855] cmd is 1,arg is 0
[ 7149.448904] gpio release
cmd is 1,gpio_read is 1

开关3接地:

[root@iTOP-4412]# ./user_ioremap_gpio 1 0
[ 7165.611665] gpio open
[ 7165.612474] cmd is 1,arg is 0
[ 7165.615540] gpio release
cmd is 1,gpio_read is 0

开关4接1.8V:

[root@iTOP-4412]# ./user_ioremap_gpio 2 0
[ 7233.297656] gpio open
[ 7233.298574] gpio release
cmd is 2,gpio_read is -1

开关4接地:

[root@iTOP-4412]# ./user_ioremap_gpio 2 0
[ 7250.365280] gpio open
[ 7250.366801] gpio release
cmd is 2,gpio_read is -1

分析:GPL2(0)和GPC0(3)的配置都是OK的,GPX0(6)的配置应该存在问题,以后再排查!

(3)卸载模块

[root@iTOP-4412]# rmmod ioremap_gpio
[ 7451.920221] gpio module exit!
[ 7451.921932]  gpio removed!
[ 7452.011765]  gpio read release!!

5. 驱动代码

(1)ioremap_gpio.c

#include 
#include 

/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include 
/*注册杂项设备头文件*/
#include 
/*注册设备节点的文件结构体*/
#include 

#include 

#define DRIVER_NAME "gpio_read"
#define DEVICE_NAME "gpio_read_dev"

volatile unsigned long *GPL2CON,*GPL2DAT,*GPL2PUD,*GPC0CON ,*GPC0DAT ,*GPC0PUD ,*GPX0CON ,*GPX0DAT ,*GPX0PUD;
volatile unsigned long GPL2_phy,GPL2_virt,GPC0_phy,GPC0_virt,GPX0_phy,GPX0_virt;

static long gpio_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
	
	printk("cmd is %d,arg is %d\n",cmd,arg);
	if(cmd > 1){
		printk(KERN_EMERG "cmd is 0 , 1 or 2!\n");
	}
	if(arg > 1){
		printk(KERN_EMERG "arg is 0 or 1!\n");
	}
	//cmd=0,GPL2(0)输出,arg=0,输出低电平,arg=1输出高电平
	//cmd=1,GPC0(3)输入
	//cmd=2,GPX0(6)输入
	
	if(cmd == 0){
		if(arg==0){
			*GPL2DAT &= 0xfe;
			}
		if(arg==1){
			*GPL2DAT |= 0x01;
			}
	}
	
	if(cmd ==1){
		return((*GPC0DAT&0x08) ?1:0);		
	}
	
	if(cmd ==2){
		return((*GPX0DAT&0x40) ?1:0);			
	}
	return 0;

}

static int gpio_release(struct inode *inode, struct file *file){
	printk(KERN_EMERG "gpio release\n");
	return 0;
}

static int gpio_open(struct inode *inode, struct file *file){
	printk(KERN_EMERG "gpio open\n");
	return 0;
}

static struct file_operations gpio_ops = {
	.owner = THIS_MODULE,
	.open = gpio_open,
	.release = gpio_release,
	.unlocked_ioctl = gpio_ioctl,
};

static  struct miscdevice gpio_dev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVICE_NAME,
	.fops = &gpio_ops,
};

static int gpio_probe(struct platform_device *pdv){
		
	printk(KERN_EMERG "\tgpio initialized\n");
	GPL2_phy = 0x11000100;
	GPC0_phy = 0x11400060;
	GPX0_phy = 0x11000c00;
	
	GPL2_virt =(unsigned long)ioremap(GPL2_phy,16);
	GPC0_virt =(unsigned long)ioremap(GPC0_phy,16);
	GPX0_virt =(unsigned long)ioremap(GPX0_phy,16);
	
	//GPL2
	GPL2CON = (unsigned long *)(GPL2_virt);
	GPL2DAT = (unsigned long *)(GPL2_virt+0x04);
	GPL2PUD = (unsigned long *)(GPL2_virt+0x08);
	//GPC0
	GPC0CON = (unsigned long *)(GPC0_virt);
	GPC0DAT = (unsigned long *)(GPC0_virt+0x04);
	GPC0PUD = (unsigned long *)(GPC0_virt+0x08);

	//GPX0
	GPX0CON = (unsigned long *)(GPX0_virt);
	GPX0DAT = (unsigned long *)(GPX0_virt+0x04);
	GPX0PUD = (unsigned long *)(GPX0_virt+0x08);

    //设置上下拉
	//GPL2(0)设置为上拉
	*GPL2PUD &= ~(0x3<<(0*2)); //bit0~bit1清零
	*GPL2PUD |= 0x3<<(0*2); //bit0~bit1写入0x3
	//GPC0(3)设置为非上下拉
	*GPC0PUD &= ~(0x3<<(3*2)); //bit6~bit7清零
	*GPC0PUD |= 0x0<<(3*2); //bit6~bit7写入0x0
	//GPX0(6)设置为非上下拉
	*GPX0PUD &= ~(0x3<<(6*2)); //bit12~bit13清零
	*GPX0PUD |= 0x0<<(6*2); //bit12~bit13写入0x0
	
	//设置输入输出
	//GPL2(0)设置为输出
	*GPL2CON &= ~(0xF<<(0*4)); //bit0~bit3清零
	*GPL2CON |= 0x1<<(0*4); //bit0~bit3写入0x1
	//GPC0(3)设置为输入
	*GPC0CON &= ~(0xF<<(3*4)); //bit12~bit15清零
	*GPC0CON |= 0x0<<(3*4); //bit12~bit15写入0x0
	//GPX0(6)设置为输入
	*GPX0CON &= ~(0xF<<(6*4)); //bit24~bit27清零
	*GPX0CON |= 0x0<<(6*4); //bit24~bit27写入0x0
    
	//设置GPL2(0)输出低电平
	*GPL2DAT &= 0x00;
	
	misc_register(&gpio_dev);	
	return 0;
}

static int gpio_remove(struct platform_device *pdv){
	printk(KERN_EMERG "\tgpio removed!\n");
	misc_deregister(&gpio_dev);
	return 0;
}

static void gpio_shutdown(struct platform_device *pdv){
	;
}

static int gpio_suspend(struct platform_device *pdv,pm_message_t pmt){
	return 0;
}

static int gpio_resume(struct platform_device *pdv){
	return 0;
}
static int gpio_read_dev_release(struct platform_device *dev)
{
	printk("\tgpio read release!!\n");
	return 0;
}

static struct platform_device s3c_device_gpio_read_dev = {
        .name   = DRIVER_NAME,
        .id             = -1,
		.dev = {
			.release = gpio_read_dev_release,
	}

};


struct platform_driver gpio_driver = {
	.probe = gpio_probe,
	.remove = gpio_remove,
	.shutdown = gpio_shutdown,
	.suspend = gpio_suspend,
	.resume = gpio_resume,
	.driver = {
		.name = DRIVER_NAME,
		.owner = THIS_MODULE,
	}
};

static int gpio_init(void)
{
	int DriverState=0,Devicestate=0;	
	printk(KERN_EMERG "\tstart gpio init!\n");
	
	Devicestate = platform_device_register(&s3c_device_gpio_read_dev);
	printk(KERN_EMERG "device state is %d \n",Devicestate);
	
	DriverState = platform_driver_register(&gpio_driver);
	if(DriverState==0)
	{
		printk(KERN_EMERG "\tgpio init OK,DriverState is %d!\n",DriverState);
	}	
	
	return 0;
}

static void gpio_exit(void)
{
	printk(KERN_EMERG "gpio module exit!\n");
	platform_device_unregister(&s3c_device_gpio_read_dev);	
	platform_driver_unregister(&gpio_driver);	

}
module_init(gpio_init);
module_exit(gpio_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");

(2)user_ioremap_gpio.c

#include 

#include 
#include 
#include 
#include 
#include 

int main(int agc,char **argv){
	int fd,cmd,output;
	char *dev_node = "/dev/gpio_read_dev";
	
	if(strcmp(argv[1],"0")==0) cmd=0;
	else if(strcmp(argv[1],"1")==0) cmd=1;
	else if(strcmp(argv[1],"2")==0) cmd=2;
	else printf("cmd must be 0 ,1 or 2!\n");
				
	if(strcmp(argv[2],"0")==0) output=0;
	else if(strcmp(argv[2],"1")==0) output=1;
	else printf("output must be 0 or 1!\n");
    
	//printf("cmd is %d,output is %d\n",cmd,output);
	
/*O_RDWR只读打开,O_NDELAY非阻塞方式*/	
if((cmd ==0)|(cmd ==1)|(cmd==2)){
	if((fd = open(dev_node,O_RDWR|O_NDELAY))<0){
		printf("APP open %s failed\n",dev_node);
	}
	else{
		if((cmd ==1)|(cmd ==2)){
			printf("cmd is %d,gpio_read is %d\n",cmd,ioctl(fd,cmd,0));
			}
			else{
				ioctl(fd,cmd,output);
				if(output==1){					
					printf("LED is ON!\n");
				}
				else{
					printf("LED is OFF!\n");
				}
			
			}
		
	}
	close(fd);
}
	
}

(3)Makefile

#!/bin/bash
obj-m += ioremap_gpio.o
KDIR := /home/topeet/iTop4412_Kernel_3.0
PWD ?= $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	rm -rf *.o

 

你可能感兴趣的:(itop4412学习记录)