嵌入式学习 day57 驱动-驱动框架
一、驱动开发
1、概念:针对内核的开发
2、需要解决的问题
1).如何在一个已经运行起来的代码中执行我们的驱动代码
2).驱动代码的编写的框架是什么?
3).驱动代码最终还是完成对寄存器的操作,如何实现虚拟地址和物理地址的映射
二、内核编写驱动
1、静态加载:
(1)编写驱动 led.c
(2)编译代码
①修改Kconfig,增加一条该驱动的说明,需要增加一个关于该条驱动的宏名
②用户通过make menuconfig选择该条驱动<*>,会引引起.config中的配置的变化 宏名=y
③修改Makefile obj-$(宏名)+=led.o,驱动编译时就会加入led.c代码的编译
④代码编译->链接->压缩->zImage (包含了led驱动)
(3)通过tftp下载最新的ziImage来执行内核,此时内核中增加了led驱动
2、动态加载
(1)、编写驱动led.c
(2)编译代码
①在makefile中 obj-m+=led.o
②在内核中通过makemodules来完成对内核模块的编译
③编译成功后生成led.ko内核模块文件
(3)将内核模块拷贝到~/nfs/rootfs
(4)在开发板中(Linux系统已经启动),通过insmod命令加载内核模块,通过rmmod命令卸载内核模块
注:ctags工具追踪:
1.概念:ctags是一款用于源代码符号索引生成的工具,通过创建tags文件记录代码中函数、变量等位置信息。
2、.配置步骤:
(1) 安装ctags工具
sudo apt-get install ctags
(2)进入源码目录顶层,并生成ctags标签
cd 内核目录
ctags -R
(3) 在源码目录顶层查看并跟踪源代码
根据如下命令,搜索源文件中涉及查找内容的部分(函数、宏、定义)
vi -t "查找内容"
可以使用命令来对内容进行跟踪
ctrl + ] //跳转到定义
ctrl + o //返回原位置
三、工程搭建和代码编译
1、demo.c
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/module.h>
//驱动程序入口
int init_demo(void)
{
printk("init demo success\n");
return 0;
}
//驱动程序出口
void exit_demo(void)
{
printk("exit demo success\n");
return;
}
//设置驱动程序的入口
module_init(init_demo);
//设置驱动程序的出口
module_exit(exit_demo);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("pute");
2.Makefile
#模块名
modulename:=demo_drv
#内核路径
kerdir:=/home/linux/imx6ull/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
#当前内核模块工程路径
curdir:=$(shell pwd)
#将代码加入到内核模块编译中
obj-m+=$(modulename).o
all:
make -C $(kerdir) M=$(curdir) modules
cp $(modulename).ko ~/nfs/rootfs
.PHONY:
clean:
make -C $(kerdir) M=$(curdir) modules clean
distclean:
make -C $(kerdir) M=$(curdir) modules clean
rm ~/nfs/rootfs/$(modulename).ko
四、加载驱动
注:
污染内核:GPL协定(需要开源)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("pute");