004_Makefile的编译

一、向内核中添加驱动步骤

在向内核中添加驱动的时候要完成3 项工作,包括:

1、在Kconfig 中添加新代码对应项目的编译条件

2、将驱动源码添加到对应的目录中

3、在目录Makefile 中文件中增加针对新代码的编译条目



二、编译器路径的设置

1、打开家目录下的.bashrc文件,在其最下面添加如下内容:

export PATH=$PATH:/home/mint/itop/arm-2009q3/bin

使其生效

 .  .bashrc

2、该目录与交叉编译器的解压放置位置相对应

/home/mint/itop/arm-2009q3/bin

在这里插入图片描述

3、打开内核源码的顶层目录的Makefile文件

在195行的位置有如下内容

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH    ?= arm
CROSS_COMPILE   ?= /home/mint/itop/arm-2009q3/bin/arm-none-linux-gnueabi-
#CROSS_COMPILE   ?= /usr/local/arm/4.5.1/bin/arm-none-linux-gnueabi-
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)

该交叉编译工具链的位置与上面是一一对应的。



三、使用make zImage编译内核执行过程

在这里以BUZZER的驱动为例。

1、在make zImage命令执行之后,它会首先找到源码顶层目录下的Makefile文件,运行Makefile 文件之后,它会在Makefile 文件中找到编译器的路径,然后系统根据环境变量找到“export PATH=$PATH/home/mint/itop/arm-2009q3/bin”编译器的路径。

2、在driver/char/ 目录下,暂时关注以下三个文件

itop4412_buzzer.c  //led 驱动的源码
itop4412_buzzer.o   //生成最终zImage 二进制的中间文件
Makefile             //make执行时所需要的文件

3、打开该目录下的Makefile文件

obj-$(CONFIG_BUZZER_CTL)  += itop4412_buzzer.o

在这里插入图片描述

如果想添加类似的字符驱动,就可以在这个目录下添加。



四、Makefile 脚本语法简介

1、强制编译进内核

obj-y       += misc.o

在这里插入图片描述

2、条件编译

obj-$(CONFIG_BUZZER_CTL)  += itop4412_buzzer.o

需要在Kconfig 中定义,在menuconfig中配置之后,编译器运行的时候找到对应的宏变量CONFIG_BUZZER_CTL之后才会编译。

3、Makefile的层层调用

打开driver/下的Makefile文件,在第33行中

obj-y               += char/

“加等号”右边有文件变为了文件夹。这里表示强制编译当前目录“/drivers”的下一级目录“/char”。在执行编译命令执行到这一句的时候,就会先跳转到“/char”目录下的“Makefile”文件。

在这里插入图片描述



五、Makefile 的测试

目标:通过配置menuconfig 中的SKYFALL,来将内核编译进内核或者不编译进内核。

实现步骤:

(1) 在源码目录下的driver/char目录下编写itop4412_skyfall.c源文件,文件内容如下。最后在/dev下显示的设备节点的名字为skyfall_007。

#include <linux/init.h>
#include <linux/module.h>
/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include <linux/platform_device.h>
/*注册杂项设备头文件*/
#include <linux/miscdevice.h>
/*注册设备节点的文件结构体*/
#include <linux/fs.h>

#define DRIVER_NAME "skyfall"
#define DEVICE_NAME "skyfall_007"
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("SKYFALL");

//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
//驱动实际操作的实现
static long skyfall_ioctl( struct file *file, unsigned int cmd, unsigned long arg){

    printk("%s,%d\n",__func__,__LINE__);

    printk("cmd is %d,arg is %d\n",cmd,arg);
    
    return 0;
}

//int (*release) (struct inode *, struct file *);
//关闭该驱动的实现
static int skyfall_release(struct inode *inode, struct file *file){
    printk("%s,%d\n",__func__,__LINE__);

    printk(KERN_EMERG "skyfall release\n");

    return 0;
}

//int (*open) (struct inode *, struct file *);
//打开该驱动的实现
static int skyfall_open(struct inode *inode, struct file *file){
    printk("%s,%d\n",__func__,__LINE__);

    printk(KERN_EMERG "skyfall open\n");

    return 0;
}

//定义一个字符设备操作集合
static struct file_operations skyfall_ops = {
    .owner           = THIS_MODULE,
    .open            = skyfall_open,
    .release         = skyfall_release,
    .unlocked_ioctl  = skyfall_ioctl,
};

//定义一个杂项设备结构体
static  struct miscdevice skyfall_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name  = DEVICE_NAME,
    //字符设备操作集合,需要提前定义一个,然后取地址
    .fops = &skyfall_ops,
};


