linux 分离分层驱动代码例子

驱动代码

usr_drv.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/irq.h>
#include <linux/poll.h>

#include <linux/platform_device.h>

#include "usr_def.h"

static DECLARE_WAIT_QUEUE_HEAD(usr_waitq);
// static struct fasync_struct * usr_async;
static volatile int usr_press ;

static struct timer_list  usr_timer;
int usr_time_tick = 0;
static void usr_timer_test_callback(unsigned long a)
{
    usr_timer.expires = jiffies + HZ/1;
	add_timer(&usr_timer);
	usr_time_tick ++;

    usr_press = 1;
    wake_up_interruptible(&usr_waitq);

    // kill_fasync(&usr_async,SIGIO,POLL_IN);
}

static void usr_timer_init(void)
{
    init_timer(&usr_timer);//先初始化timer
	
    usr_timer.expires = jiffies + HZ/1;
    usr_timer.function = &usr_timer_test_callback;//设置回调函数
    usr_timer.data = ((unsigned long)0);//设置data参数,一般传入0即可
    
    add_timer(&usr_timer);//把定时器添加到系统中,激活定时器
}

static void usr_timer_exit(void)
{
    del_timer(&usr_timer);
}




/************************************************************************************/

#define CLASS_NAME "usr_class"
#define REG_DEV_NAME "usr_drv"
static struct class *usr_drv_class;
 
static int usr_open(struct inode *inode, struct file *file)
{
	printk("usr_open\r\n");
    usr_timer_init();
	return 0;
}


static int usr_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    if(size != sizeof(int))
        return -EINVAL;

    if(file->f_flags & O_NONBLOCK)
    {
        if(!usr_press) //没有就退出。
        return -EINVAL;
    }else
    {
        printk("usr_read waitq\r\n");
        wait_event_interruptible(usr_waitq,usr_press); //阻塞
    }
   copy_to_user(buf,&usr_time_tick,sizeof(int));
   usr_press = 0;
   return 1;
}
 
static ssize_t usr_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
{
	printk("usr_write \r\n");
    return 0;	
}

static unsigned int usr_poll(struct file *file, struct poll_table_struct *wait)
{
    unsigned char mask = 0;
    poll_wait(file,&usr_waitq,wait);
    if (usr_press)
    {
        mask |= POLLIN |POLLRDNORM;
    }
    return mask;
}

// static int usr_fasync (int fd, struct file *file, int on)
// {
//     printk("usr_fasync \n");
//     return fasync_helper(fd,file,on,&usr_async);
// }

static  int usr_close (struct inode *inode, struct file *file)
{
    printk("usr_close \r\n");
    usr_timer_exit();
    return 0;
}

static struct file_operations usr_drv_fops = {
    .owner   = THIS_MODULE,
    .open    = usr_open,
    .read    = usr_read,
    .write   = usr_write,
    .poll    = usr_poll,
    // .fasync    = usr_fasync,
    .release = usr_close,

};
 

/* 驱动入口函数 */
static int usr_drv_major = (-1); /* 初始化为无效值 */
static int usr_probe(struct platform_device *pdev)
{	

    printk("usr_probe\n");

    int i=0,count=0;
    struct resource		*res;
    res = platform_get_resource(pdev,IORESOURCE_BUS,0);
    count = res->start;
    printk("count %d\n",count);
     for ( i = 0; i < count; i++)
     {
        usr_stu * tmpusr_stu=NULL;
        res = platform_get_resource(pdev, IORESOURCE_MEM, i);
        tmpusr_stu = (usr_stu *)res->start;
        printk("res(%d)->i:%d ponit:%s",i,tmpusr_stu->i,tmpusr_stu->point);

        usr_time_tick = tmpusr_stu->i;
     }
    
	usr_drv_major = register_chrdev(0,REG_DEV_NAME, &usr_drv_fops); // 注册, 告诉内核,返回值major为自动分配的主设备号
	usr_drv_class = class_create(THIS_MODULE, CLASS_NAME);
	device_create(usr_drv_class, NULL, MKDEV(usr_drv_major, 0), NULL,REG_DEV_NAME); /* insmod xxx后,会自动生成/dev/Demo_drv设备,并且自动给该设备分配主设备号major */

    return 0;
}
 
/* 驱动出口函数 */
static int usr_remove(struct platform_device *pdev)
{
    printk("usr_remove\n");
    unregister_chrdev(usr_drv_major, REG_DEV_NAME); /* 卸载驱动程序,告诉内核 */
 
    device_destroy(usr_drv_class, MKDEV(usr_drv_major, 0));
    class_destroy(usr_drv_class);
 	
	return 0;
}
 
