嵌入式 字符设备驱动经典示例
2014-12-10 14:31
417 查看
1、驱动led_joseph.c
{
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <asm/dma.h>
#include <asm/delay.h>
#include <linux/delay.h>
#define DEVICE_NAME "JOSEPH_LED"
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define GPIO_1_LED_DAT 0x201503FC
#define GPIO_1_LED_DIR 0x20150400
#define GPIO_1_MUX 0x200f0004
#define GPIO_G_DAT 0x201a03fc
#define GPIO_G_DIR 0x201a0400
#define GPIO_G_MUX 0x200f0080
volatile unsigned long *gpio1_1data = NULL;
volatile unsigned long *gpio1_1dir = NULL;
volatile unsigned long *gpio6_0data = NULL;
volatile unsigned long *gpio6_0dir = NULL;
volatile unsigned long *gpio_1_mux = NULL;//red
volatile unsigned long *gpio_6_mux = NULL;//blue
static dev_t joseph_led_devid;
static struct class *joseph_led_class;
static struct cdev *joseph_led_cdev;
static struct device *joseph_led_device;
static int joseph_led_open(struct inode * in, struct file *f)
{
return 0;
}
static ssize_t joseph_led_read(struct file *f, char __user *buf, size_t size, loff_t *off)
{
unsigned char joseph_led_buf[8] = {0};
static int led_status =0;
static int red_led_status = 0;//0 - on ; 1 - off
static int green_led_status = 0;//0 - on ; 1 - off
memset(joseph_led_buf,0,8);
#if 0
*gpio_6_mux&= ~BIT_MASK(0); //gpio
*gpio_1_mux &= ~BIT_MASK(0); //gpio
*gpio1_1dir &= ~(1<<1);//input
*gpio6_0dir &= ~(1<<0);//input
#endif
red_led_status = *gpio1_1data;
green_led_status = *gpio6_0data;
if((red_led_status & 0x2) == 0)
{
led_status = 0;
sprintf(joseph_led_buf,"%d",led_status);
}
if((red_led_status & 0x2) == 2)
{
led_status = 1;
sprintf(joseph_led_buf,"%d",led_status);
}
if((green_led_status & 0x1) == 0)
{
led_status = 0;
sprintf(joseph_led_buf+1,"%d",led_status);
}
if((green_led_status & 0x1) == 1)
{
led_status = 1;
sprintf(joseph_led_buf+1,"%d",led_status);
}
mdelay(500);
copy_to_user(buf,joseph_led_buf,sizeof(joseph_led_buf));
return sizeof(joseph_led_buf);
}
static ssize_t joseph_led_write(struct file *f, const char __user *buf, size_t size, loff_t *off)
{
char buf_tmp[8];
copy_from_user(buf_tmp, buf, size); //
printk(KERN_INFO"joseh_led_write begin %s !\n",buf_tmp);
*gpio1_1dir |= 1<<1;//output
*gpio6_0dir |= 1<<0;//output
mdelay(5);
*gpio_1_mux &= ~BIT_MASK(0); //gpio
mdelay(5);
*gpio_6_mux &= ~BIT_MASK(0); //gpio
mdelay(5);
if( strcmp(buf_tmp,"00") == 0)
{
*gpio1_1data &= ~BIT_MASK(1);//on
mdelay(5);
*gpio6_0data &= ~BIT_MASK(0);//on
mdelay(5);
}
if( strcmp(buf_tmp,"01") == 0)
{
*gpio1_1data &= ~BIT_MASK(1);//on
mdelay(5);
*gpio6_0data |= BIT_MASK(0);//off
mdelay(5);
}
if( strcmp(buf_tmp,"10") == 0)
{
*gpio1_1data |= BIT_MASK(1);//off
mdelay(5);
*gpio6_0data &= ~BIT_MASK(0);//on
mdelay(5);
}
if( strcmp(buf_tmp,"11") == 0)
{
*gpio1_1data |= BIT_MASK(1);//off
mdelay(5);
*gpio6_0data |= BIT_MASK(0);//off
mdelay(5);
}
return size;
}
static struct file_operations joseph_led_fops = {
.owner = THIS_MODULE,
.open = joseph_led_open,
.read = joseph_led_read,
.write = joseph_led_write
};
static int __init joseph_led_init(void)
{
int ret;
ret = alloc_chrdev_region(&joseph_led_devid, 0, 1,DEVICE_NAME);
if(ret < 0)
{
printk(KERN_ERR "can't allocate char device ID\n");
return -1;
}
joseph_led_class = class_create(THIS_MODULE, DEVICE_NAME);
joseph_led_cdev = cdev_alloc();
if(joseph_led_cdev == NULL)
{
printk(KERN_ERR "can't allocate cdev struct \n");
return -1;
}
joseph_led_cdev->ops = &joseph_led_fops;
joseph_led_cdev->owner = THIS_MODULE;
ret = cdev_add(joseph_led_cdev,joseph_led_devid,1);
if(ret < 0)
{
printk(KERN_ERR "can't add cdev \n");
return -1;
}
joseph_led_device = device_create(joseph_led_class,NULL,joseph_led_devid,NULL,"joseph_led");
printk("Congratulate joseph_led_init ok !\n");
gpio1_1data = ioremap_nocache((unsigned long)0x201503fc, (unsigned long)0x10000);
gpio1_1dir = ioremap_nocache((unsigned long)0x20150400, (unsigned long)0x10000);
gpio6_0data= ioremap_nocache((unsigned long)GPIO_G_DAT, (unsigned long)0x10000);
gpio6_0dir= ioremap_nocache((unsigned long)GPIO_G_DIR, (unsigned long)0x10000);
gpio_1_mux = ioremap_nocache((unsigned long)GPIO_1_MUX, (unsigned long)0x10000);
gpio_6_mux = ioremap_nocache((unsigned long)GPIO_G_MUX, (unsigned long)0x10000);
return 0;
}
static void __exit joseph_led_exit(void)
{
unregister_chrdev_region(joseph_led_devid, 1);
device_destroy(joseph_led_class, joseph_led_devid);
cdev_del(joseph_led_cdev);
class_destroy(joseph_led_class);
iounmap(gpio1_1data);
iounmap(gpio1_1dir);
iounmap(gpio_1_mux);
iounmap(gpio6_0data);
iounmap(gpio6_0dir);
iounmap(gpio_6_mux);
printk("Congratulate joseph_led_init Rmmod ok !\n");
}
module_init(joseph_led_init);
module_exit(joseph_led_exit);
MODULE_AUTHOR("xxxx");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Device Driver for joseph_led ! ");
}
2、Makefile
{
ifneq ($(KERNELRELEASE),)
obj-m := led_joseph.o
else
KERNELDIR ?= /home/kongjun/mywork/develop_kj/Hi3518_SDK_V1.0.3.0/osdrv/kernel/linux-3.0.y
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
}
3、上层应用
{
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define LED_DEV "/dev/joseph_led"
int main(int argc , char *argv[])
{
#if 1
int i;
int fd = -1;
char buf[8];
char *buf_write = NULL;
if((fd=open(LED_DEV, O_RDWR))<0){
printf("Error opening %s can device\n", LED_DEV);
return 1;
}
buf_write = argv[1];
write(fd,buf_write,8);
#else
int i;
int fd = -1;
char buf[8];
if((fd=open(LED_DEV, O_RDWR))<0){
printf("Error opening %s can device\n", LED_DEV);
return 1;
}
read(fd,buf,8);
printf("%s %d The status of led is %s\n",__FUNCTION__,__LINE__,buf);
#endif
close(fd);
return 0;
}
}
{
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <asm/dma.h>
#include <asm/delay.h>
#include <linux/delay.h>
#define DEVICE_NAME "JOSEPH_LED"
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define GPIO_1_LED_DAT 0x201503FC
#define GPIO_1_LED_DIR 0x20150400
#define GPIO_1_MUX 0x200f0004
#define GPIO_G_DAT 0x201a03fc
#define GPIO_G_DIR 0x201a0400
#define GPIO_G_MUX 0x200f0080
volatile unsigned long *gpio1_1data = NULL;
volatile unsigned long *gpio1_1dir = NULL;
volatile unsigned long *gpio6_0data = NULL;
volatile unsigned long *gpio6_0dir = NULL;
volatile unsigned long *gpio_1_mux = NULL;//red
volatile unsigned long *gpio_6_mux = NULL;//blue
static dev_t joseph_led_devid;
static struct class *joseph_led_class;
static struct cdev *joseph_led_cdev;
static struct device *joseph_led_device;
static int joseph_led_open(struct inode * in, struct file *f)
{
return 0;
}
static ssize_t joseph_led_read(struct file *f, char __user *buf, size_t size, loff_t *off)
{
unsigned char joseph_led_buf[8] = {0};
static int led_status =0;
static int red_led_status = 0;//0 - on ; 1 - off
static int green_led_status = 0;//0 - on ; 1 - off
memset(joseph_led_buf,0,8);
#if 0
*gpio_6_mux&= ~BIT_MASK(0); //gpio
*gpio_1_mux &= ~BIT_MASK(0); //gpio
*gpio1_1dir &= ~(1<<1);//input
*gpio6_0dir &= ~(1<<0);//input
#endif
red_led_status = *gpio1_1data;
green_led_status = *gpio6_0data;
if((red_led_status & 0x2) == 0)
{
led_status = 0;
sprintf(joseph_led_buf,"%d",led_status);
}
if((red_led_status & 0x2) == 2)
{
led_status = 1;
sprintf(joseph_led_buf,"%d",led_status);
}
if((green_led_status & 0x1) == 0)
{
led_status = 0;
sprintf(joseph_led_buf+1,"%d",led_status);
}
if((green_led_status & 0x1) == 1)
{
led_status = 1;
sprintf(joseph_led_buf+1,"%d",led_status);
}
mdelay(500);
copy_to_user(buf,joseph_led_buf,sizeof(joseph_led_buf));
return sizeof(joseph_led_buf);
}
static ssize_t joseph_led_write(struct file *f, const char __user *buf, size_t size, loff_t *off)
{
char buf_tmp[8];
copy_from_user(buf_tmp, buf, size); //
printk(KERN_INFO"joseh_led_write begin %s !\n",buf_tmp);
*gpio1_1dir |= 1<<1;//output
*gpio6_0dir |= 1<<0;//output
mdelay(5);
*gpio_1_mux &= ~BIT_MASK(0); //gpio
mdelay(5);
*gpio_6_mux &= ~BIT_MASK(0); //gpio
mdelay(5);
if( strcmp(buf_tmp,"00") == 0)
{
*gpio1_1data &= ~BIT_MASK(1);//on
mdelay(5);
*gpio6_0data &= ~BIT_MASK(0);//on
mdelay(5);
}
if( strcmp(buf_tmp,"01") == 0)
{
*gpio1_1data &= ~BIT_MASK(1);//on
mdelay(5);
*gpio6_0data |= BIT_MASK(0);//off
mdelay(5);
}
if( strcmp(buf_tmp,"10") == 0)
{
*gpio1_1data |= BIT_MASK(1);//off
mdelay(5);
*gpio6_0data &= ~BIT_MASK(0);//on
mdelay(5);
}
if( strcmp(buf_tmp,"11") == 0)
{
*gpio1_1data |= BIT_MASK(1);//off
mdelay(5);
*gpio6_0data |= BIT_MASK(0);//off
mdelay(5);
}
return size;
}
static struct file_operations joseph_led_fops = {
.owner = THIS_MODULE,
.open = joseph_led_open,
.read = joseph_led_read,
.write = joseph_led_write
};
static int __init joseph_led_init(void)
{
int ret;
ret = alloc_chrdev_region(&joseph_led_devid, 0, 1,DEVICE_NAME);
if(ret < 0)
{
printk(KERN_ERR "can't allocate char device ID\n");
return -1;
}
joseph_led_class = class_create(THIS_MODULE, DEVICE_NAME);
joseph_led_cdev = cdev_alloc();
if(joseph_led_cdev == NULL)
{
printk(KERN_ERR "can't allocate cdev struct \n");
return -1;
}
joseph_led_cdev->ops = &joseph_led_fops;
joseph_led_cdev->owner = THIS_MODULE;
ret = cdev_add(joseph_led_cdev,joseph_led_devid,1);
if(ret < 0)
{
printk(KERN_ERR "can't add cdev \n");
return -1;
}
joseph_led_device = device_create(joseph_led_class,NULL,joseph_led_devid,NULL,"joseph_led");
printk("Congratulate joseph_led_init ok !\n");
gpio1_1data = ioremap_nocache((unsigned long)0x201503fc, (unsigned long)0x10000);
gpio1_1dir = ioremap_nocache((unsigned long)0x20150400, (unsigned long)0x10000);
gpio6_0data= ioremap_nocache((unsigned long)GPIO_G_DAT, (unsigned long)0x10000);
gpio6_0dir= ioremap_nocache((unsigned long)GPIO_G_DIR, (unsigned long)0x10000);
gpio_1_mux = ioremap_nocache((unsigned long)GPIO_1_MUX, (unsigned long)0x10000);
gpio_6_mux = ioremap_nocache((unsigned long)GPIO_G_MUX, (unsigned long)0x10000);
return 0;
}
static void __exit joseph_led_exit(void)
{
unregister_chrdev_region(joseph_led_devid, 1);
device_destroy(joseph_led_class, joseph_led_devid);
cdev_del(joseph_led_cdev);
class_destroy(joseph_led_class);
iounmap(gpio1_1data);
iounmap(gpio1_1dir);
iounmap(gpio_1_mux);
iounmap(gpio6_0data);
iounmap(gpio6_0dir);
iounmap(gpio_6_mux);
printk("Congratulate joseph_led_init Rmmod ok !\n");
}
module_init(joseph_led_init);
module_exit(joseph_led_exit);
MODULE_AUTHOR("xxxx");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Device Driver for joseph_led ! ");
}
2、Makefile
{
ifneq ($(KERNELRELEASE),)
obj-m := led_joseph.o
else
KERNELDIR ?= /home/kongjun/mywork/develop_kj/Hi3518_SDK_V1.0.3.0/osdrv/kernel/linux-3.0.y
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
}
3、上层应用
{
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define LED_DEV "/dev/joseph_led"
int main(int argc , char *argv[])
{
#if 1
int i;
int fd = -1;
char buf[8];
char *buf_write = NULL;
if((fd=open(LED_DEV, O_RDWR))<0){
printf("Error opening %s can device\n", LED_DEV);
return 1;
}
buf_write = argv[1];
write(fd,buf_write,8);
#else
int i;
int fd = -1;
char buf[8];
if((fd=open(LED_DEV, O_RDWR))<0){
printf("Error opening %s can device\n", LED_DEV);
return 1;
}
read(fd,buf,8);
printf("%s %d The status of led is %s\n",__FUNCTION__,__LINE__,buf);
#endif
close(fd);
return 0;
}
}
相关文章推荐
- 宋宝华 《Linux设备驱动开发详解》示例代码之基本字符设备驱动
- 嵌入式学习笔记——字符设备驱动编写
- 嵌入式Linux字符设备驱动模型详解
- linux早期经典字符设备驱动模型
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-查询+中断+引入poll机制的按键驱动程序
- 宋宝华 《Linux设备驱动开发详解》示例代码之fifo字符设备驱动
- 嵌入式学习-驱动开发-lesson1-字符设备驱动模型
- 嵌入式Linux驱动学习之路(二十七)字符设备驱动的另一种写法
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-按键驱动程序之异步通知机制+原子操作+互斥信号量+阻塞与非阻塞+定时器去抖
- 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入
- 嵌入式 字符设备驱动编程
- 嵌入式Linux之字符设备驱动
- 【嵌入式Linux驱动开发】三、字符设备驱动(一)
- Linux嵌入式学习-烟雾传感器驱动-字符设备驱动-按键驱动
- 嵌入式Linux字符设备入门之--LED驱动详解
- 嵌入式 globalmem虚拟字符设备驱动雏形
- ceph存储 字符设备驱动示例x86Linux平台
- 嵌入式Linux字符设备驱动LED驱动编写
- 小学生学嵌入式:)Linux_字符设备驱动_流水灯的实现
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-LED字符设备驱动