ok6410 linux的第一个驱动LED驱动
//驱动程序代码
/**************************************************************************************************************** * 文件名称 : led_drive.c * 简介 : OK6410 LED驱动 * 作者 : 异灵元([email protected]) * 创建时间 : 2012/08/27 17:28 * 修改时间 : 2012/08/27 * 说明 : OK6410 开发板(S3C6410)LED(GPIO)驱动 ****************************************************************************************************************/ //系统头文件 #include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/irq.h> #include <mach/hardware.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <asm/unistd.h> //--------------------------// #include <mach/map.h> #include <mach/regs-clock.h> #include <mach/regs-gpio.h> //--------------------------// #include <plat/gpio-cfg.h> #include <mach/gpio-bank-e.h> #include <mach/gpio-bank-m.h> /////////////////////////////////////////////// //驱动模块名称 #define DEVICE_NAME "OK6410_LED" //函数声明 /////////////////////////////////////////////// static long OK6410_LED_ioctl( struct file *file, unsigned int cmd, unsigned long arg); static ssize_t OK6410_LED_write( struct file *file, const char __user *buff, size_t size, loff_t *loff); static ssize_t OK6410_LED_read( struct file *file, char __user *buff, size_t size, loff_t *loff); /////////////////////////////////////////////////// /* 这个结构是字符设备驱动的核心 * 当应用程序操作设备文件所提供的open,read,write等函数, * 最终会调用到这个结构中的对应函数 */ static struct file_operations dev_fops = { .owner = THIS_MODULE, //这是一个宏,指向编译模块时自动创建的__this_module变量 .unlocked_ioctl = OK6410_LED_ioctl, .read = OK6410_LED_read, .write = OK6410_LED_write }; //注册驱动所使用的相关信息 static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, //驱动模块名称 .fops = &dev_fops, }; //LED设备访问信号量 struct semaphore led_sem; /**************************************************************************************************************** *函数名 : static int __init OK6410_LED_init(void) *功能 : LED模块初始化函数 *参数 : 无 *返回 : 0:成功;<0:失败 *依赖 : linux底层宏定义 *作者 : 异灵元([email protected]) *创建时间 : 2012/08/27 17:28 *最后修改时间: 2012/08/27 17:28 *说明 : 初始化LED硬件,注册LED驱动 ****************************************************************************************************************/ static int __init OK6410_LED_init(void) { int ret; unsigned int reg; //GPIOM0-3 推挽输出 reg = readl(S3C64XX_GPMCON); //获取GPIOM寄存器数据 reg &= (~0xffff); //清除之前设置 reg |= 0x1111; //推挽输出 writel(reg,S3C64XX_GPMCON); //配置IO模式 reg = readl(S3C64XX_GPMDAT); //读取输出寄存器之前数据 reg |= 0xf; writel(reg,S3C64XX_GPMDAT); //写入1,让所有的灯都熄灭 ret = misc_register(&misc); //注册驱动 if(ret < 0) { printk(DEVICE_NAME " can't initialized LED!\n"); return ret; } init_MUTEX(&led_sem); //注册信号量 printk(DEVICE_NAME " initialized\n"); return 0; //返回成功 } /**************************************************************************************************************** *函数名 : static long OK6410_LED_ioctl( struct file *file, unsigned int cmd, unsigned long arg) *功能 : 发送命令给LED驱动模块,无实际作用,直接返回0 *参数 : 无作用 *返回 : 0 *依赖 : 无 *作者 : 异灵元([email protected]) *创建时间 : 2012/08/27 17:28 *最后修改时间: 2012/08/27 17:28 *说明 : 无 ****************************************************************************************************************/ static long OK6410_LED_ioctl( struct file *file, unsigned int cmd, unsigned long arg) { return 0; } /**************************************************************************************************************** *函数名 : static ssize_t OK6410_LED_write( struct file *file, const char __user *buff, size_t size, loff_t *loff) *功能 : 写数据到LED驱动模块,低电平灯亮 *参数 : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用 *返回 : 0:成功;<0:失败 *依赖 : linux底层宏 *作者 : 异灵元([email protected]) *创建时间 : 2012/08/27 17:43 *最后修改时间: 2012/08/27 17:43 *说明 : 点灯函数,低电平亮,0-3BIT有效;对应4个LED ****************************************************************************************************************/ static ssize_t OK6410_LED_write( struct file *file, const char __user *buff, size_t size, loff_t *loff) { unsigned int reg; if(down_interruptible(&led_sem)) //获取信号量 return -ERESTARTSYS; reg = readl(S3C64XX_GPMDAT); reg &= (~0xf); reg |= buff[0] & 0xf; writel(reg,S3C64XX_GPMDAT); up(&led_sem); //释放信号量 return 0; } /**************************************************************************************************************** *函数名 : static ssize_t OK6410_LED_read( struct file *file, char __user *buff, size_t size, loff_t *loff) *功能 : 读LED状态,低电平灯亮 *参数 : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用 *返回 : 0:成功;<0:失败 *依赖 : linux底层宏 *作者 : 异灵元([email protected]) *创建时间 : 2012/08/27 17:48 *最后修改时间: 2012/08/27 17:48 *说明 : 读取灯的状态,低电平灯亮,0-3bit有效;对应4个LED ****************************************************************************************************************/ static ssize_t OK6410_LED_read( struct file *file, char __user *buff, size_t size, loff_t *loff) { unsigned int reg; if(down_interruptible(&led_sem)) //获取信号量 return -ERESTARTSYS; reg = readl(S3C64XX_GPMDAT); buff[0] = reg | 0xfffffff0; up(&led_sem); //释放信号量 return 0; } /**************************************************************************************************************** *函数名 : static void __exit OK6410_LED_exit(void) *功能 : 卸载LED驱动 *参数 : 无 *返回 : 无 *依赖 : linux底层宏 *作者 : 异灵元([email protected]) *创建时间 : 2012/08/27 17:50 *最后修改时间: 2012/08/27 17:50 *说明 : 卸载驱动 ****************************************************************************************************************/ static void __exit OK6410_LED_exit(void) { unsigned int reg; //GPIOM0-3 输入 reg = readl(S3C64XX_GPMCON); //获取GPIOM寄存器数据 reg &= (~0xffff); //清除之前设置 writel(reg,S3C64XX_GPMCON); //配置IO模式 misc_deregister(&misc); //卸载驱动 } //动态加载驱动接口(必须) module_init(OK6410_LED_init); module_exit(OK6410_LED_exit); //其它信息(非必需) MODULE_AUTHOR("[email protected]"); //驱动程序作者 MODULE_DESCRIPTION("OK6410(S3C6410) LED Driver"); //一些描述信息 MODULE_LICENSE("GPL"); //遵循的协议
/**************************************************************************************************************** * 文件名称 : led_teset.c * 简介 : OK6410 LED驱动测试程序 * 作者 : 异灵元([email protected]) * 创建时间 : 2012/08/27 18:04 * 修改时间 : 2012/08/27 * 说明 : OK6410 开发板(S3C6410)LED(GPIO)驱动测试程序 ****************************************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> int main(void) { int fd; int retval; unsigned char led; //LED测试 printf("LED test...\n"); fd = open("/dev/OK6410_LED",O_RDWR); //open led if(fd == -1) { printf("open led error!\n"); exit(-1); } else { printf("open led ok!\n"); } while(1) { for(retval = 0;retval < 4;retval ++) { led = 1 << retval; led = ~led; write(fd,&led,sizeof((unsigned char)1)); //read(fd,&led,sizeof((unsigned char)1)); //printf("LED = 0x%X\n",led); usleep(1000 * 100); //100MS } for(retval = 2;retval > 0;retval --) { led = 1 << retval; led = ~led; write(fd,&led,sizeof((unsigned char)1)); //read(fd,&led,sizeof((unsigned char)1)); //printf("LED = 0x%X\n",led); usleep(1000 * 100); //100MS } } close(fd); exit(0); }