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

来源:互联网 发布:java导出excel的方法 编辑:程序博客网 时间:2024/06/04 15:57

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;
}

}

0 0