• .OpenWrt驱动程序Makefile的分析概述 、驱动程序代码参考、以及测试程序代码参考


    #
    #
    #
    
    include $(TOPDIR)/rules.mk  //一般在 Makefile 的开头
    include $(INCLUDE_DIR)/kernel.mk  // 文件对于 软件包为内核时是不可缺少
    
    PKG_NAME:=mydrv  // 表示软件包名称,将在 menuconfig 和 ipkg 可以看到
    PKG_RELEASE:=1  //表示软件包版本号
    
    include $(INCLUDE_DIR)/package.mk  //一般在软件包的基本信息完 成后再引入
    
    define KernelPackage/mydrv  //编译包定义,应用程序和内核驱动模块的定义不一样。应用程序软件包使用 Package,內核驱动模 块使用 KernelPackage。
      SUBMENU:=Other modules  //进行分类
      TITLE:=mydrv  //标题
      FILES:=$(PKG_BUILD_DIR)/mydrv.ko  //模块文件
      KCONFIG:=
    endef
    
    define KernelPackage/mydrv/description
      This is a mydrv drivers  //描述
    endef
    
    MAKE_OPTS:=          //编译之前指定工具和内核arch等
        ARCH="$(LINUX_KARCH)" 
        CROSS_COMPILE="$(TARGET_CROSS)" 
        SUBDIRS="$(PKG_BUILD_DIR)"
    
    define Build/Prepare          //编译前准备工作
        mkdir -p $(PKG_BUILD_DIR)
        $(CP) ./src/* $(PKG_BUILD_DIR)/
    endef
    
    define Build/Compile         //进行编译
        $(MAKE) -C "$(LINUX_DIR)" 
        $(MAKE_OPTS) modules
    endef

    $(eval $(call KernelPackage,mydrv))

    以上为驱动程序Makefile代码,驱动程序有两个Makefile,驱动文件夹里有一个(上面)以及src里也有一个Makefile

    进入src中Makefile

    我们看一下Makefile的内容,非常简单: obj-m += mydrv.o

    告诉内核添加的模块目标文件名称为mydrv.o 

    当前还包含有驱动程序

    mydrv.c

    /***************************** 
    *
    *   驱动程序模板
    *   版本:V1
    *   使用方法(末行模式下):
    *   :%s/mydrv/"你的驱动名称"/g
    *
    *******************************/
    
    
    #include <linux/mm.h>
    #include <linux/miscdevice.h>
    #include <linux/slab.h>
    #include <linux/vmalloc.h>
    #include <linux/mman.h>
    #include <linux/random.h>
    #include <linux/init.h>
    #include <linux/raw.h>
    #include <linux/tty.h>
    #include <linux/capability.h>
    #include <linux/ptrace.h>
    #include <linux/device.h>
    #include <linux/highmem.h>
    #include <linux/crash_dump.h>
    #include <linux/backing-dev.h>
    #include <linux/bootmem.h>
    #include <linux/splice.h>
    #include <linux/pfn.h>
    #include <linux/export.h>
    #include <linux/io.h>
    #include <linux/aio.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <asm/uaccess.h>
    #include <linux/ioctl.h>
    
    
    /****************  基本定义 **********************/
    //内核空间缓冲区定义
    #if 0
        #define KB_MAX_SIZE 20
        #define kbuf[KB_MAX_SIZE];
    #endif
    
    
    //加密函数参数内容: _IOW(IOW_CHAR , IOW_NUMn , IOW_TYPE)
    //加密函数用于mydrv_ioctl函数中
    //使用举例:ioctl(fd , _IOW('L',0x80,long) , 0x1);
    //#define NUMn mydrv , if you need!
    #define IOW_CHAR 'L'
    #define IOW_TYPE  long
    #define IOW_NUM1  0x80
    
    
    //初始化函数必要资源定义
    //用于初始化函数当中
    //device number;
        dev_t dev_num;
    //struct dev
        struct cdev mydrv_cdev;
    //auto "mknode /dev/mydrv c dev_num minor_num"
    struct class *mydrv_class = NULL;
    struct device *mydrv_device = NULL;
    
    
    /**************** 结构体 file_operations 成员函数 *****************/
    //open
    static int mydrv_open(struct inode *inode, struct file *file)
    {
        printk("mydrv drive open...
    ");
    
    
        return 0;
    }
    
    //close
    static int mydrv_close(struct inode *inode , struct file *file)
    {
        printk("mydrv drive close...
    ");
    
    
        return 0;
    }
    
    //read
    static ssize_t mydrv_read(struct file *file, char __user *buffer,
                size_t len, loff_t *pos)
    {
        int ret_v = 0;
        printk("mydrv drive read...
    ");
    
    
        return ret_v;
    }
    
    //write
    static ssize_t mydrv_write( struct file *file , const char __user *buffer,
                   size_t len , loff_t *offset )
    {
        int ret_v = 0;
        printk("mydrv drive write...
    ");
    
    
        return ret_v;
    }
    
    //unlocked_ioctl
    static int mydrv_ioctl (struct file *filp , unsigned int cmd , unsigned long arg)
    {
        int ret_v = 0;
        printk("mydrv drive ioctl...
    ");
    
        switch(cmd)
        {
            //常规:
            //cmd值自行进行修改
            case 0x1:
            {
                if(arg == 0x1) //第二条件;
                {
    
                }
            }
            break;
    
            //带密码保护:
            //请在"基本定义"进行必要的定义
            case _IOW(IOW_CHAR,IOW_NUM1,IOW_TYPE):
            {
                if(arg == 0x1) //第二条件
                {
                    
                }
    
            }
            break;
    
            default:
                break;
        }
    
        return ret_v;
    }
    
    
    /***************** 结构体: file_operations ************************/
    //struct
    static const struct file_operations mydrv_fops = {
        .owner   = THIS_MODULE,
        .open     = mydrv_open,
        .release = mydrv_close,    
        .read     = mydrv_read,
        .write   = mydrv_write,
        .unlocked_ioctl    = mydrv_ioctl,
    };
    
    
    /*************  functions: init , exit*******************/
    //条件值变量,用于指示资源是否正常使用
    unsigned char init_flag = 0;
    unsigned char add_code_flag = 0;
    
    //init
    static __init int mydrv_init(void)
    {
        int ret_v = 0;
        printk("mydrv drive init...
    ");
    
        //函数alloc_chrdev_region主要参数说明:
        //参数2: 次设备号
        //参数3: 创建多少个设备
        if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"mydrv") ) < 0 )
        {
            goto dev_reg_error;
        }
        init_flag = 1; //标示设备创建成功;
    
        printk("The drive info of mydrv:
    major: %d
    minor: %d
    ",
            MAJOR(dev_num),MINOR(dev_num));
    
        cdev_init(&mydrv_cdev,&mydrv_fops);
        if( (ret_v = cdev_add(&mydrv_cdev,dev_num,1)) != 0 )
        {
            goto cdev_add_error;
        }
    
        mydrv_class = class_create(THIS_MODULE,"mydrv");
        if( IS_ERR(mydrv_class) )
        {
            goto class_c_error;
        }
    
        mydrv_device = device_create(mydrv_class,NULL,dev_num,NULL,"mydrv");
        if( IS_ERR(mydrv_device) )
        {
            goto device_c_error;
        }
        printk("auto mknod success!
    ");
    
        //------------   请在此添加您的初始化程序  --------------//
           
    
    
    
            //如果需要做错误处理,请:goto mydrv_error;    
    
         add_code_flag = 1;
        //----------------------  END  ---------------------------// 
    
        goto init_success;
    
    dev_reg_error:
        printk("alloc_chrdev_region failed
    ");    
        return ret_v;
    
    cdev_add_error:
        printk("cdev_add failed
    ");
         unregister_chrdev_region(dev_num, 1);
        init_flag = 0;
        return ret_v;
    
    class_c_error:
        printk("class_create failed
    ");
        cdev_del(&mydrv_cdev);
         unregister_chrdev_region(dev_num, 1);
        init_flag = 0;
        return PTR_ERR(mydrv_class);
    
    device_c_error:
        printk("device_create failed
    ");
        cdev_del(&mydrv_cdev);
         unregister_chrdev_region(dev_num, 1);
        class_destroy(mydrv_class);
        init_flag = 0;
        return PTR_ERR(mydrv_device);
    
    //------------------ 请在此添加您的错误处理内容 ----------------//
    mydrv_error:
            
    
    
    
        add_code_flag = 0;
        return -1;
    //--------------------          END         -------------------//
        
    init_success:
        printk("mydrv init success!
    ");
        return 0;
    }
    
    //exit
    static __exit void mydrv_exit(void)
    {
        printk("mydrv drive exit...
    ");    
    
        if(add_code_flag == 1)
         {   
               //----------   请在这里释放您的程序占有的资源   ---------//
            printk("free your resources...
    ");                   
    
    
    
    
    
            printk("free finish
    ");                       
            //----------------------     END      -------------------//
        }                                
    
        if(init_flag == 1)
        {
            //释放初始化使用到的资源;
            cdev_del(&mydrv_cdev);
             unregister_chrdev_region(dev_num, 1);
            device_unregister(mydrv_device);
            class_destroy(mydrv_class);
        }
    }
    
    
    /**************** module operations**********************/
    //module loading
    module_init(mydrv_init);
    module_exit(mydrv_exit);
    
    //some infomation
    MODULE_LICENSE("GPL v2");
    MODULE_AUTHOR("from Jafy");
    MODULE_DESCRIPTION("mydrv drive");
    
    
    /*********************  The End ***************************/

    测试程序mydir_app

    Makefile

    ##Copyright (C) 2012 OpenWrt.org
    #
    # This is free software, licensed under the GNU General Public License v2.
    # See /LICENSE for more information.
    #
    
    include $(TOPDIR)/rules.mk
    
    PKG_NAME:=mydrv_app
    PKG_RELEASE:=1
    
    PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
    
    include $(INCLUDE_DIR)/package.mk
    
    define Package/mydrv_app
      SECTION:=utils
      CATEGORY:=Utilities
      TITLE:=Frame buffer device testing tool
      DEPENDS:=+libncurses
    endef
    
    define Build/Prepare
        mkdir -p $(PKG_BUILD_DIR)
        $(CP) ./src/* $(PKG_BUILD_DIR)/
    endef
    
    define Build/Configure
    endef
    
    TARGET_LDFLAGS :=
    
    define Build/Compile
        $(MAKE) -C $(PKG_BUILD_DIR) 
        CC="$(TARGET_CC)" 
        CFLAGS="$(TARGET_CFLAGS) -Wall" 
        LDFLAGS="$(TARGET_LDFLAGS)"
    endef
    
    define Package/mydrv_app/install
        $(INSTALL_DIR) $(1)/usr/sbin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/mydrv_app $(1)/usr/sbin/
    endef
    
    $(eval $(call BuildPackage,mydrv_app))

    进入src文件夹

    Makefile

    ll: mydrv_app
    OBJS = mydrv_app.o
    
    CC = gcc
    CCFLAGS = -Wall -c -o
    
    %.o: %.c
        $(CC) $(CCFLAGS) $@ $< $(LDFLAGS)
    
    fbtest: $(OBJS)
        $(CC) -o $@ $(OBJS) $(LDFLAGS)
    
    clean:
        rm -f rbcfg *.o

    测试程序代码

    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ioctl.h>
    
    int main(int argc , char** argv)
    {
        int fd;
        int num = 1;
    
        //打开驱动模块
        fd = open("/dev/mydrv" , O_RDWR|O_NONBLOCK);
        if(fd < 0)
        {
            printf("can't open /dev/mydrv
    ");
            return -1;
        }
    
        //函数测试
        write(fd,&num,1);
        read(fd,&num,1);
        ioctl(fd,1,1);
        close(fd);
        
        return 0;
    }
  • 相关阅读:
    团队冲刺0202
    团队冲刺0201
    第十五周
    第十四周博客
    十三周总结
    软件设计模式13
    软件设计模式12
    软件构造4
    软件设计模式11
    软件设计模式10
  • 原文地址:https://www.cnblogs.com/yihujiu/p/5703444.html
Copyright © 2020-2023  润新知