第八章
本章的学习是蜂鸣器,蜂鸣器是S3C6410自带的一个硬件设备。通过像寄存器写入特定的值控制蜂鸣器发出尖叫,其实现原理以及完整实现一个蜂鸣器驱动。
驱动安装失败的解决方法,在本章的前言中首先提到,在遇到无法卸载Linux驱动时通过直接修改linux驱动相应的内存地址,删除Linux驱动。
1.一些代码重用的方法
编译由多个文件组成的Linux驱动,在main.c文件会有两个宏(_init)(_exit),在以前程序中没有用过,用来标识Linux驱动初始化函数和驱动卸载函数,来提高运行效率。在product.c
文件中有extern关键字,其作用是告诉编译器该函数的函数名、参数个数、参数类型和返回值类型。当驱动包含多个文件时需要module-y或者module-objs来指定所有的目标文件。代码重用分为静态和动态,本节使用第二种模块依赖也称为导出符号,也就是在一个驱动模块里使用另一个驱动模块里被导出的符号。
2.先安装symbol_producer,再接着安装symbol_consumer,卸载时顺序正好相反。两者是依赖关系。modprobe命令会根据depmod命令生成linux模块依赖关系来装载linux模块。不需要像insmod命令那样挨个装载。
3.强行卸载linux驱动
当程序出现异常时,就不能正常卸载和装载,需要强行卸载。
(1)初始化函数崩溃
将当前linux驱动模块的引用计数器清零,修改引用寄存器用到的函数
Static inline int try_module_get(struct module *module)
Extern void module_put(struct module *module)
(2)卸载函数被阻塞
将原来的函数替换成一个空的卸载函数即可
但是以上两种情况都需要获取表示要卸载的linux驱动模块的module结构体指针。因为struct module表示了linux驱动的相关信息。从/proc/kallsyms文件中查找系统分配给要卸载的linux驱动的module 结构体的首地址,然后将首地址强行转换成module结构体指针。执行
cat /proc/kallsyms | grep _this_module | grep bad_driver1
来获取描述bad_driver1驱动的module 结构体首地址。
但是大多数情况下人工操作太复杂,万一差错,会导致修改不了不该修改的内存数据,很有可能造成内核崩溃。为了避免这种情况,特意编写一个脚本文件(build.sh)来自动查找。
4.寄存器来控制蜂鸣器
基本原理是通过脉冲来控制蜂鸣器的打开和停止,通过I/O命令可以打开和停止PWM(脉冲宽度调制)。有三个文件pwm.c驱动主程序、pwm_fun.h引用了相应的头文件,定义一些宏、pwm_fun.c包含打开和停止PWM的两个函数。
http://www.cnblogs.com/xxyue/