2019-2020 20175207- 20175235 Experiment 4 Peripheral Driver Design

20175207-20175235 Experiment 4 Peripheral Driver Design

20,175,207 cold south
20,175,235 Zeren La measures

table of Contents:

Peripheral driver design -1

Peripheral driver design -2

Job details
Full Course "hqyj. Embedded Linux application development standard tutorial .pdf" in Chapter XI of learning resources
to submit photos of Cornell notes (can be more than one)





Task details
on Ubuntu complete test test resources in the whole class of "hqyj. Embedded Linux application development standard tutorial .pdf" Chapter XI
submit to compile, load modules, unloading modules screenshots, test run (to be more Zhang, full-screen, reflecting the student number information)

  • Makefile
ifeq ($(KERNELRELEASE),)

KERNELDIR ?= /lib/modules/$(shell uname -r)/build 

PWD := $(shell pwd)

modules:

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:

    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else

obj-m := test_drv.o 

endif
  • test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define TEST_DEVICE_FILENAME "/dev/stdout"
#define BUFF_SZ 1024

int main()
{
    int fd,nwrite,nread;
    char buff[BUFF_SZ];
    
    fd = open(TEST_DEVICE_FILENAME, O_RDWR);
    if(fd<0)
    {
        perror("open");
        exit(1);
    }
    
    do 
    {
        printf("Input some words to kernel(enter 'quit' to exit):");
        memset(buff,0,BUFF_SZ);
        if(fgets(buff,BUFF_SZ,stdin) == NULL)
        {
            perror("fgets");
            break;
        }
        buff[strlen(buff) - 1] = '\0';
        if(write(fd,buff,strlen(buff)) < 0)
        {
            perror("write");
            break;
        }
        if(read(fd,buff,BUFF_SZ) < 0)
        {
            perror("read");
            break;
        }
        else
        {
            printf("The read string is from kernel:%s\n",buff);
        }
    } while(strncmp(buff,"quit",4));
    close(fd);
    exit(0);
}  
  • test_drv.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#define TEST_DEVICE_NAME "test_dev"
#define BUFF_SZ 1024
/*全局变量*/
static struct cdev test_dev;
unsigned int major =0;
static char *data = NULL;
/*读函数*/
static ssize_t test_read(struct file *file,
char *buf, size_t count, loff_t *f_pos)
{
int len;
if (count < 0 )
{
return -EINVAL;
}
len = strlen(data);
count = (len > count)?count:len;
if (copy_to_user(buf, data, count)) /* ?内核??的数????用户??*/
{
return -EFAULT;
}
return count;
}
/*写函数*/
static ssize_t test_write(struct file *file, const char *buffer,
size_t count, loff_t *f_pos)
{
if(count < 0)
{
return -EINVAL;
}
memset(data, 0, BUFF_SZ);
count = (BUFF_SZ > count)?count:BUFF_SZ;
if (copy_from_user(data, buffer, count)) /* 将用户缓冲的数据复制到内核空间*/
{
return -EFAULT;
}
return count;
}
/*打开函数*/
static int test_open(struct inode *inode, struct file *file)
{
printk("This is open operation\n");
/* 分配并初始化缓冲区*/
data = (char*)kmalloc(sizeof(char) * BUFF_SZ, GFP_KERNEL);
if (!data)
{
return -ENOMEM;
}
memset(data, 0, BUFF_SZ);
return 0;
}
/*关闭函数*/
static int test_release(struct inode *inode,struct file *file)
{
printk("This is release operation\n");
if (data)
{
kfree(data); /* 释放缓冲区*/
data = NULL; /* 防止出现野指针*/
}
return 0;
}
/* 创建、初始化字符设备,并且注册到系统*/
static void test_setup_cdev(struct cdev *dev, int minor,
struct file_operations *fops)
{
int err, devno = MKDEV(major, minor);
cdev_init(dev, fops);
dev->owner = THIS_MODULE;
dev->ops = fops;
err = cdev_add (dev, devno, 1);
if (err)
{
printk (KERN_NOTICE "Error %d adding test %d", err, minor);
}
}
/* 虚拟设备的 file_operations 结构 */
static struct file_operations test_fops =
{
.owner = THIS_MODULE,
.read = test_read,
.write = test_write,
.open = test_open,
.release = test_release,
};
/*模块注册入口*/
int init_module(void)
{
int result;
dev_t dev = MKDEV(major, 0);
if (major)
{/* 静态注册一个设备,设备号先前指定好,并设定设备名,用cat /proc/devices 来查看 */
result = register_chrdev_region(dev, 1, TEST_DEVICE_NAME);
}
else
{
result = alloc_chrdev_region(&dev, 0, 1, TEST_DEVICE_NAME);
}
if (result < 0)
{
printk(KERN_WARNING "Test device: unable to get major %d\n", major);
return result;
}
test_setup_cdev(&test_dev, 0, &test_fops);
printk("The major of the test device is %d\n", major);
return 0;
}
/*卸载模块*/
void cleanup_module(void)
{
cdev_del(&test_dev);
unregister_chrdev_region(MKDEV(major, 0), 1);
printk("Test device uninstalled\n");
}
  • Command Line:
    • In the virtual device driver source directory to compile and load the module make clean;make;./test_drv_load
    • Compile and run the test program gcc –o test test.c;./test
    • Uninstall Driver./test_drv_unload
  • Test Results

  • After installing the driver

  • After uninstalling
  • Problems encountered:
  • Use makebeing given command to compile the code Makefile ...(行号) ... 遗漏分隔符...停止
    Solution: Missing Tab before the command line
    after the backslash much space
    configuration file vimrc has set expandtab (use spaces instead of tabs)
    Reference Link: Makefile error

Guess you like

Origin www.cnblogs.com/Zrlc/p/11927168.html