Lover雪儿
想念时,就看看天空,无论距离有多远,我们总在同一片天空下!

20150223 IMX257 LED驱动程序实现

2015-02-23 李海沿

 

由于昨天对IMX257的地址分配不了解,所以前面只能用s3c24xx的驱动程序来了解ioremap等对IO端口的工作原理。

但是经过昨晚对IMX257芯片的细细梳理,今天早上起来又把IMX257的芯片资料看了一遍,终于成功看懂了,下面意义给大家道来。

我们此处使用ERR_LED 也就是GPIO3_23引脚

 

一、IMX257 芯片资料分析

1.确定相关寄存器基址

 

确定IOMUX地址

 

GPIO3的地址

 

2.确定相关寄存器的偏移地址

IOMUX的相关的模式配置寄存器,配置为ALT5模式

偏移地址:

寄存器描述:

 

接下来就是配置GPIO的相关信息,上拉,CMOS输入输出,等信息

偏移地址:

寄存器描述:

 

这个是有关ERR_LED的引脚的一些信息

 

GPIO寄存器的偏移地址

因为每个GPIO上最大只有32位,刚刚好上面的DR寄存器每一位就是表示单独一个引脚的电平

 

二、IMX257 代码分析

1.定义一些寄存器

//寄存器基址;

static unsigned long mem_iomux;

static unsigned long mem_gpio3;

static unsigned long base_iomux;     //iomux基址 0X 43FA C000 - 0X 43FA FFFF

static unsigned long base_gpio3;    //gpio3     0X 53FA 4000 - 0X 53FA 7FFF

// MUX_CTL模式选择 配置寄存器

#define MUX_CTL (*(volatile unsigned long *)(base_iomux + 0x0060))

// PAD_CTL GPIO常用功能设置

#define PAD_CTL (*(volatile unsigned long *)(base_iomux + 0x0270))

// GPIO DR 数据寄存器 DR

#define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000))

// GPIO GDIR 方向控制寄存器 GDIR

#define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004))

如图所示:

 

2.在init函数中初始化寄存器,及做相应的配置

 

IO端口申请:

配置引脚为ALT5 GPIO模式

 

配置引脚的电平,1.8v, CMOS输出,都是配置为0

 

配置为端口引脚为输出模式,并且初始化电平

 

打印各个寄存器的地址信息

 

将LED灯1秒间隔闪烁

 

 

3.在exit函数中释放IO端口

 

 

4.编译测试

 

硬件:

如图所示ERR_LED灯点亮

 

ERR_LED等熄灭

 

 

 

好了,大功告成:

