Linux驱动入门学习1/11(共11篇)

1. Linux设备驱动课程大纲

  1. Linux内核模块
  2. 字符设备驱动
  3. Linux内核中并发和竞态的解决办法
  4. IO模型(阻塞、非阻塞、IO多路复用、信号驱动IO)
  5. 设备树(语法、如何编写设备树)
  6. GPIO子系统
  7. 中断子系统
  8. 内核定时器
  9. platform平台驱动
  10. i2c总线驱动
  11. spi总线驱动
  12. 块设备驱动
  13. 摄像头驱动

2. 驱动的层次种类

应用层:APP glibc 0-3G内存空间
内核层:文件 内存 网络 进程 设备管理 3-4G内存空间
内核层到硬件层:字符设备驱动、块设备驱动、网络设备驱动
硬件层:鼠标 键盘 屏幕 硬盘 LED emmc

字符设备驱动:按照字节流访问,只能顺序访问,不能无序访问
块设备驱动:按照block(512kB)访问,可以顺序访问也可以无序访问
网络设备驱动:没有设备节点,完成网络协议栈向硬件上的数据收发功能的代码

3. Linux内核模块

3.1 内核模块三要素

  1. 入口
    在驱动的入口函数中完成资源的分配工作,在安装驱动的时候入口函数执行
  2. 出口
  3. 在驱动的出口函数中完成资源的释放工作,在卸载驱动的时候出口函数执行
  4. 许可证
    内核模块必须遵从GPL开源协议

3.2 内核模块代码实列

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

// 入口
// static:限定作用域,只在当前文件可以使用
// int:函数的返回值类型
// __init: #define __init __section(".init.text")
// 告诉编译器将驱动的入口函数放在.init.text段中
// 在linux内核启动的时候从这个段中找到驱动,回调驱动的入口函数
// demo_init:入口函数的名字,习惯上:led_init,adc_init,uart_init...
// (void):没有参数
static int __init demo_init(void)
{
    return 0;
}
// 出口
// static:限定作用域,只在当前文件可以使用
// void:函数的返回值类型
// __exit: #define __init __section(".exit.text")
// 告诉编译器将驱动的出口函数放在.exit.text段中
// demo_exit:入口函数的名字,习惯上:led_exit,adc_exit,uart_exit...
// (void):没有参数
static void __exit demo_exit(void)
{
}
module_init(demo_init); // 告诉内核入口函数
module_exit(demo_exit); // 告诉内核出口函数
MODULE_LICENSE("GPL"); // 许可证,开源协议

3.3 内核模块的编译

内部编译(产品阶段)

  1. 把驱动代码拷贝到内核源代码目录下
linux@ubuntu:~/linux-5.10.61/drivers/char$ cp ~/work/day1/01demo/demo.c .
  1. 修改Kconfig文件
    Kconfig文件:生成make menuconfig的选项菜单的文件
472 config DEMO
473     tristate "this is demo list"
474     help                                                                        
475         this is demo to test intel compile 
  1. 执行make menukonfig选配选项
    选项菜单

Y:将驱动编译到uImage,当内核启动的时候就会执行驱动的入口函数
M:将驱动进行模块化编译,生成一个xxx.ko文件,执行安装命令驱动入口才会被执行
N:不编译

  1. 将上述的配置信息保存到.config文件中
2148 CONFIG_DEMO=m 
  1. 在Makefile中添加编译选项

在linux-5.10.61/drivers/char/Makefile中添加如下选项

obj-$(CONFIG_DEMO) +=demo.o

经过变量的替换obj-$(CONFIG_DEMO) 就变成了obj-m +=demo.o

  1. 编译驱动

make uImage LOADADDR=0xc2000000 编译内核
将obj-y后面的文件都编译到uImage这个内核文件中
make modules 模块化编译
将obj-m后的文件单独编译成xxx.ko模块

外部编译(开发阶段)

  1. 外部编译:驱动代码放在linux内核目录之外进行编译
    自己编写Makefile文件
KERNELDIR:= /home/linux/linux-5.10.61 #开发板内核路径
PWD:= $(shell pwd) #当前路径

.PHONY:all
all:
 make -C $(KERNELDIR) M=$(PWD)  modules
 @#make -C $(KERNELDIR)切换路径到内核顶层目录下,
 @#读取顶层Makefile文件,对着它执行make  M=$(PWD)  modules
 @#make M=$(PWD) modules对当前目录下的驱动进行模块化编译
 
.PHONY:clean
clean:
 make -C $(KERNELDIR) M=$(PWD)  clean
 @#make -C $(KERNELDIR)切换路径到内核顶层目录下,
 @#读取顶层Makefile文件,对着它执行make  M=$(PWD)  clean
 @#make M=$(PWD) clean清除当前目录编译生成的文件 

obj-m:=demo.o #指定编译的模块

  1. 通用的Makefile
    make arch=arm modname=hello
    make arch=x86 modname=hello
arch?=x86
modname?=demo
ifeq ($(arch),arm)
 KERNELDIR:= /home/linux/linux-5.10.61 
else
 KERNELDIR:= /lib/modules/$(shell uname -r)/build/
endif
PWD:= $(shell pwd) #当前路径

.PHONY:all
all:
 make -C $(KERNELDIR) M=$(PWD)  modules

.PHONY:clean
clean:
 make -C $(KERNELDIR) M=$(PWD)  clean

obj-m:=$(modname).o #指定编译的模块

3.4 模块相关命令

sudo insmod demo.ko 安装模块

lsmod 查看模块

sudo rmmod demo 卸载模块

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值