驱动程序tips

前序:

驱动程序全是回调函数,用一些驱动层的库函数。看着和单片机程序类似

驱动:编写Linux设备驱动必须牢固掌握自旋锁、信号量、完成量、中断顶/底半部、定时器、内存和I/O映射以及异步通知、阻塞/非阻塞、I/O等大量理论知识;
实践:最好有一块可以实际练手的电路板来构造嵌入式的开发环境。如果暂时没有,则可以选择这样的权宜之策:用VmWare搭建两台虚拟机,两台虚拟机上都运行Linux操作系统,一台作为开发主机,一台作为目标机。
Intel的80386属于微处理器,而内部集成了80386处理器、片选单元、中断控制、定时器、看门狗定时器、串行I/O、DMA和总线仲裁
应用软件工程师在调用套接字发送和接收数据包的时候,他不必关心网卡上的硬件:中断、寄存器、存储空间、I/O端口、片选以及其他任何硬件词汇;在使用printf()函数输出信息的时候,他不用知道底层究竟是怎样把相应的信息输出到屏幕或者串口.

正文:

Linux设备驱动开发=硬件控制+Linux内核API(用于并发/同步控制、阻塞/唤醒、中断底半部调度、内存和I/O访问等)+驱动框架

实体功能代码
设备描述基地址、中断号、时钟、DMA、复位等信息 arch/arm,arch/blackfin,arch/xxx等目录 
驱动完成外设的功能,如网卡收发包,声卡录放,SD卡读写…drivers/net,sound,drivers/mmc等目录
总线完成设备和驱动的关联drivers/base/platform.c,drivers/pci/pci-driver.c
设备树是一种dts文件,它用最简单的语法描述每个板子上的所有设备,以及这些设备的连接信息。 

1 Linux主要将设备分为二类:字符设备和块设备。

这两类设备的不同点在于:

在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了.而块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。

块设备主要针对磁盘等慢速设备。以字符设备的驱动较为简单,因此本章主要阐述字符设备的驱动编写。
读写字符设备,用字符设备的驱动程序
驱动函数: register_chrdev然后操作函数, (*lseek)();(*read);(*write);(*readdir);(*select);(*ioctl);(*mmap);(*open);
  (*release);(*fsync);(*fasync);(*check_media_change);(*revalidate);
  
2 一个硬件驱动模块通常应包括如下函数:
(1)中断服务程序ISR
(2)硬件初始化:a.修改寄存器 b.将中断服务程序入口地址写入中断向量表:
(3)设置CPU针对该硬件的控制线
a.如果控制线可作PIO(可编程I/O)和控制信号用,则设置CPU内部对应寄存器使其作为控制信号;
b.设置CPU内部的针对该设备的中断屏蔽位,设置中断方式(电平触发还是边缘触发)。
(4)提供一系列针对该设备的操作接口函数

中断:request_irq  类似应用层的signal捕获信号,request_irq 用于获取中断

3 驱动程序发送和接收:
数据报经过物理层到达数据链路层,然后再通过mux层到达网络层,在通过TCP协议层到达应用层,完成数据报接收的全过程.
notes:物理层--数据链路层--mux--网络层--应用层.
接收数据报:当一个数据报到来时会触发一个中断,中断服务程序xxInt将通过调用netjobAdd()任务队列添加一个网络任务(数据报接收函数(xxReceive)),它通过系统任务tNettask来调用。然后接收函数调用MUX的接口函数muxReceive(),而muxReceive()又调用协议层提供的接口函数stackRcvRtn()将数据报传递到协议层,最终数据将通过协议层到达应用程序的缓冲区中,应用程序通过read()函数对其读取.
notes:接收数据--中断---添加网络任务---tNettask---muxReceive--stackRcvRtn--协议层--应用层
当有数据要发送时,网络协议层通过其与mux层的接口调用muxSend()函数,而muxSend()函数又通过调用xxSend()函数负责将利用指针传递来的数据报送到发送FIFO队列中,然后起动网卡设备的发送功能,发送完后将随之产生中断信号,调用中断服务程序,清除设备缓冲区
notes: 发送函数---网络层---muxSend---FIFO队列---起动网卡发送---中断---清理设备缓冲区

4 mmu:高性能处理器一般会提供一个内存管理单元(MMU)(MMU是一个独立的硬件),该单元辅助操作系统进行内存管理,提供虚拟地址和物理地址的映射、内存访问权限保护和CACHE缓存控制等硬件支持
内存分配:kmalloc(因为驱动是内核的一部分不能用malloc)

5 在驱动中,对于外设的寄存器,不能直接访问物理地址,需访问经过映射后的虚拟地址。外设的寄存器可以用2种方式被映射到虚拟地址,一是静态映射,二是通过ioremap()动态映射。静态映射的方法是在将Linux移植到特定平台时建立一个 map_desc数组,通过 MACHINE_START和MACHINE_END宏之间的.map_io成员函数建立页面。
       
6 按键往往是一个按钮直接对应于一个可中断的GPIO,而键盘则有一个行列矩阵,有一个扫描的过程,由键盘控制器负责扫描、去抖动、得到键值等工作。

7 内核:
1) BIOS从启动设备中导入主引导记录(MBR),接下来MBR中的代码查看分区表并从活动分区读取GRUB,LILO或SYSLINUX等bootloader
2) bootloader会加载压缩后的内核映像并将控制权传递给它。
3) 内核取得控制权后,会将自身解压缩并投入运转.
4) 直到指定shell开始运行告一段落,这时用户开始操作Linux

Netlink一种在内核空间和用户空间透过套接字API进行通信的足够强大的机制
主要是放kelnel的一些全局数据结构,如内核页表,arm的页目录要有16k大
文件管理:bio层的下一层就是最终的驱动

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页