驱动代码
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 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);
}
static void usr_timer_init(void)
{
init_timer(&usr_timer);
usr_timer.expires = jiffies + HZ/1;
usr_timer.function = &usr_timer_test_callback;
usr_timer.data = ((unsigned long)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_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,
.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);
usr_drv_class = class_create(THIS_MODULE, CLASS_NAME);
device_create(usr_drv_class, NULL, MKDEV(usr_drv_major, 0), NULL,REG_DEV_NAME);
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
Makefile
KERN_DIR = /home/linux/workspace/Hi3516/system/SDK/rp-hi3516dv300-sdk020/osdrv/opensource/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);
if(fd <0)
{
perror("fd");
return -1;
}
while(1)
{
read(fd, &value, sizeof(int));
printf("read val = %d\n",value);
}
close(fd);
return 0;
}
Makefile
PROJ_NAME = usr_test
objs += $(PROJ_NAME).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
加载驱动
应用运行结果