《Verilog数字系统设计教程(第2版.pdf》

Verilog数字系统设计教程(第2版).pdf

https://github.com/shigh1005/pdf_book


《Linux设备驱动开发详解:基于最新的Linux 4.0内核.pdf》

《Linux设备驱动开发详解(基于最新4.0内核)》前言

LinuxDev
2015-04-28
    阅读数:1056

Linux从未停歇脚步。Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核。做技术,从来没有终南捷径,拼的就是坐冷板凳的傻劲。

这是一个连阅读都被碎片化的时代,在这样一个时代,人们趋向于激进、浮躁。内心的不安宁使我们极难静下心来研究什么。我见过许许多多的Linux工程师,他们的简历书写着“精通”Linux内核,有多年的工作经验,而他们的“精通”却只是把某个寄存器从0改成1,从1改成0的不断重复;我见过许许多多的Linux工程师,他们终日埋头苦干,敲打着自己的机器和电路板,却从未冷静下来思考,并不断重构和升华自己的知识体系。

这是要把牢底坐穿的程序员。这样“忙忙碌碌”的程序员,从来都不是什么好程序员。

优秀的程序员,最优秀的品质是能够内心宁静地学习与思考问题,透析代码背后的架构、原理和设计思想。没有思想的代码是垃圾代码,没有思想的程序员,只是在完成低水平重复建设的体力活。很多程序员,连自己写的代码最后在机器里面怎么跑都从不过问,很多事情莫名其妙地发生了,很多bug莫名其妙地消失了……永远都是得过且过

由此,衍生出《Linux设备驱动开发详解》新版的第一个出发点,那就是带给读者更多关于Linux开发背后思想的讲解,奠定根基。《Linux设备驱动开发详解(基于4.0内核)》呈现给读者的,更多的是一种思考,而不是知识点的简单罗列

这次更新更进一步加强了对驱动编程所涉及Linux内核最底层机理的讲解,并对前2版的基础理论部分进行了大篇幅地重写,实例代码也被大面积重构。大幅度修改的内容包括中断、定时器、进程生命周期、uevent、并发、编译乱序、执行乱序、等待队列、I/O模型、内存管理等。这些知识点是如此重要,是真正证明程序员对Linux理解的部分,只有打好根基,才能游刃有余。

新版删除了《Linux设备驱动开发详解》第一版、第二版大量描述各种具体具体驱动类型的章节比如Sound、PCI、MTD、TTY等,而将更多焦点转移到了驱动编程背后的内核原理, 并试图从Linux内核上百个驱动子系统中寻找出内部的规律,以培养读者举一反三的能力

Linux内核有上百个驱动子系统,这一点从内核的drivers子目录就可以看出来:

好吧,傻子才会一个目录一个目录地去看,一个目录一个目录地从头学起。我们势必要寻找各种驱动子系统的共性,摸索规律。本次更新,我们将更多看到各驱动子系统的类比,以及驱动子系统的层次化设计。

技术工作,从来都不是一劳永逸。这世界变化太快,当前技术革新的速度数倍于我们父辈祖辈祖祖辈经过的任何时代。证明你是真球迷还是伪球迷的时候到了。这是伪程序员的地狱,也是真程序员痛苦中的狂欢。

从浩如烟海的知识体系中、不断更新的软件版本中终生学习,不断攻克一个个挑战,获取新的养分,寻找新的灵感,这实在是黑暗码农生涯中不断闪现的璀璨光芒。

自本书第一版、第二版发布后,内核版本不断刷新,3.0、3.1、3.2…3.19、4.0、4.1,变化的是软件的架构,不变的是Linus的热情。

这无疑是本次升级的第二个出发点,更新Linux驱动编程的知识体系以符合最新的时代。所以,本次更新大量新增了关于Device Tree、ARM Linux移植、Linux电源管理、GPIO、clock、timer、pinmux、DMA等的内容。我们的操作平台,也转移到了QEMU模拟的4核Cortex-A9电路板,书中的实例,基本都转移到了市面流行的新芯片。

最近两三年,老是听到许多程序员抱怨,缺乏讲新内核的资料、缺乏从头到尾讲Device Tree的资料,但是我想说,这实在不是什么难点。难点仍然是本书第一个出发点要解决的问题,如果有好的基础,以优秀程序员极强的学习能力,应该很快就可以掌握这些新知识。机制没有变,变化的是只是策略。

所以学习能力,也是优秀程序员的又一品质。没有人生下来就是天才,良好学习能力的培训,本身也是通过不断学习来获取的。可以说,学的越多的人,学新东西一定越快,学习能力也变得越强。因为,知识的共通性实在太多。

读者阅读本书的思路,不应该是企图把它当成一本工具书、查API的书,而是一本梳理完整理论体系、开发思想、软件架构的书。唯如此,我们才能适应未来新的变化。

不知不觉中,离本书的第一次出版已经过去了七个年头。而自本次更新开始实施至今,也经过了一轮寒暑更替。岁月如歌,七载而下,我已非当年的意气青年。本书一版,二版,再版,这实非当初的预料。回首过去,我们惊奇地发现,这七年,正好是Linux由弱而盛,节节胜利的七年。也是许多如我一般的码农成家立业、结婚生子的七年。未来七年的Linux会是什么样子,我们无从预料。本书是否会有更进一步的新版,我们也无法预知,一如Linux没有路线图。社区和生态就是最好的Roadmap,万事随缘,而唯一不变的只是激情。

时代的滚滚车轮,推动着Linux内核的版本不断向前,也推动着每个人的人生。红尘滚滚,

我不去想是否能够成功,

既然选择了远方,

便只顾风雨兼程。

最后,本书能得以出版,要感谢带领我向前的人生导师和我的众多小伙伴,他们或者在我人生的关键时刻改变了我,或者带给了我黑暗程序生涯中无尽的快乐和动力。我的小伙伴,他们力挺我,鼓励我,也辱骂我,奚落我,这些,就是真挚的友情。

谨以此书,致以对杨平先生、何昭然、方毅伟、李华毅、宋志吾、杜向龙、叶祥振、刘昊、王榕、何晔、王立赛、曾过、刘永生、段炳华、章君义、王文琪、卢鹏、刘涛、徐西宁、吴赫、任桥伟、秦龙廷、胡良兵、张家旺、王雷、Bryan Wu、Eric Miao、Qipan Li、Guoying Zhang、陈健松、应荣军、Haoyu Zhong、刘洪涛、季久峰、邴杰、孙志忠、吴国举、Bob Liu、赵小吾、贺亚锋、刘仕杰、Hao Yin等老师和小伙伴的深深感激;谨以此书,致以对我的父母大人、老婆大人、兄长和姐姐、伟大丈母娘的深深感激,本书新版的写作时间超过一年,其过程是一种巨大的肉体和精神折磨,没有他们的默默支持和不断鞭策,是不可能完成的;谨以此书,致以对为本书做出巨大贡献的编辑、策划老师们,尤其是张国强老师深深的感激!

由于篇幅的关系,我没有办法一一列举所有我要感激的人入感谢名单。但是,我这些年从你们那里获得的,远远大于我付出的。所以,内心深处,唯有怀着对小伙伴深深的感恩,不断前行。岁月如歌,吾歌狂行。

宋宝华

2015年4月于上海浦东


 

1.4 Linux 设备驱动

1.4.1 设备的分类及特点

计算机系统的硬件主要由 CPU、存储器和外设组成。随着 IC 制作工艺的发展,目前, 芯片的集成度越来越高,往往在 CPU 内部就集成了存储器和外设适配器。譬如,相当多的 ARM、PowerPC、MIPS 等处理器都集成了 UART、I2C 控制器、SPI 控制器、USB 控制器、 SDRAM 控制器等,有的处理器还集成了 GPU(图形处理器)、视频编解码器等。

驱动针对的对象是存储器和外设(包括 CPU 内部集成的存储器和外设),而不是针对 CPU 内核。Linux 将存储器和外设分为 3 个基础大类。

● 字符设备。

● 块设备。
● 网络设备。 

字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标 等。块设备可以按任意顺序进行访问,以块为单位进行操作,如硬盘、eMMC 等。字符设备 和块设备的驱动设计有出很大的差异,但是对于用户而言,它们都要使用文件系统的操作接 口 open()、close()、read()、write() 等进行访问。

在 Linux 系统中,网络设备面向数据包的接收和发送而设计,它并不倾向于对应于文件 系统的节点。内核与网络设备的通信与内核和字符设备、网络设备的通信方式完全不同,前 者主要还是使用套接字接口。 

SRAM、Flash、SDRAM、

磁盘的读写方式,UART、I2C、USB 等设备的接口以及轮询、中断、DMA 的原理,

PCI 总线的工作方式以及 CPU 的内存管理单元(MMU) 

虚拟机环境:

http://pan.baidu.com/s/1c08gzi4(密码为 puki) 

1.5.2 QEMU 实验平台

QEMU 模拟了 vexpress Cortex-A9 SMP 四核处理器开发板,板上集成了 Flash、SD、 I2C、LCD 等。ARM 公司的 Versatile Express 系列开发平台提供了超快的环境,用于为下一 代片上系统设计方案建立原型,比如 Cortex-A9 Quad Core。

在 http://www.arm.com/zh/products/tools/development-boards/versatile-express/index.php 上 可以发现更多关于 Versatile Express 系列开发平台的细节。

本书配套虚拟机映像中已经安装好了工具链,包含 arm-linux-gnueabihf-gcc 和 arm-linux- gnueabi-gcc 两个版本。

Linux 内核在 /home/baohua/develop/linux 目录中,在该目录下面,包含内核编译脚本:

第1章 Linux设备驱动概述及开发环境构建 11

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make LDDD3_vexpress_defconfig
make zImage -j8
make modules -j8
make dtbs
cp arch/arm/boot/zImage extra/
cp arch/arm/boot/dts/*ca9.dtb
cp .config extra/

由此可见,我们用的默认内核配置文件是 LDDD3_vexpress_defconfig。上述脚本也会自
动将编译好的 zImage 和 dtbs 复制到 extra 目录中。

extra 目录下的 vexpress.img 是一张虚拟的 SD 卡,将作为根文件系统的存放介质。它能
以 loop 的形式被挂载(mount),譬如在 /home/baohua/develop/linux 目录下运行。

sudo mount -o loop,offset=$((2048*512)) extra/vexpress.img extra/img

可以把 vexpress.img 的根文件系统分区挂载到 extra/img,这样我们可以在目标板的根文
件系统中放置我们喜欢的内容。

/home/baohua/develop/linux 目录下面有个编译模块的脚本 module.sh,它会自动编译内核
模块并安装到 vexpress.img 中,其内容如下:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules

extra/

12 Linux设备驱动开发详解:基于最新的Linux 4.0内核

sudo mount -o loop,offset=$((2048*512)) extra/vexpress.img extra/img
sudo make ARCH=arm modules_install INSTALL_MOD_PATH=extra/img
sudo umount extra/img

运行 extra 下面的 run-nolcd.sh 可以启动一个不含 LCD 的 ARM Linux。run-nolcd.sh 的内
容为 qemu-system-arm -nographic -sd vexpress.img -M vexpress-a9 -m 512M -kernel zImage -dtb
vexpress-v2p-ca9.dtb -smp 4 -append “init=/linuxrc root=/dev/mmcblk0p1 rw rootwait earlyprintk
console=ttyAMA0” 2>/dev/null,运行结果为:

baohua@baohua-VirtualBox:~/develop/linux/extra$ ./run-nolcd.sh
Uncompressing Linux… done, booting the kernel.
Booting Linux on physical CPU 0x0
Initializing cgroup subsys cpuset

Linux version 3.16.0+ (baohua@baohua-VirtualBox) (gcc version 4.7.3 (Ubuntu/
Linaro 4.7.3-12ubuntu1) ) #3 SMP Mon Dec 1 16:53:04 CST 2014

CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine model: V2P-CA9
bootconsole [earlycon0] enabled
Memory policy: Data cache writealloc
PERCPU: Embedded 7 pages/cpu @9fbcd000 s7232 r8192 d13248 u32768
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048
Kernel command line: init=/linuxrc root=/dev/mmcblk0p1 rw rootwait earlyprintk

console=ttyAMA0
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 513088K/524288K available (4583K kernel code, 188K rwdata, 1292K rodata,

247K init, 149K bss, 11200K reserved)
Virtual kernel memory layout:

vector : 0xffff0000 – 0xffff1000
fixmap : 0xffc00000 – 0xffe00000
vmalloc : 0xa0800000 – 0xff000000
lowmem : 0x80000000 – 0xa0000000
modules : 0x7f000000 – 0x80000000

.text : 0x80008000 – 0x805c502c
.init : 0x805c6000 – 0x80603c40
.data : 0x80604000 – 0x80633100

( 4 kB)
(2048 kB)
(1512 MB)
( 512 MB)
( 16 MB)
(5877 kB)
( 248 kB)
( 189 kB)
( 150 kB)

.bss : 0x80633108 – 0x806588a8
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
Hierarchical RCU implementation.

RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
NR_IRQS:16 nr_irqs:16 16
L2C: platform modifies aux control register: 0x02020000 -> 0x02420000
L2C: device tree omits to specify unified cache
L2C: DT/platform modifies aux control register: 0x02020000 -> 0x02420000
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 dynamic clock gating disabled, standby mode disabled
L2C-310 cache controller enabled, 8 ways, 128 kB

L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x46420001
smp_twd: clock not found -2
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956969942ns
Console: colour dummy device 80×30

运行 extra 下面的 run-lcd.sh 可以启动一个含 LCD 的 ARM Linux,运行结果如图 1.11
所示。

图 1.11 含 LCD 的 ARM Linux

除了 QEMU 模拟的 ARM 电路板以外,本书配套的 Ubuntu 中还包含一些直接可以
在 Ubuntu 上 运 行 的 案 例, 譬 如 /home/baohua/develop/training/kernel 中 就 包 含 了 globalfifo、
globalmem 等,这些目录的源代码都包含了 Makefile,在其中直接 make,生成的 .ko 可以直
接在 Ubuntu 上运行。 

 

1.5.3 源代码阅读和编辑

源代码是学习 Linux 的权威资料,在 Windows 上阅读 Linux 源代码的最佳工具是 Source Insight,在其中建立一个工程,并将 Linux 的所有源代码加入该工程,同步这个工程之后, 我们将能非常便捷地在代码之间进行关联阅读,如图 1.12 所示。

类似 http://lxr.free-electrons.com/、http://lxr.oss.org.cn/ 这样的网站提供了 Linux 内核源代 码的交叉索引,在其中输入 Linux 内核中的函数、数据结构或变量的名称就可以直接得到以 超链接形式给出的定义和引用它的所有位置。还有一些网站也提供了 Linux 内核中函数、变 量和数据结构的搜索功能,在 google 中搜索“linux identifier search”可得。 

在 Linux 主机上阅读和编辑 Linux 源码的常用方式是 vim + cscope 或者 vim + ctags,vim 是一个文本编辑器,而 cscope 和 ctags 则可建立代码索引,建议读者尽快使用基于文本界面 全键盘操作的 vim 编辑器,如图 1.13 所示。 

此时,我们只需要有一个感性认识,那就是,上述暂时陌生的元素都是 Linux 内核为字 符设备定义的,以实现驱动与内核接口而定义的。Linux 对各类设备的驱动都定义了类似的 数据结构和函数。

第2章
驱动设计的硬件基础

本章导读

本章讲述底层驱动工程师必备的硬件基础,给出了嵌入式系统硬件原理及分析方法的一 个完整而简洁的全景视图。

2.1 节描述了微控制器、微处理器、数字信号处理器以及应用于特定领域的处理器各自 的特点,分析了处理器的体系结构和指令集。

2.2 节对嵌入式系统中所使用的各类存储器与 CPU 的接口、应用领域及特点进行了归纳 整理。

2.3 节分析了常见的外设接口与总线的工作方式,包括串口、I2C、SPI、USB、以太网接口、 PCI 和 PCI-E、SD 和 SDIO 等。

嵌入式系统硬件电路中经常会使用 CPLD 和 FPGA,作为驱动工程师,我们不需要掌握 CPLD 和 FPGA 的开发方法,但是需要知道它们在电路中能完成什么工作,2.4 节讲解了这项 内容。

2.5 ~ 2.7 节给出了在实际项目开发过程中硬件分析的方法,包括如何进行原理图分析、 时序分析及如何快速地从芯片数据手册中获取有效信息。

2.8 节讲解了调试过程中常用仪器仪表的使用方法,涉及万用表、示波器和逻辑分析仪。 2.1 处理器

2.1.1 通用处理器

目前主流的通用处理器(GPP)多采用 SoC(片上系统)的芯片设计方法,集成了各种功 能模块,每一种功能都是由硬件描述语言设计程序,然后在 SoC 内由电路实现的。在 SoC 中,每一个模块不是一个已经设计成熟的 ASIC 器件,而是利用芯片的一部分资源去实现某 种传统的功能,将各种组件采用类似搭积木的方法组合在一起。

ARM 内核的设计技术被授权给数百家半导体厂商,做成不同的 SoC 芯片。ARM 的功耗 很低,在当今最活跃的无线局域网、3G、手机终端、手持设备、有线网络通信设备等中应用 非常广泛。至本书编写时,市面上绝大多数智能手机、平板电脑都使用 ARM SoC 作为主控 

 


Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注