嵌入式linux-嵌入式内核及驱动开发,驱动模块开发,驱动代码,Makefil编写,insmod,lsmod,rmmo,模块ko参数传递,ko模块符号导出

1,驱动模块开发

驱动代码需要有四个部分
	1.头文件
	2.驱动模块装载和卸载函数入口声明
	3.实现模块装载和卸载函数入口
	4.GPL声明

1.1,编辑驱动代码hell.c

在Ubuntu下Samba共享文件夹中组织自己的目录结构

linux@linux:~/share$ mkdir my_driver
linux@linux:~/share$ cd my_driver/
linux@linux:~/share/my_driver$ mkdir 1_driver
linux@linux:~/share/my_driver$ cd 1_driver/
linux@linux:~/share/my_driver/1_driver$ mkdir hello_drv
linux@linux:~/share/my_driver/1_driver$ cd hello_drv/
linux@linux:~/share/my_driver/1_driver/hello_drv$ touch hello.c
linux@linux:~/share/my_driver/1_driver/hello_drv$ ls
hello.c

在Windows下将Samba共享文件夹中的驱动程序拖到source insight中编辑

在这里插入图片描述

1.1.1,例—驱动代码hello.c

/*
驱动代码需要有四个部分
		1.头文件
		2.驱动模块装载和卸载函数入口声明
		3.实现模块装载和卸载函数入口
		4.GPL声明
*/

//头文件
#include <linux/init.h>
#include <linux/module.h>

//实现模块装载和卸载函数入口
static int __init hello_drv_init(void)   
{
	//向系统申请资源
	printk("-----------%s-------------\n",__FUNCTION__);

	return 0;
}

static void __exit hello_drv_exit(void)
{
	//释放资源
	printk("-----------%s-------------\n",__FUNCTION__);

}

//驱动模块装载和卸载函数入口声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);

//GPL声明
MODULE_LICENSE("GPL");

在这里插入图片描述

1.2,编写Makefile

  1. Mkaefile会被读两次
  2. 第一次是make的时候,这时候主要读取的路径
  3. 第二次是内核源码变异的时候,这时候,内核源码要知道要把该路径下哪个文件编译成ko

1.2.1,例—Makefile

ROOTFS_DIR = /nfs/rootfs#根文件系统路径

ifeq ($(KERNELRELEASE),)

KERNEL_DIR = /home/linux/linux-3.14.79  		#编译过的内核源码的路径
CPU_DIR = $(shell pwd) 	#当前路径

all:
	make -C $(KERNEL_DIR) M=$(CPU_DIR) modules  #把当前路径编成modules
	@#make -C 进入到内核路径
	@#M 指定当前路径(模块位置)

clean:
	make -C $(KERNEL_DIR) M=$(CPU_DIR) clean

install:
	sudo cp -raf *.ko $(ROOTFS_DIR)/drv_module 	#把当前的所有.ko文件考到根文件系统的drv_module目录

else

obj-m += hello.o    #指定内核要把哪个文件编译成ko

endif

1.3,insmod 加载ko模块

在这里插入图片描述

1.4,lsmod 查看系统中装载了哪些模块

在这里插入图片描述

1.5,rmmod 卸载ko模块

在这里插入图片描述
注意:卸载时是驱动名,不加后缀.ko

2,模块ko参数传递

  1. 加载模块时insmod hello.ko myname="xinyuan" myvalue=33参数会传递给模块内部
  2. 用途:
 	 wifi驱动:   wifi硬件中内部也运行内部代码,原厂开发,这些代码叫做固件--firmware.bin
		装载wifi驱动,必须告诉固件文件在哪里
			 insmod  rtxxx.ko path=/lib/modules/firmware/xxx.bin
  1. 在代码如何处理参数:
	module_param(name, type, perm)
	参数1:表示参数到名字,比如myname, myvalue
	参数2:参数到类型, charp, int
	参数3: /sys/modules/表示文件到权限: 0666
  1. 用法:
	module_param(myvalue, int, 0666);
	module_param(myname, charp, S_IRUGO|S_IWUGO|S_IXUGO);

传参(当驱动内部已经定义了参数后,优先使用外部传入的参数)

在这里插入图片描述

3,ko模块的符号导出

3.1,新建math.c

#include <linux/init.h>
#include <linux/module.h>

//不需要模块加载和卸载的入口申明,直接定义好一些封装的函数

int my_add(int a,int b)
{
	return a+b;
}
EXPORT_SYMBOL(my_add);

int my_sub(int a,int b)
{
	return a-b;
}
EXPORT_SYMBOL(my_sub);

MODULE_LICENSE("GPL");

3.2,新建math.h

#ifndef __MATH_H__
#define __MATH_H__

int my_add(int a,int b);
int my_sub(int a,int b);

#endif

3.3,修改Makefile

在这里插入图片描述

3.4,hello.c

/*
驱动代码需要有四个部分
		1.头文件
		2.驱动模块装载和卸载函数入口声明
		3.实现模块装载和卸载函数入口
		4.GPL声明
*/

//头文件
#include <linux/init.h>
#include <linux/module.h>
#include "math.h"

static int myvalue = 56;
static char *myname = "xinyuan";

//实现模块装载和卸载函数入口
static int __init hello_drv_init(void)   
{
	//向系统申请资源
	printk("-----------%s-------------\n",__FUNCTION__);
	printk("name = %s, value = %d\n",myname,myvalue);


	printk("a+b = %d, a-b = %d\n",my_add(33,22),my_sub(44,12));

	return 0;
}

static void __exit hello_drv_exit(void)
{
	//释放资源
	printk("-----------%s-------------\n",__FUNCTION__);

}


//驱动模块装载和卸载函数入口声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);

//GPL声明
MODULE_LICENSE("GPL");

//传参(当驱动内部已经定义了参数后,优先使用外部传入的参数)
module_param(myvalue,int,0644);
module_param(myname,charp,S_IRUGO|S_IWUSR);

3.5,调用模块符号

在这里插入图片描述
hello.ko里面调用了math.ko中的符号,所以要先加载math.ko
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值