本文主要是介绍嵌入式学习-驱动开发前奏-lesson4-驱动分类和硬件访问相关,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、驱动开发相关知识
1)驱动的分类
1.常规分类法
按照常规的分类,可以将驱动分为字符设备、块设备、网络接口(网络设备)等。
字符设备
字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现 open, close, read和write 系统调用。例:串口,LED,按键等。
块设备
在大部分的Unix系统中, 块设备定义为:以块(通常是512字节)为最小传输单位的设备,块设备不能按字节处理数据。
而Linux则允许块设备传送任意数目的字节。因此,块和字符设备的区别仅仅是驱动与内核的接口不同。常见的块设备包括硬盘,flash,SD卡……
网络接口
网络接口可以是一个硬件设备,如网卡; 但也可以是一个纯粹的软件设备, 比如回环接口(lo).一个网络接口负责发送和接收数据报文。
2.总线分类法
按照总线分类法,可以将其分为:USB设备,PCI设备,平台总线设备
2)驱动学习方法
驱动的学习,首先要遵守驱动模型,在驱动模型的基础上进行编程。
在编写某个驱动的时候,首先需要知道这个驱动的模型,然后对驱动的硬件进行操作。
二、硬件访问相关知识
1)硬件访问
驱动程序控制硬件设备,其实质就是对硬件设备的寄存器进行操作。
2)地址映射
在Linux系统中,无论是内核程序还是应用程序,都只能使用虚拟地址,而芯片手册中给出的硬件寄存器地址或者RAM地址则是物理地址,无法直接使用,因此,我们读写寄存器的第1步就是将它的物理地址映射为虚拟地址。
可分为动态映射和静态映射
1.动态映射
所谓动态映射,是指在驱动程序中采用ioremap函数将物理地址映射为虚拟地址。
原型:void * ioremap(physaddr, size)
参数:
Physaddr:待映射的物理地址
Size: 映射的区域长度
返回值:映射后的虚拟地址
2.静态映射
所谓静态映射,是指Linux系统根据用户事先指定的映射关系,在内核启动时,自动地将物理地址映射为虚拟地址。
疑问:
如何事先指定映射关系?
先填充结构,然后通过函数告诉Linux内核,这样就可以指定映射关系
内核启动时,在什么地方完成自动映射?
在初始化函数中,根据填充的结构,自动完成自动映射
静态映射关系
在静态映射中,用户是通过map_desc结构来指明物理地址与虚拟地址的映射关系。
struct map_desc {
unsigned long virtual; /* 映射后的虚拟地址 */
unsigned long pfn; /* 物理地址所在的页帧号 */
unsigned long length; /* 映射长度 */
unsigned int type; /* 映射的设备类型 */
};
pfn: 利用__phys_to_pfn(物理地址)可以计算出物
理地址所在的物理页帧号
3.寄存器读写
在完成地址映射后,就可以读写寄存器了,Linux内核提供了一系列函数,来读写寄存器。
unsigned ioread8(void *addr)
unsigned ioread16(void *addr)
unsigned ioread32(void *addr)
unsigned readb(address) //从 I/O 读取 8 位数据 ( 1 字节 );
unsigned readw(address) //从 I/O 读取 16 位数据 ( 2 字节 )
unsigned readl(address) //从 I/O 读取 32 位数据 ( 4 字节 )
void iowrite8(u8 value, void *addr)
void iowrite16(u16 value, void *addr)
void iowrite32(u32 value, void *addr)
void writeb(unsigned value, address)
void writew(unsigned value, address)
void writel(unsigned value, address)
接下来就开始进行驱动程序的学习。。。
菜鸟一枚,如有错误,多多指教。。。
这篇关于嵌入式学习-驱动开发前奏-lesson4-驱动分类和硬件访问相关的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!