注: 接触Linux驱动开发已有一段时间,但是一直感觉只是在驱动开发的门外徘徊。随着项目开发的需要,以及阅读了一些驱动开发和内核的资料,慢慢地有了一些体会。藉此机会,想把一些基本的知识和体会整理。
主要参考了以下的一些资料:
1,宋宝华老师: 《Linux设备驱动开发详解》
2,《Linux内核设计与实现》----Robert Love
3,tekkman.cublog.cn -------------Linux设备驱动程序学习:http://blog.chinaunix.net/u1/34474/showart_404278.html
一,基本驱动知识介绍 :
1. Linux 设备的分类:
# 字符设备 ---指须以串行顺序依次访问设备;
# 块设备 ---指以块为单位,可以是任意的顺序访问设备;
# 网络设备 ---兼 字符设备 和 块设备。
2, 在linux中添加一个新的驱动程序,一般需要以下的三个步骤
1) 添加驱动程序的源程序;
2) 增加配置文件 :Kconfig ----用于 make menuconfig 配置;
3) 增加Makefile编译选项 : 用于设置驱动程序的编译选项。
二,GNU C ---- 编写Linux驱动使用的C语言 。
注: Linux 上常用的编译器是GCC 编译器,GNU C 对标准 ANSI C 做了一些扩展,下面就一些特殊用法进行介绍:
1. 可变参数的宏:
在 GNU C,宏可以接受不指定个数的参数数目,如:
#define pr_debug(fmt, arg...) /
printk(fmt, ##arg)
即arg 的个数不是指定的,如: pr_debug("%s/t%d", string, i) 等价于: printk("%s/t%d", string, i)
2. Linux 2.6 的结构体一般采用标准C的格式 :
static struct wm8350_audio_platform_data imx_3stack_wm8350_setup = {
.vmid_discharge_msecs = 1000,
.drain_msecs =30,
.cap_dischasrge_msecs = 700,
.vmid_charge_msecs = 700,
.vmid_s_curve = WM8350_S_CURVE_SLOW,
.....
};
3, 当前函数名:
在GNU C中预定义了两个标识符用于保存当前函数名, __FUNCTION__ 保存函数在源码中名字, __PRETTY_FUNCTION__保存带有语言特色的名字, 在C中,改两名字是等价的。
因此常用来在调试时用: printk(KERN_INFO " the current function is %s/n", __FUNCTION__);
4, 特殊属性说明 :
5,do { } while(0)
主要用于 宏定义,表示该定义至少被执行一次。 之所以使用 do { } while(0), 是为了保证该括号的内容不被在宏展开时出现错误,例如:
#define SAFE_FREE(p) do { free(p); p = NULL; }while(0);
若在如下代码中:
if ( NULL != p)
SAFT_FREE(p);
else
........
分析: 假若无do{ } while(0) ---直接展开,则是:
if ( NULL != p )
free(p); p = NULL; ---------因此编译错误;
else
......
6. 补充: 关于goto的使用: Linux内核中 goto使用的地方主要是出错时跳到出错处理:
if error
goto erro_fun;
三, 驱动程序学习的内容;
1. 驱动程序入门介绍;
2. Linux内核模块和Linux fs 与 sysfs;
3. 字符设备驱动,介绍 LED 例子与完整的编写Linux驱动的
4. 并发处理的几种方式,介绍Linux驱动开发中常用的几种并发处理方式,
5. 阻塞与异步;
6. 中断,分析一个中断实例,并结合Linux内核分析Linux中断的过程和处理方法;
7. 时钟,定时器与延迟;结合实例分析如何使用定时器来实现延迟;
8. 内存
9. 杂设备(miscellaneous device) 开发----Watch Dog 实例;
10. Linux 块设备 --- mmc分析与 U盘驱动;
11. I2C 设备分析: wm8350 或者 G-sensor 分析;
12. Linux音频设备分析 : ALSA 实例分析;
13. LCD 设备;
14. USB设备;
15、Net device : FEC
网友评论