标签:
第8章:让开发板发出声音:蜂鸣器
一、Linux驱动的代码重用
Linux 驱动的代码重用有很多种方法。可以采用标准 C 程序的方式。将要重用的代码放在其他的文件(在头文件中声明)中。如果要使用某些功能, include 相应的头文件即可(这种方式称为静态重用)。也可以使用另外一种动态重用的方式,也就是一个 Linux 驱动可以使用另外一个Linux驱动中的资源(函数、变量、宏等)。本节将详细介绍这些代码重用方法。
编译是有多个文件组成的Linux驱动
Linux 驱动的代码不多,将所有的代码都放到一个文件中并没有什么不妥, 但对于复杂的 Linux 驱动, 就需要使用多个源代码文件存放不同的功能代码, 这样做有利于代码分类和管理。当然,如果Linux 驱动要使用第三方的源代码, 那么就不得不编译多个源代码文件,最终便成.ko文件或编译进Linux内核(估计不会有人将第三方草原代码都复制到 个文件里再进行编译)。
Linux驱动模块的依赖(导出符号)
代码重用分为静态和动态两种。在上一节介绍的方式是代码的静态重用,这种方式是代码级的重用,也就是将需要重用的代码和使用这些代码的使用者放在一起进行编译,最终生成一个可执行文件或程序库(.ko、.so等)。
在本节将介绍另外一种代码共享的方式:模块依赖,也称为导出符号。如果只能用一句话解释如何利用导出符号实现代码共卒,这句话就是“在一个驱动模块里使用另一个驱动模块里的被导出的符号(常章、变量、函数等)”。
二、强行卸载Linux驱动
如果编写的Ljnux驱动程序在逻辑上是正确的,那么可以正常装载和卸载,但在某些情况下,可能某些程序会出现异常情况。这时Linux驱动可能会无法正常卸载。在本节将介绍如何处这些无法卸载的驱动。
情况1:初始化函数崩溃
由于Linux驱动模块的初始化函数(通过module_init 宏指定的函数)进行了某些操作而崩溃,从而导致初始化函数无法正常返回。这种情况的表现是当前Linux 驱动模块没用被任何其他的Linux驱动模块使用,但却显示已经被引用了一次。
情况2:卸载函数被阻塞
在使用 rmmod 命令卸载 Linux 驱动时,系统会调用卸载函数(通过 module_exit 宏指定的函数),只有卸载函数成功返回肘, Linux 驱动才会被卸载。 如果卸载函数被阻塞(可能是死循环、并发等情况引起的阻塞), rmmod 命令也会被阻塞.也就是说永远不会执行到卸载 Linux 驱动模块的代码。这种情况的表现是一执行rmmod命令就会停在那不动了, 永远也不会返回到系统的操作提示符。
三、蜂鸣器(PWM)驱动实验
PWM驱动与LED驱动的实现流程类似,可能还要简单一些。在本章只是为了演示如何将一个 Linux驱动分成多个实现文件, 才使用了比较简单的PWM驱动。
总结:
通过本章的学习, 可以掌握Linux驱动常用的代码重用方式。除此之外,本章还介绍了一种强行卸载Linux驱动的方法。通过这种方法,就可免去不断重启机器的痛苦了。
第九章 硬件抽象层:HAL
9.1为什么要在安卓中加入HAL?
首先Google 为 Android 增加 HAL 的主要目的除了尽量避免应用程序直接访问 Linux 驱动外,还有一仓重要原因,那就是保护 “私人财产”。-对于
那些既想发布茬子·Android,的 Linux 驱动程序,又不想将核心业务逻辑公开的企业或个人, ~简直就是福音。
HAL 并不是Linux 内核的一部分,而是位于Android的系统运行库层,尽管这些 Linux.驱动都是免费给用户’使用的,但是由于这些Linux 驱动的实现涉及一些,技术专利或商业秘密,如果公开源代码会有很大麻烦。但作为Linux.驱动,又不得不公开源代码。这是由于 Linux 内核采用了 GPL 协议,而 GPL协议要求所有使用基于 GPL 协议的源代码的程序必须开源(由于 Linux 驱动属于 Linux 内核的一部分,因此 Linux 驱动必须开源)。
总而言之,Google 为 Android 增加 HAL 的主要目的:
1.统一硬件的调用接口。由于HAL 有标准的调用接口,所以可以利用 HAL屏蔽Linux 驱动复杂,不统一的接口。
2.解决了GP(版权问题。由于 Linux 内核基于GPL协议,而 Android 基于 Apache Licence 2 ..0、协议.因此 Google 玩了个“穿越飞将原本位于 Linux驱动中的敏感代码向上移了一个层次二这样这些敏感代码就摆脱了 GPL 协议的束缚,。那些不想开源的 Linux驱动作者也就没必要开源了。
3.针对一些特殊的要求。对于有些硬件,可能需要访问→些用户空间的资源,或在内核空间不方便完成的工作以及特殊需求。在这种情况下,可以利用位于用户空间的HAL 代码来辅助 Linux驱动完成一些工作。
9.3为LED驱动增加 HAL
9.3.1 编写一款支持 HAL 的 Linux 驱动程序的步骤编写一款支持 HAL 的 Linux 驱i.9J.程序要比编写普通的 Linux 驱动程序复杂一些,但这些付出是值得的。 因为加入 HAL 会使组成 Linux 驱动的一整套 Library 的各部分更独立,更容易维护。下面看一下具体的实现步骤。在后面的内容会逐渐对每一步进行讨论。
第 1 步 编写 Linux 驱动
“编写 Linux 驱动”,从表明上看是废话,但如果要为 Linux 驱动添加 HAL,而且想尽量保护敏感数据。 Linux 驱动的代码就要尽量简洁,尽可能将业务逻辑放到 HALLibrary 中。
第 2 步:编写 HAL Library
HAL Library 就是普通的 Linux Library 仆.so )文件。但这类库文件有一个接口。通过HAL_MODULE_INFO_ SYM 变量实现。 Service Library 就是通过在这个接口中定义的 ID 定位 HAL Library 的。
第 3 步:编写 Service Library
尽管这步并不是必需的,但新的 HAL 架构要求我们这样做。 Service Library 也是 Linux Library。这一步比较灵活。 Service Library 可以是一般的 Linux Library,也可以是别I Library。在本章的 LED 驱动例子中将 Service Libratγ 和刑I Library 合到了一起。也就是说, Service Library 就是 JNI Library.实际上这一步除了用 CIC件实现的*.so 库文件外,还应该包含一个用 Java 编写的服务管理类( ServiceManager)。 ServiceManager 会调用 Service Library。而 APK 程序会调用 ServiceManager 类米访问 Service Library。
第10章 嵌入式Linux的调试技术
本章主要讲Linux调试技术。打印内核调试信息:printk,printk函数运行在内核空间,linux内核程序只能使用printk函数输出调试信息。printk文件由一个4个数字组成文本文件。6:将消息输出到控制台的级别。4:默认的消息日志级别。1:控制台日志级别可被设置的最小值。7:控制台日志级别的默认值。在不想使用prink输出消息时,还需要了解可变参数的宏和do while。通过虚拟文件系统进行数据交互:在 Linux文件系统中/proc被用来作为内核空间与用户空间进行数据交互的工具。/proc文件系统和/dev文件系统一样,需要设置访问文件的动作处理函数。而/proc文件系统主要通过 proc_dir_entry.read_proc和proc_dir_entry.read_write函数指针来设置读写处理函数。
调试工具:gdb、gdbserver和调试内核空间程序的kgdb。gdb可跟踪调试用户空间的程序。quit用于退出gdb调试界面;list用于列出程序中的代码。用gdbserver远程调试用户空间程序,是一个可以运行在ARM架构上的服务端程序。首先进入Android模拟器的终端,然后进入data/local目录。Android模拟器只能通过端口映射方式使用gdbserver调试程序。
用kgdb远程调试内核程序,kgdb除了提供类似prink函数的日志输出功能,还让开发人员在pc上链接目标设备。kgdb包含两部分:kgdb内核和一套链接接口,支持串口tty设备连接和以太网连接。用kgdb调试Linux内核前需要先配置Linux内核和设置内核参数,使用make menuconfig命令进Linux内核配置菜单中。
标签:
原文地址:http://www.cnblogs.com/mnh930102/p/5648464.html