static int skyfall_probe(struct platform_device *pdv){
    
    printk(KERN_EMERG "initialized\n");
    printk("%s,%d\n",__func__,__LINE__);
    
    //注册杂项设备,需要一个传一个杂项设备的结构体,所以需要提前定义一个,然后取地址
    misc_register(&skyfall_dev);
    
    return 0;
}

static int skyfall_remove(struct platform_device *pdv){
    
    printk(KERN_EMERG "\tremove\n");
    //注销杂项设备
    misc_deregister(&skyfall_dev);
    return 0;
}

static void skyfall_shutdown(struct platform_device *pdv){
    
    ;
}

static int skyfall_suspend(struct platform_device *pdv,pm_message_t pmt){
    
    return 0;
}

static int skyfall_resume(struct platform_device *pdv){
    
    return 0;
}

struct platform_driver skyfall_driver = {
    .probe      = skyfall_probe,
    .remove     = skyfall_remove,
    .shutdown   = skyfall_shutdown,
    .suspend    = skyfall_suspend,
    .resume     = skyfall_resume,
    .driver     = {
                    .name = DRIVER_NAME,
                    .owner = THIS_MODULE,
    }
};


static int __init skyfall_init(void)
{
    int DriverState;//定义驱动状态,判断驱动是否注册成功
    
    printk(KERN_EMERG "skyfall driver enter!\n");
    printk("%s,%d\n",__func__,__LINE__);
    DriverState = platform_driver_register(&skyfall_driver);
    /*
    驱动一旦注册成功,会与设备进行匹配,匹配成功是由
    platform_match函数进行匹配,驱动调用probe初始化函数
    */
    
    printk(KERN_EMERG "DriverState = %d\n",DriverState);
    
    return 0;
}


static void __exit skyfall_exit(void)
{
    printk(KERN_EMERG "skyfall driver exit!\n");
    
    platform_driver_unregister(&skyfall_driver);    
}

module_init(skyfall_init);
module_exit(skyfall_exit);

以上这些需要配合后面的注册设备与注册驱动相结合。

(2)打开源码目录下的driver/char目录下Makefile文件,添加编译选项

obj-$(CONFIG_SKYFALL_CTL) += itop4412_skyfall.o

在这里插入图片描述

(3)打开源码目录下的driver/char目录下Kconfig文件,添加菜单选项

config SKYFALL_CTL
        bool "Enable SKYFALL config"
        default y
        help
          Enable SKYFALL config!

在这里插入图片描述

(4)打开menuconfig界面,将Device Drivers —> Character devices—> [] Enable SKYFALL config (NEW) 添加 。

在这里插入图片描述
添加完毕后,保存,生成新的.config文件。

(5)查看.config文件

CONFIG_SKYFALL_CTL=y

在这里插入图片描述

(6)编译内核 sudo make zImage,查看有没有生成itop4412_skyfall.o中间文件

在这里插入图片描述

编译内核

在这里插入图片描述
在这里插入图片描述

(7)将新生成的内核烧写至开发板中

cp arch/arm/boot/zImage /mnt/share/

(8)在开发板的/dev目录中产生itop4412_skyfall.c 驱动的设备节点skyfall_007。在源码的driver/char目录下,生成了对应的中间文件。

在这里插入图片描述

(9)以上是生成skyfall设备节点的步骤。
在这里插入图片描述

(10)打开menuconfig界面,将Device Drivers —> Character devices—> [ ] Enable SKYFALL config 去掉 。

在这里插入图片描述

保存并退出,生成新的.config文件。

(11)打开.config文件,发现配置成功。

# CONFIG_SKYFALL_CTL is not set

在这里插入图片描述

(12)再次编译内核,发现没有中间文件itop4412_skyfall.o生成。

sudo make zImage

在这里插入图片描述

(13)将新生成的内核烧写至开发板中

cp arch/arm/boot/zImage /mnt/share/

(14)在开发板的/dev目录中没有产生itop4412_skyfall.c 驱动的设备节点skyfall_007。

在这里插入图片描述
在这里插入图片描述
(15)至此,整个过程全部完成。



六、内核编译的全部过程

在这里插入图片描述

1、红色的线条表示配置文件Kconfig 这一部分,在Kconfig 中要定义针对具体驱动文件的宏变量。然后使用menuconfig 工具生成新的.config文件。

2、黑色的线条表示编译文件Makefile 这一部分,在Makefile 中针对宏变量编译驱动文件。

3、执行make 命令之后,调用.config文件,配合各级目录中的Makefile 文件编译具体的驱动源代码,将源代码编译成.o中间文件。

4、当中间文件全部编译完成之后,编译工具会生成一个非常精炼的zImage二进制文件。




版权声明:本文为zxy131072原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。