struct platform_driver usr_drv = {
	.probe		= usr_probe,
	.remove		= usr_remove,
	.driver		= {
		.name	= "myusr",
	}
};

static int usr_drv_init(void)
{
	platform_driver_register(&usr_drv);
	return 0;
}

static void usr_drv_exit(void)
{
	platform_driver_unregister(&usr_drv);
}

module_init(usr_drv_init);
module_exit(usr_drv_exit);
 
MODULE_LICENSE("Dual BSD/GPL");
 

usr_dev.c
#include <linux/module.h>
#include <linux/version.h>

#include <linux/init.h>

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>

#include "usr_def.h"

usr_stu usr_stu1=
{
    .i = 1000,
    .point ="usr_stu1 hello driver\n",
};
usr_stu usr_stu2=
{
    .i = 2000,
    .point ="usr_stu2 hello driver\n",
};
static struct resource usr_resource[] =
{
    {
        .start = 2,
        .end   = 2,
        .flags = IORESOURCE_BUS,
    },
    {
        .start = ((int)&usr_stu1),
        .end   = ((int)&usr_stu1)+4-1,
        .flags = IORESOURCE_MEM,
    },
    {
        .start = ((int)&usr_stu2),
        .end   = ((int)&usr_stu2)+4-1,
        .flags = IORESOURCE_MEM,
    },
};

static void usr_release(struct device * dev)
{

}

static struct platform_device usr_dev = {
    .name         = "myusr",
    .id       = -1,
    .num_resources    = ARRAY_SIZE(usr_resource),
    .resource     =usr_resource,
    .dev = { 
    	.release = usr_release, 
	},
};

static int usr_dev_init(void)
{
	platform_device_register(&usr_dev);
	return 0;
}

static void usr_dev_exit(void)
{
	platform_device_unregister(&usr_dev);
}

module_init(usr_dev_init);
module_exit(usr_dev_exit);

MODULE_LICENSE("Dual BSD/GPL");
usr_def.h
#ifndef __USR_DEF_H
#define __USR_DEF_H

#include <linux/module.h>
#include <linux/kernel.h>

typedef struct
{
    int i;
    void *point;
}usr_stu;


#endif /*__USR_DEF_H */
Makefile
KERN_DIR = /home/linux/workspace/Hi3516/system/SDK/rp-hi3516dv300-sdk020/osdrv/opensource/kernel/linux-4.9.y-smp
#KERN_DIR = /work/Hi3516_SDK/system/kernel/linux-4.9.y-smp


all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= usr_Drv.o
usr_Drv-objs := usr_drv.o 

obj-m	+= usr_Dev.o
usr_Dev-objs := usr_dev.o 

编译命令
make ARCH=arm CROSS_COMPILE=arm-himix200-linux-

应用代码

usr_test.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <signal.h>
#include <poll.h>


int fd = -1;
void sig_exit_handle(int signo)
{
	if(SIGINT == signo)
	{
		close(fd);
        exit(1);
	}
}


int main(int argc ,void **argv)
{
    
    int ret;
    struct timeval rto;
    fd_set read_fds;
    int value = 0;
    signal(SIGINT,sig_exit_handle);

    // fd = open("/dev/usr_drv",O_RDWR);
    fd = open("/dev/usr_drv",O_RDWR);
    if(fd <0)
    {
        perror("fd");
        return -1;
    }
    while(1)
    {
        // rto.tv_sec =0;
        // rto.tv_usec =500000;
        
        // FD_ZERO(&read_fds);
        // FD_SET(fd, &read_fds);
        // ret = select(fd+1, &read_fds, NULL, NULL, &rto);
        // if(ret == -1) {
        //     perror("select error\n");
        //     continue;
        // } else if(ret == 0) {
        //     printf("select timeout\n");
        //     continue;
        // } else {
        //     if(FD_ISSET(fd, &read_fds)) {
                read(fd, &value, sizeof(int));
                printf("read val = %d\n",value);
        //     }
        // }
    }
    close(fd);
    return 0;
}

Makefile

PROJ_NAME  = usr_test

objs += $(PROJ_NAME).o
#objs += SX127x_def.o


dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))

CFLAGS = -Werror -Iinclude

$(PROJ_NAME): $(objs)
	arm-himix200-linux-gcc -o $(PROJ_NAME) -lm $^  -lrt 

ifneq ($(dep_files),)
include $(dep_files)
endif

%.o : %.c
	arm-himix200-linux-gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d

clean:
	rm *.o $(PROJ_NAME)

distclean:
	rm $(dep_files)
	
.PHONY: clean	

加载驱动

在这里插入图片描述

应用运行结果

在这里插入图片描述

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值