赞
踩
我们基于寄存器的方式已经编写了LED驱动,实现点亮/熄灭LED,但是你有没有发现一个问题,就是假设LED修改了一个GPIO,那么需要对应的修改寄存器代码,非常繁琐,而且随着改板次数增加,那么会带来一个灾难性的重复性没有技术含量的重复工作的弊端。
在之前的文档我们已经介绍了LED寄存器实现方式:https://blog.csdn.net/XiaoXiaoPengBo/article/details/128684419?spm=1001.2014.3001.5501
并且我们之前文档也写过了设备树相关的概念内容:
https://blog.csdn.net/XiaoXiaoPengBo/article/details/128734828?spm=1001.2014.3001.5501
那么本节,我们就结合之前的内容把他利用起来!!!我们还是用之前的LED GPIO1_3
在根节点下增加一下内容
- wireless_link_led{
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "wl_led";
- status = "ok";
- reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
- 0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
- 0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
- 0X0209C000 0X04 /* GPIO1_DR_BASE */
- 0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
- };
make dtbs
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/gpio.h>
- #include <linux/of_address.h>
- #include <linux/of.h>
- #include <asm/mach/map.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
-
-
- #define LED_MAJOR 200
- #define LED_NAME "led"
-
- static struct class *led_class;
- struct device_node *led_nd;
-
-
-
- static void __iomem *IMX6U_CCM_CCGR1;
- static void __iomem *SW_MUX_GPIO1_IO03;
- static void __iomem *SW_PAD_GPIO1_IO03;
- static void __iomem *GPIO1_DR;
- static void __iomem *GPIO1_GDIR;
-
-
- static int led_open(struct inode *inode, struct file *filp)
- {
- printk("led_open\r\n");
- return 0;
- }
-
-
- static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
- {
- printk("led_read\r\n");
- return 0;
- }
-
- static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
- {
- printk("led_write\r\n");
- int retvalue;
- u32 val = 0;
- unsigned char databuf[1];
- unsigned char ledstat;
-
- retvalue = copy_from_user(databuf, buf, cnt);
- if(retvalue < 0) {
- printk("kernel write failed!\r\n");
- return -EFAULT;
- }
-
- ledstat = databuf[0];
-
- printk("ledstat:%d\r\n",ledstat);
-
- if(ledstat == 1)
- {
- val = readl(GPIO1_DR);
- val &= ~(1 << 3);
- writel(val, GPIO1_DR);
- }
- else if(ledstat == 0)
- {
- val = readl(GPIO1_DR);
- val|= (1 << 3);
- writel(val, GPIO1_DR);
- }
-
- return 1;
- }
-
-
- static int led_release(struct inode *inode, struct file *filp)
- {
- printk("led_release\r\n");
- return 0;
- }
-
-
-
- static struct file_operations led_fops = {
- .owner = THIS_MODULE,
- .open = led_open,
- .read = led_read,
- .write = led_write,
- .release = led_release,
- };
-
-
- static int __init led_driver_init(void)
- {
- u8 index;
- u32 val = 0;
- int ret = 0;
- const char *str;
- u32 regdata[14];
- struct property *proper;
- printk("led_driver_init\r\n");
-
- led_nd = of_find_node_by_path("/wireless_link_led");
- if(led_nd)
- printk("led nd found\r\n");
- else
- {
- printk("led nd is not found\r\n");
- return -1;
- }
-
- proper = of_find_property(led_nd, "compatible", NULL);
- if(proper)
- printk("compatible = %s\r\n", (char*)proper->value);
- else
- printk("compatible property find failed\r\n");
-
- ret = of_property_read_string(led_nd, "status", &str);
- printk("of_property_read_string ret:%d\r\n",ret);
- if(ret >= 0)
- printk("status = %s\r\n",str);
-
- ret = of_property_read_u32_array(led_nd, "reg", regdata, 10);
- printk("of_property_read_string ret:%d\r\n",ret);
-
- printk("---------------------------\r\n");
- for(index = 0; index < 10; index++)
- printk("%#X ", regdata[index]);
- printk("\r\n---------------------------\r\n");
-
- IMX6U_CCM_CCGR1 = of_iomap(led_nd, 0);
- SW_MUX_GPIO1_IO03 = of_iomap(led_nd, 1);
- SW_PAD_GPIO1_IO03 = of_iomap(led_nd, 2);
- GPIO1_DR = of_iomap(led_nd, 3);
- GPIO1_GDIR = of_iomap(led_nd, 4);
-
- val = readl(IMX6U_CCM_CCGR1);
- val &= ~(3 << 26);
- val |= (3 << 26);
- writel(val, IMX6U_CCM_CCGR1);
-
- writel(5, SW_MUX_GPIO1_IO03);
-
- writel(0x10B0, SW_PAD_GPIO1_IO03);
-
- val = readl(GPIO1_GDIR);
- val &= ~(1 << 3);
- val |= (1 << 3);
- writel(val, GPIO1_GDIR);
-
- val = readl(GPIO1_DR);
- val |= (1 << 3);
- writel(val, GPIO1_DR);
-
- ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
- if(ret < 0){
- printk("register chrdev failed!\r\n");
- return -EIO;
- }
-
- led_class = class_create(THIS_MODULE,"led_class");
-
- device_create(led_class,NULL,MKDEV(LED_MAJOR,0),NULL,"led"); /* /dev/led */
-
- return 0;
- }
-
- static void __exit led_driver_exit(void)
- {
- printk("led_driver_exit\r\n");
-
- iounmap(IMX6U_CCM_CCGR1);
- iounmap(SW_MUX_GPIO1_IO03);
- iounmap(SW_PAD_GPIO1_IO03);
- iounmap(GPIO1_DR);
- iounmap(GPIO1_GDIR);
- device_destroy(led_class,MKDEV(LED_MAJOR,0));
- class_destroy(led_class);
- unregister_chrdev(LED_MAJOR, LED_NAME);
- }
-
- module_init(led_driver_init);
- module_exit(led_driver_exit);
- MODULE_LICENSE("GPL");
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdint.h>
-
-
-
- int main(int argc, char *argv[])
- {
- int fd;
- int ret;
- uint8_t led;
- fd = open(argv[1], O_RDWR);
-
- if(!strcmp("led_on",argv[2]))
- {
- printf("led on\r\n");
- led = 1;
- write(fd,&led,sizeof(led));
- }
-
- if(!strcmp("led_off",argv[2]))
- {
- led = 0;
- printf("led on\r\n");
- write(fd,&led,sizeof(led));
- }
-
-
- close(fd);
-
-
- }
点亮 LED灯 ./test_app /dev/led led_on
熄灭 LED灯 ./test_app /dev/led led_on
其实到了这一步虽然不需要配对寄存器地址,但是代码还在编写寄存器代码,也就是说换了一个GPIO还是要修改代码,是的!!!别急,后续我们看了GPIO子系统以及pinctl子系统后相信会有答案!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。