itop4412学习记录
本章目标:将GPL2(0)设置为输出,将GPC0(3)和GPX0(6)设置为输出,分别完成3个IO口的读或写实验。
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
参考:006_linux驱动之_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);
GPL2共8个IO口,GPL2CON寄存器共32bit,每4bit控制一个IO脚。
GPL2(0)对应的控制位为bit0~bit3,设置为输出时需要使bit0=1,bit1=bit2=bit3=0。
GPL2DAT共8bit,控制的bit0的值,即可完成GPL2(0)的输出状态:
bit0=1,GPL2(0)输出高电平
bit0=0,GPL2(0)输出低电平
GPL2PUD共16bit,每2bit控制一个IO的上下拉状态。GPL2(0)对应bit0~bit1,当bit0=bit1=1时,GPL2(0)设置为上拉。
注意,下图0x3 = Disables Pull-up需要改成Enable Pull-up。
GPC0共5个IO口,GPC0CON寄存器共20bit,每4bit控制一个IO脚。
GPC0(3)对应的控制位为bit12~bit15,设置为输入时需要使bit12=bit13=bit14=bit15=0。
GPC0DAT的bit3对应IO口GPC0(3)的数据大小
GPC0PUD共10bit,每2bit控制一个IO的上下拉状态。
GPC0(3)默认为下拉(0x1),当bit6=bit7=0时,设置为非上下拉。
GPX0共5个IO口,GPX0CON寄存器共32bit,每4bit控制一个IO脚。
GPX0(6)对应的控制位为bit24~bit27,设置为输入时需要使bit24=bit25=bit26=bit27=0。
GPX0DAT的bit6对应IO口GPX0(6)的数据大小
GPX0PUD共10bit,每2bit控制一个IO的上下拉状态。
GPX0(6)默认为下拉(0x1),当bit12=bit13=0时,设置为非上下拉。
//设置输入输出
//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)设置为上拉
*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
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);
[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!
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)的配置应该存在问题,以后再排查!
[root@iTOP-4412]# rmmod ioremap_gpio
[ 7451.920221] gpio module exit!
[ 7451.921932] gpio removed!
[ 7452.011765] gpio read release!!
#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");
#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);
}
}
#!/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