LED
平台:全志A64
源码:Android 7.1 Linux 3.1
led.c
1 //没有使用平台总线 2 3 #include <linux/init.h> 4 #include <linux/module.h> 5 #include <linux/fs.h> 6 #include <linux/device.h> 7 #include <linux/slab.h> 8 #include <linux/gpio.h> 9 #include <linux/cdev.h> 10 11 #include <asm/io.h> 12 #include <asm/uaccess.h> 13 #include <asm-generic/ioctl.h> 14 15 16 //面向对象封装led信息 17 struct a64_led{ 18 //unsigned int major; 19 dev_t devno; 20 struct class * cls; 21 struct device * dev; 22 struct cdev *cdev; 23 int data; 24 }; 25 struct a64_led *led_dev; 26 27 28 volatile unsigned int *gpco_conf = NULL; 29 volatile unsigned int *gpco_data = NULL; 30 31 32 33 34 int led_open(struct inode *inode, struct file *filp) 35 { 36 37 //将对应的管脚设置为输出——PL10 38 *gpco_conf &= ~(0x07<<8); //清零 39 *gpco_conf |= 0x01<<8; //置位 40 41 return 0; 42 } 43 44 45 ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *flags) 46 { 47 int ret; 48 49 //应用空间数据转换为内核空间数据 50 ret = copy_from_user(&led_dev->data,buf,size); 51 if(ret != 0){ 52 printk("copy_from_user error!\n"); 53 return -EFAULT; 54 } 55 56 if(led_dev->data){ 57 *gpco_data |= 0x1<<10; //点灯 58 }else{ 59 *gpco_data &= ~(0x1<<10);//灭灯 60 } 61 62 return size; 63 } 64 65 66 int led_close(struct inode *inode, struct file *filp) 67 { 68 69 *gpco_data &= ~(0x1<<10); //灭灯 70 71 return 0; 72 } 73 74 75 static struct file_operations fops = { 76 .open = led_open, // 打开对gpio初始化config 77 .write = led_write, 78 .release = led_close, 79 }; 80 81 82 static int __init led_init(void) 83 { 84 85 // 1_实例化设备对象 86 //参数1 -- 要申请的空间的大小 87 //参数2 -- 申请的空间的标识 88 led_dev = kzalloc(sizeof(struct a64_led),GFP_KERNEL); 89 if(IS_ERR(led_dev)){ 90 printk("kzalloc error!\n"); 91 ret = PTR_ERR(led_dev); 92 return -ENOMEM; 93 } 94 95 96 // 2_申请设备编号 97 98 //动态申请设备号 99 ret = alloc_chrdev_region(&led_dev->devno,10,1,"led_drv"); 100 if(ret < 0){ 101 printk("register_chrdev_region error!\n"); 102 ret = -EINVAL; 103 goto err_kfree; 104 } 105 106 //申请cdev的空间 107 led_dev->cdev = cdev_alloc(); 108 if(IS_ERR(led_dev->cdev)){ 109 printk("led_dev->cdev error!\n"); 110 ret = PTR_ERR(led_dev->cdev); 111 goto err_unregister; 112 } 113 114 //初始化cdev的成员 115 cdev_init(led_dev->cdev,&fops); 116 117 //将cdev加入到内核中----链表 118 ret = cdev_add(led_dev->cdev,led_dev->devno,1); 119 120 121 // 3_创建设备文件 122 led_dev->cls = class_create(THIS_MODULE,"led_cls"); 123 if(IS_ERR(led_dev->cls)){ 124 printk("class_create error!\n"); 125 ret = PTR_ERR(led_dev->cls); 126 goto err_cdev_del; 127 } 128 led_dev->dev = device_create(led_dev->cls,NULL,led_dev->devno,NULL,"led"); 129 if(IS_ERR(led_dev->dev)){ 130 printk("device_create error!\n"); 131 ret = PTR_ERR(led_dev->dev); 132 goto err_class; 133 } 134 135 // 4_硬件初始化----地址映射 136 137 gpco_conf = ioremap(0x1F02C04,8); 138 gpco_data = ioremap(0x1F02C10,8); 139 140 return 0; 141 142 err_class: 143 class_destroy(led_dev->cls); 144 145 err_cdev_del: 146 cdev_del(led_dev->cdev); 147 148 err_unregister: 149 unregister_chrdev_region(led_dev->devno,1); 150 151 err_kfree: 152 kfree(led_dev); 153 return ret; 154 155 } 156 157 158 static void __exit led_exit(void) 159 { 160 printk("--------^_^ %s------------\n",__FUNCTION__); 161 device_destroy(led_dev->cls,led_dev->devno); 162 class_destroy(led_dev->cls); 163 cdev_del(led_dev->cdev); 164 unregister_chrdev_region(led_dev->devno,1); 165 kfree(led_dev); 166 } 167 168 module_init(led_init); 169 module_exit(led_exit); 170 MODULE_LICENSE("GPL");
app.c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <fcntl.h> 7 #include <sys/ioctl.h> 8 9 10 int main(void) 11 { 12 char led [1] = {1}; 13 14 int fd = open("/dev/led",O_RDWR); 15 if(fd < 0){ 16 perror("open"); 17 exit(1); 18 } 19 20 //闪灯 21 int ret = write(fd, led, 1); 22 if(ret <0) 23 { 24 printf("write failed !\n"); 25 exit(0); 26 } 27 sleep(1); 28 29 close(fd); 30 return 0; 31 }
笔记
配置寄存器和数据寄存器自行查询用户手册(基地址+偏移地址)
A64:如下