您的位置:首页 > 其它

嵌入式 字符设备驱动经典示例

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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: