一.设备驱动的作用:
1 计算机系统里面的软件和硬件是互相成就的,没有软件的硬件是废铁,没有硬件作为依托的软件是空中楼阁。
2 当应用软件工程师不想了解硬件底层的具体操作的时候,就需要设备驱动的设计来实现硬件对应用层的透明。
3 没有操作系统的时候,硬件的调用接口是任意的,应用程序是可以和硬件进行交互的,但是当有了操作系统以后,必须根据具体系统的架构设计相应的设备驱动。
4 在行业里,也许驱动工程师,硬件工程师,应用软件工程师,是一套流水线。当然不乏大牛通吃全部。
二 无操作系统的设备驱动
1 单任务架构特点。无限循环,夹杂着轮询,中断检测。
2 模块化的编程。一般有头文件和C文件,而且要防止编译的时候报错:重复定义。所以头文件的编写有一个不是技巧的技巧。它指明了需要用的全局变量和外部函数,而C文件则实现了具体的驱动程序模块。在单片机里面最常见了。
3 设备驱动的接口直接提交给软件工程师,中间没有中介。
4 编程的时候,注意应用程序,模块化驱动,硬件设备的具体层次安排,力求高内聚,低耦合的标准化编程。
三 有OS的时候
1 还是需要类似于无OS时候设备驱动的硬件操作工作
2 将驱动融入内核。这种融合需要在所有设备驱动中设计面向操作系统的内核的接口,而这些接口由OS规定。对一类设备而言,接口一致,只是独立于具体设备。
3 内核和硬件设备之间的桥梁就是驱动程序。它实际上就是把单一的驱动硬件设备行动的工作演化成为操作系统内核与硬件交互的模块。导致代码量变大,对外呈现为API。
4 看上去比没有操作系统复杂,但是为什么还要大费周章呢?原因是为了处理多并发任务,必须用到操作系统。而操作系统的存在,提供了内存管理机制,使得每个进程可以单独访问4GB的地址空间。所以OS通过给驱动制造麻烦,使得上层应用极为便利。
四 关于Linux设备驱动
1 分类:字符设备,块设备,网络设备。针对于存储器和外设来分类和编写驱动程序。
2 字符设备:必须以串行顺序依次进行访问的设备;
块设备:可以用任意顺序进行访问,但是是以块为单位进行操作。
两者之间没有明确的界限,都是用API里面的open(),close(),read(),write()接口。
3 网络设备:面向数据包的收发而设计的。不对应文件系统节点,通信方式与前两种也不一样。
4 补充说明:
最好用C库编写应用程序,这样移植性更好。虽然本质上也是调用API。块设备上面还有Flash/磁盘文件系统,比字符设备复杂。文件系统的格式定义了目录和文件在存储介质上的组织形式。
五 重难点
1 硬件方面
存储设备:SRAM,SDRAM,Flash,磁盘读写方式
总线协议:UART,IIC,IIS,SPI,USB,PCI的协议
轮询,中断,DMA,MMU原理
2 软件方面
C语言的结构体,指针,函数指针,内存动态申请和释放
3 内核:要了驱动和内核的接口以及驱动的架构
4多任务并发控制和同步操作的基础
5 多总结,多交流
六 开发环境
1 工具链
(1) arm-linux-gcc应该放在/usr/local/arm/目录下
(2) 修改环境变量
#vim /etc/profile
在最后添加:
PATH=”$PATH:/usr/local/arm/4.3.2/usr/bin”
Export PATH
或者修改:
#vim /home/.bashrc
最后添加:
Export PATH=/usr/local/arm/4.3.2/usr/bin/:$PATH
(3) 生效环境变量
#source /etc/profile
(4) 测试环境变量
#echo PATH
#arm-linux-gcc –v
(5) 调试工具
Arm-linux-gdb安装在PC的/usr/local/arm/4.3.2/usr/bin。
Strace gdbserver 安装在开发板的根文件系统的/usr/sbin。
2 网络服务
(1)#apt-get install tftpd-hpa
#/etc/init.d/tftpdhpa start
(2)#apt-get install nfs-kernel-server
#mkdir /home/nfs
#chmod 777 –R /home/nfs
#vim /etc/exports
添加:
/home/nfs *(rw,sync,…)
#/etc/init.d/nfs-kernel-sever restart
3 代码工具:Source Insight ,VIM,gedit
4 网站:http://lxr.linux.no/
Google搜索:linux identifier search
七 C语言强化
1 数据类型是固定内存大小的别名,创建变量的模子。
2 变量是一段实际连续存储空间的别名,通过访问它访问内存或者堆栈或者寄存器
3 typedef 已有类型 自定义类型
自定义类型 变量名
4 auto:局部变量的默认属性,指明变量在堆栈分配空间(即在堆栈定义变量),这种数据容易在程序执行的过程中改变。只能修饰局部变量,由于是编译器默认的属性,所以局部变量没有必要强调其auto属性
5 register:指明变量存储于CPU的寄存器中,他只是请求寄存器装载一个变量,但是不一定成功。不是每个数据类型都会被寄存器接受,也不是所有的寄存器都能存放变量。且他修饰的变量没有地址对应,即不可以用&获取地址,不能修饰全局变量,但是在实时性要求高的场合功不可没,因为其直接在CPU寄存器读取数据,快得很啊!
6 static 静态属性。具有文件作用域限定功能。指明变量在程序静态区(全局区)分配空间。可以通过函数func作为中介从A文件来访问B文件里的static类型的变量或者函数。但是function函数必须在B文件中定义为全局函数,且在A文件中申明为外部函数。
7 全局变量也在程序的全局区域分配空间。
8 对于静态局部变量,只会被初始化一次,在第一次访问该变量的时候初始化,当再次遇到该变量的时候,不会在初始化。所以它的作用域只是在他的函数或者程序段,但是生命周期却是整个程序执行的过程。