Introduction to driver for "s3c6410 LED"
折腾着非得写个LED driver出来~不然心里都不舒服...
内核版本:3.0.1
环境: Ubuntu14.0 TSL
开发板上嵌有4个LED灯
4个LED对应的ARM芯片上的引脚
易知,这里4个LED对应的IO引脚就是GPM0~GPM3
三个寄存器控制这里的GPIO -- GPM0~GPM3
- GPMCON
- GPMDAT
- GPMPUD
这里gpio-bank-m.h定义了GPM相关的寄存器地址~这是一层爽歪歪的封装~(发现这是飞凌添加的header file...)
/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-m.h * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks <[email protected]> * http://armlinux.simtec.co.uk/ * * GPIO Bank M register and configuration definitions * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #define S3C64XX_GPMCON (S3C64XX_GPM_BASE + 0x00) #define S3C64XX_GPMDAT (S3C64XX_GPM_BASE + 0x04) #define S3C64XX_GPMPUD (S3C64XX_GPM_BASE + 0x08) #define S3C64XX_GPM_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) #define S3C64XX_GPM_INPUT(__gpio) (0x0 << ((__gpio) * 2)) #define S3C64XX_GPM_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) #define S3C64XX_GPM0_HOSTIF_CS (0x02 << 0) #define S3C64XX_GPM0_EINT23 (0x03 << 0) #define S3C64XX_GPM0_RESERVED1 (0x04 << 0) #define S3C64XX_GPM0_DATA_CF10 (0x05 << 0) #define S3C64XX_GPM0_CE_CF0 (0x06 << 0) #define S3C64XX_GPM0_RESERVED2 (0x07 << 0) #define S3C64XX_GPM1_HOSTIF_CS_M (0x02 << 0) #define S3C64XX_GPM1_EINT24 (0x03 << 0) #define S3C64XX_GPM1_RESERVED1 (0x04 << 0) #define S3C64XX_GPM1_DATA_CF11 (0x05 << 0) #define S3C64XX_GPM1_CE_CF1 (0x06 << 0) #define S3C64XX_GPM1_RESERVED2 (0x07 << 0) #define S3C64XX_GPM2_HOSTIF_IF_CS_S (0x02 << 0) #define S3C64XX_GPM2_EINT25 (0x03 << 0) #define S3C64XX_GPM2_HOSTIF_MDP_VSYNC (0x04 << 0) #define S3C64XX_GPM2_DATA_CF12 (0x05 << 0) #define S3C64XX_GPM2_IORD_CF (0x06 << 0) #define S3C64XX_GPM2_RESERVED2 (0x07 << 0) #define S3C64XX_GPM3_HOSTIF_WE (0x02 << 0) #define S3C64XX_GPM3_EINT26 (0x03 << 0) #define S3C64XX_GPM3_RESERVED1 (0x04 << 0) #define S3C64XX_GPM3_DATA_CF13 (0x05 << 0) #define S3C64XX_GPM3_IOWR_CF (0x06 << 0) #define S3C64XX_GPM3_RESERVED2 (0x07 << 0) #define S3C64XX_GPM4_HOSTIF_OE (0x02 << 0) #define S3C64XX_GPM4_EINT27 (0x03 << 0) #define S3C64XX_GPM4_RESERVED1 (0x04 << 0) #define S3C64XX_GPM4_DATA_CF14 (0x05 << 0) #define S3C64XX_GPM4_IORDY_CF (0x06 << 0) #define S3C64XX_GPM4_RESERVED2 (0x07 << 0) #define S3C64XX_GPM5_HOSTIF_INTR (0x02 << 0) #define S3C64XX_GPM5_CF_DATA_DIR (0x03 << 0) #define S3C64XX_GPM5_RESERVED1 (0x04 << 0) #define S3C64XX_GPM5_DATA_CF15 (0x05 << 0) #define S3C64XX_GPM5_RESERVED2 (0x06 << 0) #define S3C64XX_GPM5_RESERVED3 (0x07 << 0)
相关的有宏定义
S3C64XX_GPM_BASE
这个在regs-gpio.h 里面
节选了部分,不全部贴出了
...
#define S3C64XX_GPL_BASE S3C64XX_GPIOREG(0x0810) #define S3C64XX_GPM_BASE S3C64XX_GPIOREG(0x0820) #define S3C64XX_GPN_BASE S3C64XX_GPIOREG(0x0830)
...
Here my source code for my led-device driver.
/* code writer : EOF code date : 2014.08.19.com code file : led_by_EOF.c e-mail : [email protected] code purpos: This code is a demo for beginner how to write a character device to drive IO port. If you find there is something wrong with my code and change it into a better version , please touch me by e-mail. Thank you. */ #include <linux/init.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <asm/uaccess.h> /* for 'copy_from_user' */ #include <linux/cdev.h> #include <linux/kdev_t.h> #include <linux/types.h> #include <mach/gpio-bank-m.h> #include <mach/regs-gpio.h> #include <mach/map.h> #include <linux/pci.h> #include <linux/device.h> #include <linux/delay.h> /* for 'msleep' */ MODULE_AUTHOR("EOF"); MODULE_LICENSE("Dual BSD/GPL"); #define DEVICE_NAME "led_by_EOF" #define DEVICE_MAJOR_NUMBER 0 #define USE_IMMEDIATE static dev_t dev_number = DEVICE_MAJOR_NUMBER; static struct class* led_class; static struct cdev my_led_cdev; static int led_open(struct inode* node,struct file* file) { printk(KERN_ALERT "Device Opened successful!\n"); return 0; } static ssize_t led_write(struct file* file,const char __user* buf,size_t count,loff_t* ppos) { int kbuf; int ret = 0; kbuf = readl(S3C64XX_GPMCON); kbuf &= (~0xFFFF); kbuf |= 0x1111; writel(kbuf,S3C64XX_GPMCON); printk(KERN_ALERT "before writing... &kbuf:%p buf:%p\n",&kbuf,buf); ret = __copy_from_user(&kbuf,buf,count); if(ret != 0) { printk(KERN_ALERT "'__copy_from_user' failed! ret:%d\n",ret); return -1; } printk(KERN_ALERT "writing... kbuf:%x \n",kbuf); writel(kbuf,S3C64XX_GPMDAT); return 0; } static int led_release(struct inode* inode,struct file*file) { printk(KERN_ALERT "Device released\n"); return 0; } static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .write = led_write, .release= led_release, }; int led_init(void) { int kbuf; if(alloc_chrdev_region(&dev_number,0,1,DEVICE_NAME) < 0) { printk(KERN_ALERT "Error in function '%s' : can't register device\n",__FUNCTION__); return -1; } led_class = class_create(THIS_MODULE,DEVICE_NAME); if(IS_ERR(led_class)) { printk(KERN_ALERT "Bad class create\n"); return -1; } cdev_init(&my_led_cdev,&led_fops); /* ** GPM0~GPM3 pull up */ kbuf = readl(S3C64XX_GPMPUD); kbuf &= (~0xFF); kbuf |= 0xaa;//1010 1010 writel(kbuf,S3C64XX_GPMPUD); /* ** GPM0~3 output mode */ kbuf = readl(S3C64XX_GPMCON); kbuf &= (~0xFFFF); kbuf |= 0x1111; writel(kbuf,S3C64XX_GPMCON); /* ** GPM0~GPM3 output 0 and light up all LED */ kbuf = __raw_readl(S3C64XX_GPMDAT); kbuf |= 0x10; writel(kbuf,S3C64XX_GPMDAT); if(cdev_add(&my_led_cdev,dev_number,1)) { printk(KERN_ALERT "Bad cdev add\n"); return 1; } device_create(led_class,NULL,dev_number,NULL,DEVICE_NAME); return 0; } void led_cleanup(void) { device_destroy(led_class,MKDEV(MAJOR(dev_number),0)); class_destroy(led_class); unregister_chrdev_region(MAJOR(dev_number),1); printk(KERN_ALERT "See you! My LED\n"); } module_init(led_init); module_exit(led_cleanup);
Test code:
/* code writer : EOF code date : 2014.08.19.com code file : led_by_EOF.c e-mail : [email protected] code purpos: This code is a demo for test my led-device. If you find there is something wrong with my code and change it into a better version , please touch me by e-mail. Thank you. */ #include <stdio.h> #include <fcntl.h> #include <stdlib.h> int main() { int fd = 0; int ret = 0; if((fd = open("/dev/led_by_EOF",O_RDWR)) < 0) { printf("line %d open failed\n",__LINE__); return 0; } int buf = 0; int time = 0; buf = 0x0; for(time = 0,buf = 0;time < 5;time++) { if((ret = write(fd,&buf,sizeof(buf))) < 0) { printf("write error!\n ret : %d\n",ret); //goto failed; } else { printf("write successful! ret %d,buf:%d &buf:%p\n",ret,buf,&buf); } buf = ~buf; sleep(2); } failed: close(fd); return 0; }
最后灯会闪亮
时间: 2024-10-30 09:57:18