




已阅读5页,还剩68页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux驱动学习总结汇报 2016年11月12日 内核模块Bootloder并发控制中断处理设备驱动的结构 Linux内核重要子系统 系统调用接口进程管理内存管理虚拟文件系统网络堆栈设备驱动 最简单的嵌入式系统 MTK的Bootloader 在嵌入式操作系统中 BootLoader是在操作系统内核运行之前运行 可以初始化硬件设备 建立内存空间映射图 从而将系统的软硬件环境带到一个合适状态 以便为最终调用操作系统内核准备好正确的环境 MTK的bootloader有两部分组成 1 第1部分bootloader 也就是MTK内部 in house 的pre loader 这部分依赖平台 2 第2部分bootloader 也就是LittleKernel 这部分依赖操作系统 负责引导linux操作系统和Android框架 源码位置 vendor mediatek proprietary bootable bootloader MTK的Bootloader 正常启动的主要工作如下 1 设备上电后 BootROM开始运行 2 BootROM初始化软件堆栈 softwarestack 通信端口和可引导存储设备 比如NAND EMMC 3 BootROM从存储器中加载pre loader到内部SRAM ISRAM 中 因为这时候还没有初始化外部的DRAM 4 BootROM跳转到pre loader的入口处并执行 5 Pre loader初始化DRAM和加载LK到RAM中 6 Pre loader跳转到LK中并执行 然后LK做一些初始化 比如显示的初始化等 7 LK从存储器中加载引导镜像 bootimage 包括linux内核和ramdisk Android呢 8 LK跳转到linux内核并执行 MTK的Bootloader pre loaders中涉及的硬件部分 1 PLL模块1 PLL模块用于调整处理器和外部内存的频率 2 在PLL模块初始化后 处理器和外部内存的频率可由26MHZ 26MHZ增加到1GHZ 192MHZ 2 UART模块1 UART模块用于调试或是META MobileEngineeringTestingArchitecture 模式下的握手 2 默认情况下 UART4初始化波特率为9216000bps和用于调试信息的输出 UART1初始化为115200bps和作为UARTMETA端口 但也可以使用UART1作为调试或是UARTMETA端口 3 计时器 timer 模块这是个基本的模块 用来计算硬件模块所需要的延时或是超时时间 4 内存模块1 Pre loader由bootROM加载和在芯片组内部的SRAM中执行 因为外部的DRAM还没有初始化 2 为了准备软件整个可执行环境 pre loader采用内置的内存设置来初始化DRAM DRAMisinitializeduponpre loaderbuilt inmemorysettigns 这样 LK就能够被加载到DRAM中并执行 5 GPIO模块 6 PMIC模块为了提供一些基本的硬件功能 比如控制外设电源 pre loader初始化上层模块 uppermodules 7 RTC模块1 当通过power按键开机后 pre loader拉高RTC的PWBB来保持设备一直有电 keepthedevicealive 和继续引导LK 2 RTC闹钟 alarm 有可能是设备开机的启动源 对于这种情况 设备部需要按power按键就可自动启动 8 USB模块当USB线插入时 它初始化来和外部工具通信 比如用于升级系统的下载工具或是META模式触发器的META工具 9 NAND模块 10 MSDC模块Pre loader可以从NANDflash或是EMMC中加载LK 这两者只能选择其中一种来启动 LK中涉及的硬件部分 LK是第2个loader 它由pre loader引导并执行 从根本上来说 basically pre loader已经初始化了相关的硬件模块 而不需要在LK中重新配置这些模块了 但一些模块在LK中被重新复位来配置硬件寄存器 这样可创造一个干净的环境 比如计时器模块 在LK中 计时器重新复位清零硬件计数来对计时进行复位 所有在LK中需要初始化的列在下面 1 计时器模块通过复位硬件寄存器来复位计时 2 串口模块LK采用串口模块来配置它的输入 输出系统 在这个模块初始化后 我们可以使用LK提供的 printf 等函数来使用串口功能 3 I2C模块 4 PWM模块 5 PMIC模块 6 RTC模块和计时器模块一样 在U Boot中 I2C PMIC RTC重新复位寄存器来复位这些模块 7 LED模块通过这poweroffcharging个模块 设备能够通知用户当前的充电状态 8 充电模块这个模块负责关机充电 poweroffcharging 低电压充电 lowercharginginthesystem 9 LCD模块使用这个模块 设备能够显示logo或是任何通知的消息 10 NAND模块因为U Boot也需要从flash读取镜像 比如内核或是ramdisk 所以有必要在U Boot中初始化NAND相关的功能 11 MSDC模块支持MSDC启动 一些重要的数据结构 大部分驱动程序涉及三个重要的内核数据结构 文件操作结构体文件对象file结构体索引节点inode结构体 Linux设备驱动 Linux下设备的属性设备的类型 字符设备 块设备 网络设备主设备号 标识设备对应的驱动程序 一般 一个主设备号对应一个驱动程序 次设备号 每个驱动程序负责管理它所驱动的几个硬件实例 这些硬件实例则由次设备号来表示 同一驱动下的实例编号 用于确定设备文件所指的设备 可通过ls l 设备文件名 命令查看设备的主次设备号 以及设备的类型 18 分配和释放字符设备号 编写驱动程序要做的第一件事 为字符设备获取一个设备号 事先知道所需要的设备编号 主设备号 的情况 intregister chrdev region dev tfirst unsignedcount constchar name first是要分配的起始设备编号值 first的次设备号通常设置为0 Count所请求的连续设备编号的个数 Name设备名称 指和该编号范围建立关系的设备 分配成功返回0 19 分配和释放字符设备号 动态分配设备编号 主要是主设备号 intalloc chrdev region dev t dev unsignedbaseminor unsignedcount constchar name dev是一个仅用于输出的参数 它在函数成功完成时保存已分配范围的第一个编号 baseminor应当是请求的第一个要用的次设备号 它常常是0 count和name参数跟request chrdev region的一样 20 分配和释放字符设备号 不再使用时 释放这些设备编号 使用以下函数 voidunregister chrdev region dev tfrom unsignedcount 在模块的卸载函数中调用该函数 21 字符设备的注册 内核内部使用structcdev结构表示字符设备 编写设备驱动的第二步就是注册该设备 包含头文件 获取一个独立的cdev结构 structcdev my cdev cdev alloc 调用cdev init初始化cdev结构体voidcdev init structcdev cdev struct fops 初始化该设备的所有者字段 dev cdev owner THIS MODULE 初始化该设备的可用操作集 dev cdev ops 22 字符设备的注册 编写设备驱动的第二步就是注册该设备 cdev结构已建立和初始化 最后通过cdev add函数把它告诉内核 intcdev add structcdev dev dev tnum unsignedintcount dev是要添加的设备的cdev结构 num是这个设备对应的第一个设备编号 count是应当关联到设备的设备号的数目 卸载字符设备时 调用相反的动作函数 voidcdev del structcdev dev 23 Linux设备驱动的并发控制 24 设备驱动的并发控制 在驱动程序中 当多个线程同时访问相同的资源时 可能会引发 竞态 必须对共享资源进行并发控制 并发和竞态广泛存在 并发控制的目的 使得线程访问共享资源的操作是原子操作 原子操作 在执行过程中不会被别的代码路径所中断的操作 驱动程序中的全局变量是一种典型的共享资源 25 考虑一个非常简单的共享资源的例子 一个全局整型变量和一个简单的临界区 其中的操作仅仅是将整型变量的值增加1 i 该操作可以转化成下面三条机器指令序列 得到当前变量i的值并拷贝到一个寄存器中将寄存器中的值加1把i的新值写回到内存中 原子操作 26 Linux内核的并发控制 在内核空间的内核任务需要考虑同步内核空间中的共享数据对内核中的所有任务可见 所以当在内核中访问数据时 就必须考虑是否会有其他内核任务并发访问的可能 是否会产生竞争条件 是否需要对数据同步 27 确定保护对象找出哪些数据需要保护是关键所在内核任务的局部数据仅仅被它本身访问 显然不需要保护 如果数据只会被特定的进程访问 也不需加锁大多数内核数据结构都需要加锁 若有其它内核任务可以访问这些数据 那么就给这些数据加上某种形式的锁 若任何其它东西能看到它 那么就要锁住它 Linux内核的并发控制 28 Linux内核的并发控制 并发控制的机制中断屏蔽 原子数操作 自旋锁和信号量都是解决并发问题的机制 中断屏蔽很少被单独使用 原子操作只能针对整数来进行 因此自旋锁和信号量应用最为广泛 29 锁机制可以避免竞争状态正如门锁和门一样 门后的房间可想象成一个临界区 在一段时间内 房间里只能有一个内核任务存在 当一个任务进入房间后 它会锁住身后的房门 当它结束对共享数据的操作后 就会走出房间 打开门锁 如果另一个任务在房门上锁时来了 那么它就必须等待房间内的任务出来并打开门锁后 才能进入房间 加锁机制 30 任何要访问临界资源的代码首先都需要占住相应的锁 这样该锁就能阻止来自其它内核任务的并发访问 加锁机制 31 原子数操作 整型原子数操作原子变量初始化atomic ttest ATOMIC INIT i 设置原子变量的值voidatomic set atomic t v inti 获得原子变量的值atomic read v 原子变量加voidatomic add inti atomic t v 原子变量减voidatomic sub inti atomic t v 32 原子数操作 整型原子数操作原子变量的自增操作voidatomic inc atomic t v 原子变量的自减操作voidatomic dec atomic t v 操作并测试 测试其是否为0 0为true 否为false atomic inc and test atomic t v atomic dec and test atomic t v intatomic sub and test inti atomic t v 操作并返回 返回新值 intatomic add return inti atomic t v intatomic sub return inti atomic t v 33 原子数操作 原子位操作设置位voidset bit intnr volatileunsignedlong addr 清除位voidclear bit intnr volatileunsignedlong addr 改变位change bit nr p 测试位test bit intnr constvolatileunsignedlong p 测试并操作位test and set bit nr p 34 自旋锁 自旋锁是专为防止多处理器并发而引入的一种锁 它在内核中大量应用于中断处理等部分 而对于单处理器来说 防止中断处理中的并发可简单采用关闭中断的方式 不需要自旋锁 自旋锁最多只能被一个内核任务持有 若一个内核任务试图请求一个已被持有的自旋锁 那么这个任务就会一直进行忙循环 也就是旋转 等待锁重新可用 自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区 因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源 35 自旋锁 自旋锁的初衷就是 在短期间内进行轻量级的锁定 一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋 特别浪费处理器时间 所以自旋锁不应该被持有时间过长 如果需要长时间锁定的话 最好使用信号量 36 自旋锁 自旋锁防止在不同CPU上的执行单元对共享资源的同时访问 以及不同进程上下文互相抢占导致的对共享资源的非同步访问 在单CPU且不可抢占的内核下 自旋锁的所有操作都是空操作 自旋锁不允许任务睡眠 37 自旋锁 自旋锁的基本形式如下 spin lock 38 自旋锁 自旋锁原语要求包含文件是 锁的类型是spinlock t 锁的两种初始化方法 spinlock tmy lock SPIN LOCK UNLOCKED voidspin lock init spinlock t lock 进入一个临界区前 必须获得需要的lock voidspin lock spinlock t lock 自旋锁等待是不可中断的 一旦你调用spin lock 将自旋直到锁变为可用 释放一个锁 voidspin unlock spinlock t lock 39 自旋锁 关中断的自旋锁Spin lock irq Spin unlock irq Spin lock irqsave Spin unlock irqrestore 40 信号量 Linux中的信号量是一种睡眠锁 如果有一个任务试图获得一个已被持有的信号量时 信号量会将其推入等待队列 然后让其睡眠 当持有信号量的进程将信号量释放后 在等待队列中的一个任务将被唤醒 从而便可以获得这个信号量 信号量的睡眠特性 使得信号量适用于锁会被长时间持有的情况 信号量的操作信号量支持两个原子操作P 和V 前者做测试操作 后者叫做增加操作 Linux中分别叫做down 和up 41 信号量 42 信号量 43 Linux信号量的实现 内核代码必须包含 才能使用信号量 相关的类型是structsemaphore 信号量的定义 structsemaphore atomic tcount intsleepers wait queue head twait 44 Linux信号量的实现 信号量的声明和初始化直接创建一个信号量structsemaphore sem 接着使用sema init来初始化这个信号量 voidsema init structsemaphore sem intval 互斥模式的信号量声明 内核提供宏定义 DECLARE MUTEX name 信号量初始化为1DECLARE MUTEX LOCKED name 信号量初始化为0 45 自旋锁忙等待 无调度开销 进程抢占被禁止 锁定期间不能休眠 信号量拿不到就切换进程 有调度开销 锁定期间可以休眠 46 Linux的中断处理 47 为什么会有中断 中断最初是为克服对I O接口控制采用程序查询所带来的处理器低效率而产生的 处理器速度一般比外设快很多用轮询的方式来查询设备的状态 CPU效率不高 CPU和外设不能并行工作 中断机制让CPU启动设备后 就去处理其他任务 只有当外设真正完成数据传输的准备 请求CPU服务的时候 CPU才转过来处理外设的请求 48 中断和异常 外部中断 外部设备所发出的I O请求 随着计算机系统结构的不断改进以及应用技术的日益提高 中断的适用范围也随之扩大 出现了所谓的内部中断 或叫异常 异常 为解决机器运行时所出现的某些随机事件及编程方便而出现的 49 I O中断处理 为了保证系统对外部的响应 一个中断处理程序必须被尽快的完成 因此 把所有的操作都放在中断处理程序中并不合适Linux中把紧随中断要执行的操作分为三类紧急的 critical 一般关中断运行 诸如对PIC应答中断 对PIC或是硬件控制器重新编程 或者修改由设备和处理器同时访问的数据非紧急的 noncritical 如修改那些只有处理器才会访问的数据结构 例如按下一个键后读扫描码 这些也要很快完成 因此由中断处理程序立即执行 不过一般在开中断的情况下 50 I O中断处理 Linux中把紧随中断要执行的操作分为三类非紧急可延迟的 noncriticaldeferrable 这些操作可以被延迟较长的时间间隔而不影响内核操作 有兴趣的进程将会等待数据 内核用下半部分这样一个机制来在一个更为合适的时机用独立的函数来执行这些操作 如把缓冲区内容拷贝到某个进程的地址空间 例如把键盘缓冲区内容发送到终端处理程序进程 51 注册中断服务例程 中断号是一个宝贵且常常有限的资源 内核维护一个中断号的注册表 要使用中断 就要进行中断号的申请 也就是IRQ InterruptReQuirement 只有当设备需要中断的时候才申请占用一个IRQ 或者是在申请IRQ时采用共享中断的方式 让更多的设备使用中断 52 注册中断服务例程 在实现中断注册接口 intrequest irq unsignedintirq irqreturn t handler int void structpt regs unsignedlongflags constchar dev name void dev id voidfree irq unsignedintirq void dev id request irq的返回值是0指示申请成功 为负值时表示错误码 函数返回 EBUSY表示已经有另一个驱动占用了所要申请的中断线 53 注册中断服务例程 request irq的参数说明 unsignedintirq 要申请的中断号 irqreturn t handler int void structpt regs 要安装的中断处理函数指针 constchar dev name 用在 proc interrupts中显示中断的拥有者 54 注册中断服务例程 request irq的参数说明 unsignedlongflags 与中断管理相关的位掩码选项 Flags的每个位有不同含义SA INTERRUPT当该位被设置时 表示这是一个 快速 中断 快速中断处理例程运行时 屏蔽中断 SA SHIRQ这个位表示中断可以在设备间共享 void dev id这个指针用于共享的中断号 做为驱动程序的私有数据区 可用来识别那个设备产生的中断 不使用共享中断线方式时 可设置为NULL 55 实现中断处理例程 中断处理例程特别之处 在中断时间内运行 不能向用户空间发送或者接收数据 不能做任何导致休眠的操作 不能调用schedule函数 无论快速还是慢速中断处理例程 都应该设计成执行时间尽可能短 56 实现中断处理例程 中断处理函数的参数和返回值irqreturn t handler intirq void dev id structpt regs regs Irq中断号Dev id驱动程序可用的数据区 通常可传递指向描述设备的数据结构指针 structpt regs regs 保存了处理器进入中断代码之前的cpu寄存器的值 一般驱动可不要 57 实现中断处理例程 启动和禁用中断驱动禁止特定中断线的中断 include voiddisable irq intirq voidenable irq intirq 禁止所有中断voidlocal irq save unsignedlongflags local irq save在当前处理器上禁止中断递交 在保存当前中断状态到flags voidlocal irq disable void local irq disable关闭本地中断递交而不保存状态 58 实现中断处理例程 打开中断 voidlocal irq restore unsignedlongflags 恢复由local irq save存储于flags的状态 而local irq enable无条件打开中断 voidlocal irq enable void 59 顶半部和底半部 中断处理的一个主要问题是如何在处理中进行长时间的任务 响应一次设备中断需要完成一定数量的工作 但是中断处理需要很快完成并且不使中断阻塞太长 Linux把中断处理例程分两部分 顶部分 实际响应中断的例程 底部分 被顶部分调用 通过开中断的方式进行 两种机制实现 Tasklet工作队列workqueue 60 顶半部和底半部 顶半部顶半部的功能是 登记中断 当一个中断发生时 它进行相应地硬件读写后就把中断例程的下半部挂到该设备的底半部执行队列中去 顶半部执行的速度就会很快 可以服务更多的中断请求 底半部仅有 登记中断 是远远不够的 因为中断的事件可能很复杂 Linux引入了一个底半部 来完成中断事件的绝大多数使命 底半部和顶半部最大的不同是底半部是可中断的 而顶半部是不可中断的 底半部几乎做了中断处理程序所有的事情 而且可以被新的中断打断 底半部则相对来说并不是非常紧急的 通常还是比较耗时的 因此由系统自行安排运行时机 不在中断服务上下文中执行 61 软中断和tasklet的关系如下图 小任务机制tasklet 62 小任务机制tasklet ksoftirqd是一个后台运行的内核线程 它会周期的遍历软中断的向量列表 如果发现哪个软中断向量被挂起了 pend 就执行对应的处理函数 tasklet所对应的处理函数就是tasklet action 这个处理函数在系统启动时初始化软中断时 就在软中断向量表中注册 63 小任务以数据结构的形式存在 structtasklet struct structtasklet struct next unsignedlongstate atomic tcount void func unsignedlong unsignedlongdata 每个结构一个函数指针func 指向自定义的函数 这就是我们要执行的小任务函数 小任务机制tasklet 64 tasklet的接口DECLARE TASKLET name function data 此接口初始化一个tasklet name是tasklet的名字 function是执行tasklet的函数 data是unsignedlong类型的function参数 staticinlinevoidtasklet schedule structtasklet struct t 调度执行指定的tasklet 将定义后的tasklet挂接到cpu的tasklet vec链表 而且会引起一个软tasklet的软中断 既把tasklet对应的中断向量挂起 pend 小任务机制tasklet 65 工作队列 工作队列类似taskets 允许内核代码请求在将来某个时间调用一个函数 不同在于 tasklet在软件中断上下文中运行 所以tasklet代码必
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 45710-2025聚对苯二甲酸乙二醇酯纤维及切片中低聚物的测定高效聚合物色谱法(APC)
- 2025年食品科学与工程专业综合知识考核试题及答案
- Aromatase-IN-5-生命科学试剂-MCE
- 2025年人力资源管理政策与实务试题及答案
- 2025年监会与财经法规专业资格考试试题及答案
- 2025年家庭教育与儿童心理发展专业知识考试试卷及答案
- 2025年海洋科学专业研究生入学考试题及答案
- 2025年公共卫生管理硕士考试试题及答案
- 爱的礼物我家的宠物狗写物作文(7篇)
- 一年级写人作文我的妹妹300字(12篇)
- 互联网与营销创新智慧树知到期末考试答案章节答案2024年华东师范大学
- 云南开放大学实-用写作离线作业1-5
- 四川省成都市温江县2023-2024学年八下物理期末监测试题及答案解析
- 内科学(肾脏-内分泌-血液)智慧树知到期末考试答案章节答案2024年温州医科大学
- 食品安全与日常饮食智慧树知到期末考试答案章节答案2024年中国农业大学
- 100以内进退位加减法口算题每天60道
- MOOC 嵌入式软件设计-大连理工大学 中国大学慕课答案
- 永久基本农田储备区划定技术方案
- 医疗销售经验技巧分享
- 大气组成与垂直分层(简洁版)
- 钢铁企业环保培训课件
评论
0/150
提交评论