[1] Course outline
1. Linux kernel module
2. Character device driver
3. Concurrency and race conditions solution
4. IO model
5. Linux kernel interrupt
6. Platform bus driver
7. i2c bus driver
8. spi bus driver
9. Block device driver
10. Network card device driver
[2]
Linux device driver development at work,
Android device driver development
[3] What is a driver? What is the difference between arm bare metal driver and Linux device driver?
Drive: Drive hardware to work through software code
in common:
can drive hardware work
different points:
ARM bare metal drive: a code that can only be performed, in accordance with the order in the main
to the order of execution, this code can execute alone, does not depend on that
his code.
Linux设备驱动:它是基于Linux内核才能够操作硬件,
如果没有Linux内核,驱动不能单独执行,也不能自动
执行(必须通过应用层控制才能执行)。可以同时安装
多个Linux设备驱动
[4] Linux system level
Application layer: [0-3G]
APP glibc
---------------(system call swi)-------------- ----------------
Kernel layer: 5 major functions [3-4G]
File management: Organize and
manage files through the file system ext2 ext3 ext4 yaffs jiffe, etc.
Memory management: through memory (slab ) Management unit to allocate and release memory.
Process management: It manages the creation, destruction, process scheduling and other functions of the process.
Network management: The network data is sent and received through the network protocol stack.
Device management: Device driver management.
Character device driver: Access according to byte stream and in sequence Visited.
Block device driver: access in blocks (512 bytes), which can be accessed sequentially
or out of order.
Network card device driver: There is no device file in the network card device driver.
(Network data transmission through this device)
Hardware layer: LED CAMERA LCD TOUCHSCREEN
sound card graphics card BEEP USB mouse U disk hard disk
FLASH switch router cat network card, etc.
[5] Linux device driver use
demo.c <==== character device driver
Kconfig :生成选项菜单的文件
/home/linux/kernel/kernel-3.4.39/drivers/char
config FARSIGHT_DEMO (选项名)
tristate "test test test ..." (选项菜单名)
help
this is a driver demo
.config :保存选配号的选项
CONFIG_FARSIGHT_DEMO=y
CONFIG_FARSIGHT_DEMO=m
#CONFIG_FARSIGHT_DEMO is not set
Makefile :用来编译驱动模块的
obj-$(CONFIG_FARSIGHT_DEMO) += demo.o
obj-y +=demo.o
obj-m +=demo.o
编译:
y:
make uImage ===>将驱动编译到uImage中
m:
make modules ===>将驱动编译生成xxx.ko文件
[6] Linux kernel module
模块三要素:内核模块不能单独执行,也不能自动自行
入口
static int __init demo_init(void)
{
return 0;
}
module_init(demo_init);
出口
static void __exit demo_exit(void)
{
}
module_exit(demo_exit);
许可证
MODULE_LICENSE("GPL");
内部编译:在内核源码树中编译
外部编译:在内核源码树外进行编译
Makefile:
KERNELDIR:= /lib/modules/$(shell uname -r)/build/
//这是Makefile中的一个变量,记录ubuntu内核的路径的
//$(shell 命令) 在Makefile中起一个终端,执行命令,将
//将命令执行的结果作为返回值
PWD:=$(shell pwd)
//PWD它是记录驱动所在目录的一个变量。
all:
//all是make执行的时候的默认的标签,
//这个all的名字也可以随意指定(如modules)
make -C $(KERNELDIR) M=$(PWD) modules
//make -C dir 进入到dir目录下执行它里面的Makefile文件
//M 它是记录程序当前路径的一个变量
//make modules 编译模块,只编译M指定的目录下的模块
clean:
make -C $(KERNELDIR) M=$(PWD) clean
//make -C dir 进入到dir目录下执行它里面的Makefile文件
//M= 它是记录程序当前路径的一个变量
//make clean 清除编译,只清除M指定的目录下的模块文件
obj-m:=demo.o
//指定的要编译的模块的名字
Makefile中四种赋值的区别?
=
查找Makefile中变量最后一次被赋值
的结果,然后将它赋值给新的变量
var1=abc
var2=$(var1)
var1=def
all:
@echo $(var1) #def
@echo $(var2) #def
:= 立即赋值
var1=abc
var2:=$(var1)
var1=def
all:
@echo $(var1) #def
@echo $(var2) #abc
+= 附加赋值
var1=abc
var2=def
var2+=$(var1)
all:
@echo $(var1) #abc
@echo $(var2) #def abc
?= 询问赋值:询问变量之前是否被赋值过,
如果变量之前没有被赋值过本次赋值成立,
否则本次赋值不成立
var1?=def
all:
@echo $(var1) #def
var1=abc
var1?=def
all:
@echo $(var1) #abc
[7] Commands for driver installation and uninstallation
sudo insmod xxx.ko Install driver
lsmod Check whether the module is installed
sudo rmmod xxx Uninstall driver
modinfo xxx.ko Command to check various information in the module
dmesg Check the message printed by printk
sudo dmesg- c First display it on the terminal, and then clear the message
sudo dmesg -C directly clear the message
[8] Kernel printing function
printk (print level "control format", variable);
printk("control format", variable); //
The eight print levels of the default kernel are used as follows, the smaller the number, the higher the priority .
#define KERN_EMERG “<0>”
/* system is unusable /
#define KERN_ALERT “<1>”
/ action must be taken immediately /
#define KERN_CRIT “<2>”
/ critical conditions /
#define KERN_ERR “<3>”
/ error conditions /
#define KERN_WARNING “<4>”
/ warning conditions /
#define KERN_NOTICE “<5>”
/ normal but significant condition /
#define KERN_INFO “<6>”
/ informational /
#define KERN_DEBUG “<7>”
/ debug-level messages */
打印级别问题:
proc/sys/kernel$ ls printk
cat /proc/sys/kernel/printk
4 4 1 7
终端的级别 消息的默认级别 终端的最大级别 终端的最小级别
只有当消息的级别大于终端的级别的
时候,消息才会显示。
由于ubuntu的终端已经被开发者修改过了,所以
即使消息的级别大于控制台的级别,消息依然不会
显示,使用虚拟控制台才执行代码
ctrl +alt +[F1-F6] 进入虚拟终端
ctrl +alt + F7 退出虚拟终端
修改默认级别的办法:
su root
echo 4 3 1 7 > /proc/sys/kernel/printk
[9] Kernel module parameter transfer problem.
When developing at work, when purchasing screen hardware, we provide you with the
screen driver (xxx.ko). For example, you can modify
the default maximum size of the screen through command line parameter transfer . brightness.
Standard types are:
byte, short, ushort, int, uint, long, ulong 注意:没有char类型!!
charp: a character pointer
bool: a bool, values 0/1, y/n, Y/N.
invbool: the above, only sense-reversed (N = true).
module_param(name, type, perm)
功能:接收命令行传的参数
参数:
@name:变量名
@type: 变量的类型
@perm: 权限 0664 0775
MODULE_PARM_DESC(_parm, desc)
功能:对命令行传递的参数进行描述
参数:
@_parm:变量
@desc:描述的字符串
安装驱动的时候传参:
sudo insmod demo.ko light=80
在运行的使用传参
/sys/module/驱动命名的目录/parameters/
以变量命名的文件
su root
echo 70 > light