基于全志A33的LED驱动开发,安卓6.0.1平台

来源:互联网 发布:什么是少儿编程 编辑:程序博客网 时间:2024/05/17 02:33

本篇基于华清远见733平板进行的LED驱动开发,这个板子用的是全志A33开发,其它板子也是通用的,所以,接下来介绍一下驱动开发:


根据全志的用户手册可以看到,GPIO的基地址是0X01C20800,然后需要驱动哪个口,就在基地址上增加偏移地址即可,本板子用到是PF2口:

     

如上图,PF口的Configure寄存器的偏移地址是0XB4,这个在驱动开发的时候会用到,下面的驱动程序中可以看到,然后找到PF2口,如下图:



如上图红线框起来的,本例选择输出,


然后,有了configure寄存器的信息之后,还需要上图的data寄存器信息,这个信息全志给的太随便了,需要有一定经验才能猜到,5:0,一看就知道有6个IO口喽,然后0代表0口,以此类推,也就是PF口有6个IO喽,带着疑惑看了老师写的驱动,还真是!然后data寄存器的偏移量是0XC4,嘿嘿,就是基地址+0XC4,也就是0x01C208C4,

那么有了以上资料之后,我们就可以写驱动了,当然这个驱动是老师写的,我拿来给大家分享,首先定义一个头文件:

#ifndef __S5PC100_LED_H#define __S5PC100_LED_H#define LED_ON _IO('k', 0)#define LED_OFF _IO('k', 1)#endif

定义头文件主要是接下来的驱动中用到了ioctl这个函数,为了区分不同的命令,才定义的,其中_IO,我在网上差的是volatile的意思,所以,我在Java里写jni是把_IO去掉了,因为有报错,然后把指令写成头文件,那么其它的,比如应用程序就可以也引用该头文件中的指令,以此保证正确的指令,当然,也可以分开写,比如在你的应用程序中也定几个宏定义,下面就看一下驱动程序:

#include <linux/module.h> #include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/device.h>#include <asm/io.h>#include "fspad733_led.h"//register of the pin using for led#define FSPAD733_GPFCON0x01C208B4#define FSPAD733_GPFDAT0x01C208C4//license informationMODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("farsight");//the major and minor idstatic int led_major = 500;static int led_minor = 0;//this is an cdev type devicestatic struct cdev led_cdev;//the pointer of the ledstatic unsigned int *gpfcon;static unsigned int *gpfdat;//class of led devicestruct class *led_class;/** * init the register */static void led_init(void){writel((readl(gpfcon) & ~(0xf << 8)) | (0x1 << 8), gpfcon);}/** * reset the register */static void led_recovery(void){writel((readl(gpfcon) & ~(0xf << 8)) | (0x3 << 8), gpfcon);}/** * set led ON */static void led_on(void){writel(readl(gpfdat) & ~(0x1 << 2), gpfdat);}/** * set led OFF */static void led_off(void){writel(readl(gpfdat) | (0x1 << 2), gpfdat);}/** * open the led device * in this fonction do noting  * because the pin using for LED is multiplexing using for UART * so anyway using this pin should init and reset the register * init while opening the device may cause some error */static int fspad733_led_open(struct inode *inode, struct file *file){printk("led: device open\n");//led_init();return 0;}/** * close is equal as reset */static int fspad733_led_close(struct inode *inode, struct file *file){printk("led: device close\n");led_recovery();return 0;}/** * use ioctl type for control the led device */static long fspad733_led_ioctl(struct file *file, unsigned int cmd, unsigned long arg){printk("led: device ioctl\n");switch(cmd){case LED_ON:printk("led: ON\n");led_init();led_on();break;case LED_OFF:printk("led: OFF\n");led_off();led_recovery();break;default:printk("led: available command\n");break;}return 0;}/** * file_operations struct */static struct file_operations fspad733_led_ops = {.owner = THIS_MODULE,.open = fspad733_led_open,.release = fspad733_led_close,.unlocked_ioctl= fspad733_led_ioctl};/** * setup for cdev */static int led_setup_cdev(struct cdev *cdev, struct file_operations *fops){int result;dev_t devno = MKDEV(led_major, led_minor);cdev_init(cdev, fops);cdev->owner = THIS_MODULE;result = cdev_add(cdev, devno, 1);if(result){printk("led: cdev add failed\n");return result;}return 0;}/** * do ontiong */static ssize_t fspad733_led_enable_show(struct device *dev,struct device_attribute *attr, char *buf){return 0;}/** * this is the same as the operate on ioctl type */static ssize_t fspad733_led_enable_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count){unsigned long data;int error;error = strict_strtoul(buf, 10, &data);printk("set value = %d\n", data);if (error)return error;if (data == 1) {printk("turn on\n");led_init();led_on();}else {printk("turn off\n");led_off();led_recovery();}return count;}//DEVICE_ATTRstatic DEVICE_ATTR(enable, 0777,fspad733_led_enable_show, fspad733_led_enable_store);//attribute tablestatic struct attribute *fspad733_led_attributes[] = {&dev_attr_enable.attr,NULL,};//group of attrstatic struct attribute_group fspad733_led_attributes_group = {.attrs = fspad733_led_attributes};//devicestruct device *dev;//deivce initstatic int __init fspad733_led_init(void){int result;dev_t devno = MKDEV(led_major, led_minor);result = register_chrdev_region(devno, 1, "fspad733_led");if(result){printk("led: unable to get major %d\n", led_major);return result;}result = led_setup_cdev(&led_cdev, &fspad733_led_ops);if(result) {printk("led: failed in cdev add.\n");unregister_chrdev_region(devno, 1);return result;}gpfcon = ioremap(FSPAD733_GPFCON, 4);if (gpfcon == NULL) {printk("led: failed in ioremap.\n");goto err1;}gpfdat = ioremap(FSPAD733_GPFDAT, 4);if (gpfcon == NULL) {printk("led: failed in ioremap.\n");goto err2;}led_class = class_create(THIS_MODULE, "farsight_led");if (IS_ERR(led_class)) {printk("led: failed in creating class.\n");goto err3;}dev = device_create(led_class, NULL, devno, NULL, "led");result = sysfs_create_group(&dev->kobj, &fspad733_led_attributes_group);if (result < 0){printk("led: sysfs_create_group err\n");goto err3;}printk("led: driver installed, with major %d!\n", led_major);return 0;err3:iounmap(gpfdat);err2:iounmap(gpfcon);err1:cdev_del(&led_cdev);unregister_chrdev_region(devno, 1);return result;}//deivce unregisterstatic void __exit fspad733_led_exit(void){dev_t devno = MKDEV(led_major, led_minor);sysfs_remove_group(&dev->kobj, &fspad733_led_attributes_group);device_destroy(led_class, devno);class_destroy(led_class);iounmap(gpfdat);iounmap(gpfcon);cdev_del(&led_cdev);unregister_chrdev_region(devno, 1);printk("led: driver uninstalled!\n");}module_init(fspad733_led_init);module_exit(fspad733_led_exit);

哈哈,老师写的注释是英文的,big有点高,嘿黑,我现在在上课,就写这么多吧,反正以上就是一个完整的驱动程序,copy一下就可以用了,先不说了,上课ing...

原创粉丝点击