由于昨天对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
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
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!nn');
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!nn');
53 return 1;
54 }
55
56 static int key_release(struct inode *inode, struct file *filp)
57 {
58 printk('<0>function write!nn');
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!nn');
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!nn',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!nn',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');
相关文章