附上驱动程序代码:

 

  1 #include<linux/cdev.h>
  2 #include<linux/module.h>
  3 #include<linux/types.h>
  4 #include<linux/fs.h>
  5 #include<linux/errno.h>
  6 #include<linux/mm.h>
  7 #include<linux/sched.h>
  8 #include<linux/init.h>
  9 #include<asm/io.h>
 10 #include<asm/system.h>
 11 #include<asm/uaccess.h>
 12 #include<linux/device.h>
 13 #include <linux/delay.h>
 14 
 15 #define Driver_NAME "err_led_dev"
 16 #define DEVICE_NAME "err_led_dev"
 17 
 18 static int major = 0;
 19 
 20 //auto to create device node
 21 static struct class *drv_class = NULL;
 22 static struct class_device *drv_class_dev = NULL;
 23 
 24 //寄存器基址;
 25 static unsigned long mem_iomux;
 26 static unsigned long mem_gpio3;
 27 static unsigned long base_iomux;      //iomux基址 0X 43FA C000 -  0X 43FA FFFF
 28 static unsigned long base_gpio3;    //gpio3      0X 53FA 4000 -  0X 53FA 7FFF
 29 // MUX_CTL模式选择  配置寄存器
 30 #define MUX_CTL  (*(volatile unsigned long *)(base_iomux + 0x0060))
 31 // PAD_CTL GPIO常用功能设置
 32 #define PAD_CTL  (*(volatile unsigned long *)(base_iomux + 0x0270))
 33 // GPIO DR   数据寄存器  DR
 34 #define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000))
 35 // GPIO GDIR 方向控制寄存器  GDIR
 36 #define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004))
 37 
 38 
 39 static int key_open(struct inode *inode, struct file *file)
 40 {
 41     printk("<0>function open!\n\n");
 42     return 0;
 43 }
 44 
 45 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
 46 {
 47     return 0;
 48 }
 49 
 50 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
 51 {
 52     printk("<0>function write!\n\n");
 53     return 1;
 54 }
 55 
 56 static int  key_release(struct inode *inode, struct file *filp)
 57 {
 58     printk("<0>function write!\n\n");
 59     return 0;
 60 }
 61 
 62 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
 63 {
 64     printk("<0>function ioctl!\n\n");
 65     return 0;
 66 }
 67 static struct file_operations key_fops = {
 68     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
 69     .open   =   key_open,
 70     .read   =   key_read,
 71     .write  =   key_write,
 72     .release=   key_release,
 73     .ioctl  =   key_ioctl,
 74 };
 75 
 76 void gpio_addr(void){
 77     printk("<0>addr base_iomux : %x \n",base_iomux);
 78     printk("<0>addr base_gpio3 : %x \n",base_gpio3);
 79     printk("<0>addr MUX_CTL : %x \n",&MUX_CTL);
 80     printk("<0>addr PAD_CTL : %x \n",&PAD_CTL);
 81     printk("<0>addr GDIR_GPIO3 : %x \n",&GDIR_GPIO3);
 82     printk("<0>addr DR_GPIO3 : %x \n",&DR_GPIO3);
 83 }
 84 
 85 void led_on_off(void){
 86     ssleep(1);
 87     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1
 88     ssleep(1);
 89     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零
 90     ssleep(1);
 91     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1
 92     ssleep(1);
 93     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零
 94     ssleep(1);
 95     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1
 96     ssleep(1);
 97     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零
 98     ssleep(1);
 99     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1
100     ssleep(1);
101     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零
102     ssleep(1);
103     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1
104 }
105 
106 static int __init  key_irq_init(void)
107 {
108     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
109     //register and mknod
110     major = register_chrdev(0,Driver_NAME,&key_fops);
111     drv_class = class_create(THIS_MODULE,Driver_NAME);
112     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);  /*/dev/key_query*/
113     
114     //IO端口申请 ioremap  可以直接通过指针来访问这些地址
115     base_iomux = ioremap(0x43FAC000,0xFFF);
116     base_gpio3 = ioremap(0x53FA4000,0xFFF);
117 
118     //MUX_CTL
119     MUX_CTL &= ~(0x07 << 0);    
120     MUX_CTL |= (0X05 << 0);    //设置为ALT5  GPIO3_23 ERR_LED
121     //PAD_CTL
122     PAD_CTL &= ~(0x01<<13 | 0x01<<3 | 0x03<<1 | 0x01<<0);   //1.8v 不需要上拉下拉  CMOS输出 slew rate
123     //GDIR_GPIO3    配置为输出模式
124     GDIR_GPIO3 &= ~(0x01 << 23);    
125     GDIR_GPIO3 |= (0x01 << 23);    //配置为输出模式    
126 
127     //DR_GPIO3        配置为输出0 点亮ERR_LED
128     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零
129     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零
130     gpio_addr();
131     led_on_off();
132     return 0; 
133 }
134                      
135 static void __exit key_irq_exit(void)
136 {
137     gpio_addr();
138     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
139     led_on_off();
140 
141        unregister_chrdev(major,Driver_NAME);
142     device_unregister(drv_class_dev);
143     class_destroy(drv_class);
144     
145     //释放IO端口
146     iounmap(base_iomux);
147     iounmap(base_gpio3);
148 }
149 
150 
151 /* 这两行指定驱动程序的初始化函数和卸载函数 */
152 module_init(key_irq_init);
153 module_exit(key_irq_exit);
154 
155 /* 描述驱动程序的一些信息,不是必须的 */
156 MODULE_AUTHOR("Lover雪儿");
157 MODULE_VERSION("0.1.0");
158 MODULE_DESCRIPTION("IMX257 key Driver");
159 MODULE_LICENSE("GPL");
View Code

 

posted on 2015-02-23 11:04  Lover雪儿  阅读(645)  评论(0编辑  收藏  举报