前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux驱动开发入门 demo

Linux驱动开发入门 demo

作者头像
嘘、小点声
发布2020-10-27 17:34:18
4.1K0
发布2020-10-27 17:34:18
举报
文章被收录于专栏:嘘、小点声嘘、小点声

驱动开发时候,尽量选择对应操作系统内核的Linux系统作为上位机平台

下载源码与编译

源码的下载可以从网站:https://mirrors.edge.kernel.org/pub/linux/kernel/

找到对应的内核版本,然后下载,通过make menuconfig和make,进行编译。

没有编译过的内核,驱动开发过程中进行编译可能有错误,找不到文件等。

编写一个最简单的驱动

如下是hello.c文件的驱动程序。其中声明了证书,和模块加载后与退出时应该执行的函数。

代码语言:javascript
复制
#include<linux/module.h>
#include<linux/kernel.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
        printk(KERN_ALERT "hello,world\n");
        return 0;
}
static void hello_exit(void)
{
        printk(KERN_ALERT "goodbye,world\n");
}
module_init(hello_init);
module_exit(hello_exit);

编写Makefile文件

Makefile文件的编写如下,主要是KERNELDIR,为linux源码的位置

代码语言:javascript
复制
ifeq ($(KERNELRELEASE),)
        KERNELDIR ?= /usr/src/linux-source-5.4.0
        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
else
        obj-m := hello.o
endif

修改部分信息和执行

当编译的内核为系统本身的内核,但是make以后生成的ko文件无法加载,即通过insmod xxx.ko无法加载,格式不对

查看dmesg信息,参考解决:https://www.cnblogs.com/blfbuaa/p/6907027.html

正常执行后再dmesg中会有相应的加载和卸载模块的message信息。卸载命令为rmmod xxx

模块之间的依赖通信

以下为add_sub.c

代码语言:javascript
复制
#include<linux/kernel.h>
#include<linux/module.h>
#include"add_sub.h"
long add_integer(long a,long b)
{
        printk(KERN_ALERT "add init");
        return a+b;
}
long sub_integer(long a,long b)
{
        printk(KERN_ALERT "sub init");
        return a-b;
}
EXPORT_SYMBOL(add_integer);
EXPORT_SYMBOL(sub_integer);
MODULE_LICENSE("Dual BSD/GPL");

以下为add_sub.h

代码语言:javascript
复制
#ifndef _ADD_SUB_H_
#define _ADD_SUB_H_
long add_integer(long a,long b);
long sub_integer(long a,long b);
#endif

以下为Makefile,当执行完make后,则生成了符号表文件,其为Module.symvers,该文件可以用于其他文件的函数引用

代码语言:javascript
复制
ifeq ($(KERNELRELEASE),)
        KERNELDIR ?= /usr/src/linux-source-5.4.0
        PWD := $(shell pwd)
        PRINT_INC =$(PWD)/../include
        EXTRA_CFLAGS += -I $(PRINT_INC)
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
else
        obj-m := add_sub.o
endif

以下为test.c

代码语言:javascript
复制
#include<linux/kernel.h>
#include<linux/module.h>
#include"../add_sub.h"
static long a = 1;
static long b = 1;
static int AddOrSub = 1;
static int test_init(void)
{
        long result = 0;
        printk(KERN_ALERT "test init\n");
        if (1 == AddOrSub)
        {
                result = add_integer(a,b);
        }
        else
        {
                result = sub_integer(a,b);
        }
        //printk(KERN_ALERT, "the %s result is %ld", AddOrSub==1?"Add":"Sub",result);
        return 0;
}
static void test_exit(void)
{
        printk(KERN_ALERT, "test_exit");
}
module_init(test_init);
module_exit(test_exit);
module_param(a,long,S_IRUGO);
module_param(b,long,S_IRUGO);
module_param(AddOrSub,int,S_IRUGO);
MODULE_LICENSE("Dual BSD/GPL");

以下为test.c的Makefile

代码语言:javascript
复制
ifeq ($(KERNELRELEASE),)
        KERNELDIR ?= /usr/src/linux-source-5.4.0
        PWD := $(shell pwd)
KBUILD_EXTRA_SYMBOLS=$(obj)/../print/Module.symvers
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
else
        obj-m := test.o
endif

编译完后,需要先挂载add_sub模块,然后再挂载test模块。

未得到预期的效果,主要是在顺次加载后,并在加载过程添加a,b等参数,无法从dmesg中获得一个调用输出

将模块编译到内核中

如在drivers下建立add_sub_Kconfig文件夹,然后放入对应的源码文件,对应的Makefile和Kconfig文件。其中Kconfig文件用于make menuconfig的索引,其和上层的Kconfig关联

Makefile文件内容如下:

代码语言:javascript
复制
obj-$(CONFIG_ADD_SUB)+=add_sub.o
obj-$(CONFIG_TEST)+=test.o

Kconfig文件内容如下:

代码语言:javascript
复制
#
# add_sub configuration
#

menu "ADD_SUB"
        comment "ADD_SUB"
config CONFIG_ADD_SUB
        tristate "ADD_SUB support"
        default y

config CONFIG_TEST
        tristate "ADD_SUB test support"
        depends on CONFIG_ADD_SUB
        default y
endmenu

然后修改上层的Kconfig文件,添加如下内容:

代码语言:javascript
复制
Source "drivers/add_sub_Kconfig/Kconfig"

然后修改上层的Makefile文件,添加如下内容:

代码语言:javascript
复制
obj-$(ADD_SUB)                  += add_sub_Kconfig/

就可以在主目录下执行make menuconfig后,在驱动下找到对应的驱动和编译信息了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 下载源码与编译
  • 编写一个最简单的驱动
  • 编写Makefile文件
  • 修改部分信息和执行
  • 模块之间的依赖通信
  • 将模块编译到内核中
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档