描述
开 本: 16开纸 张: 胶版纸包 装: 平装是否套装: 否国际标准书号ISBN: 9787111449522丛书名: 电子与嵌入式系统设计丛书
译者序
序
前言
第1版前言
网站上的内容
嵌入式软件开发路线图
第1章嵌入式软件
1.1嵌入式应用的影响
1.1.1来自开发的挑战
1.1.2软件复用
1.1.3实时操作系统
1.1.4文件系统
1.1.5USB
1.1.6图形
1.1.7网络
1.1.8小结
1.2嵌入式系统的存储器
1.2.1存储器
1.2.2软件开发面临的挑战
1.2.3所有东西都会出错
1.2.4好的解决方法
1.3存储器架构
1.3.1选项
1.3.2平面单一地址空间存储器
1.3.3分段空间存储器
1.3.4单元切换空间存储器
1.3.5多地址空间存储器
1.3.6虚拟空间存储器
1.3.7高速缓冲存储器
1.3.8存储器管理单元
1.3.9小结
1.4软件是如何影响硬件设计的
1.4.1谁在设计硬件
1.4.2软件主导硬件
1.4.3软硬件的均衡
1.4.4硬件调试
1.4.5自检
1.4.6小结
1.5将软件移植到新处理器架构上
1.5.1特定目标
1.5.2RTOS问题
1.5.3处理器移植和开放标准
1.5.4小结
1.6汽车电子的嵌入式软件
1.6.1概要
1.6.2汽车电子特征
1.6.3编程问题
1.6.4实时操作系统因素
1.6.5小结
1.7芯片设计时如何选择CPU
1.7.1设计复杂度
1.7.2设计复用性
1.7.3存储器架构和保护
1.7.4CPU性能
1.7.5功耗
1.7.6成本
1.7.7软件问题
1.7.8多核SoC
1.7.9小结
1.8USB软件的介绍
1.8.1什么是USB
1.8.2USB外设
1.8.3USB通信
1.8.4USB软件
1.8.5USB和嵌入式系统
1.8.6小结
1.9走向USB3.0时代
1.9.1概述
1.9.2总线架构
1.9.3线缆和连接器
1.9.4封包路由
1.9.5双向协议流
1.9.6批量流
1.9.7USB3.0电源管理
1.9.8USB3.0集线器
1.9.9xHCI:新型主控制器接口
1.9.10USB的未来应用
1.9.11小结
扩展阅读
第2章设计和开发
2.1嵌入式系统软件开发的新兴技术
2.1.1微处理器技术
2.1.2系统架构
2.1.3设计组合性
2.1.4软件内容
2.1.5编程语言
2.1.6软件团队的规模和分布
2.1.7UML和建模
2.1.8关键技术
2.1.9小结
2.2选择开发工具
2.2.1开发工具链
2.2.2编译器特征
2.2.3嵌入式系统的扩展
2.2.4优化
2.2.5构建工具:简要介绍关键问题
2.2.6调试
2.2.7调试工具:关键问题的回顾
2.2.8标准和开发工具集成
2.2.9选择的暗示
2.2.10小结
2.3Eclipse:集成嵌入式开发工具
2.3.1介绍
2.3.2Eclipse平台的思想
2.3.3平台
2.3.4使用Eclipse进行嵌入式开发
2.3.5小结
2.4跨越RTOS界限的开发系统
2.4.1标准化是解决之道
2.4.2Eclipse解决方案
2.4.3Eclipse插件
2.4.4Eclipse授权
2.4.5Eclipse用户优势
2.4.6视图
2.4.7非嵌入式插件
2.5嵌入式软件和UML
2.5.1为什么要用UML建模
2.5.2从架构中分离应用
2.5.3xtUML代码生成
2.5.4小结
2.6用户界面开发
2.6.1用户界面的多样性
2.6.2用户界面的实现
2.6.3一个合理化的UI解决方案
2.6.4小结
2.7软件和功耗
2.7.1介绍
2.7.2软件问题
2.7.3软件中的功耗控制
2.7.4多核
2.7.5硬件问题
2.7.6虚拟编程
2.7.7小结
第3章编程
3.1为特殊存储器编程
3.1.1特殊存储器
3.1.2非易失性RAM
3.1.3共享存储器
3.1.4小结
3.2嵌入式系统中的自检
3.2.1存储器测试
3.2.2I/O设备
3.2.3多线程问题
3.2.4看门狗
3.2.5自检失败
3.2.6最后一些要点
3.3命令行解释器
3.3.1嵌入式系统的诊断功能
3.3.2让嵌入式系统开始运行
3.3.3命令行解释器—需求
3.3.4设计命令行解释器
3.3.5命令行解释器的实现
3.3.6命令行解释器的原型代码
3.3.7小结
3.4嵌入式软件应用:交通信号灯
3.4.1应用程序
3.4.2硬件配置
3.4.3程序的实现
3.4.4主循环
3.4.5中断
3.4.6延时
3.4.7信号灯
3.4.8使用全局变量
第4章C语言
4.1共同变量
4.2C函数的原型
4.2.1在函数原型之前
4.2.2函数原型的应用
4.2.3使用函数原型
4.3中断函数和ANSI关键字
4.3.1中断函数
4.3.2ANSICconst关键字
4.3.3ANSICvolatile关键字
4.4从位开始
4.4.1位运算
4.4.2二进制常量
4.4.3结构体中的位域
4.4.4微处理器位域指令
4.4.5I/O设备和位域
4.4.6小结
4.5浮点数在编程中的应用
4.5.1示例
4.5.2程序实测
4.5.3问题的解答
4.5.4从教训中学习
4.6从不同的角度看待C语言
4.6.1静态数据
4.6.2关于分号
4.6.3指针和指针运算
4.6.4聪明反被聪明误
4.6.5小结
4.7减少函数调用的开销
4.7.1编译器和结构化代码
4.7.2内联函数
4.7.3函数调用
4.7.4参数传递
4.7.5局部存储
4.7.6生成堆栈帧
4.7.7返回值
4.7.8小结
4.8精通结构布局
4.8.1关键概念
4.8.2位域
4.8.3提示和技巧
4.9C语言编程和存储器
4.9.1存储器
4.9.2段
4.9.3小结
4.10C/C++中的指针和数组
4.10.1指针和指针运算
4.10.2数组和指针
4.10.3小结
4.11C/C++中的动态存储
4.11.1C/C++存储空间
4.11.2C语言中的动态存储
4.11.3C++中的动态存储
4.11.4和动态存储相关的问题
4.11.5存储空间碎片化
4.11.6RTOS中的存储管理
4.11.7实时存储解决方案
4.11.8小结
第5章C++
5.1从管理的角度看嵌入式系统中的C++
5.1.1嵌入式系统开发团队
5.1.2面向对象编程
5.1.3团队管理和面向对象方法
5.1.4作为面向对象语言的C++
5.1.5开销
5.1.6前方的路
5.2为什么要从C转向C++
5.2.1隐藏具体实现的细节
5.2.2重用类的代码
5.2.3重用通用的类
5.2.4扩展操作符的功能
5.2.5从基类中衍生新的类
5.2.6通过函数原型避免错误
5.2.7增加函数参数而不改变调用语句
5.2.8使用更加简单和安全的I/O
5.2.9通过内联函数提升性能
5.2.10重载函数名
5.2.11对嵌入式系统的支持
5.2.12转变的代价
5.2.13向C++中引入C代码
5.2.14难点:设计对象
5.2.15如果没有出现问题,就不要去改变
5.3扫清通向C++的障碍
5.3.1过渡策略
5.3.2循序渐进
5.3.3实现可重用性
5.3.4编写CleanC代码
5.3.5C+:接近C++
5.3.6小结:前方的路
5.4C++模板的优势与劣势
5.4.1什么是模板
5.4.2模板的实例化
5.4.3模板带来的问题
5.4.4多个模板参数
5.4.5模板的其他应用
5.4.6小结
5.4.7后记
5.5C++的异常处理
5.5.1C语言中的错误处理
5.5.2异常和中断无关
5.5.3C++的异常处理
5.5.4特殊情况
5.5.5EHS和嵌入式系统
5.5.6小结
5.6C++的代码大小和性能
5.6.1C++比C语言更高效吗
5.6.2C++对内存需求的影响
5.6.3正确使用C++
5.6.4小结
5.7C++中的只写端口
5.7.1封装专业知识
5.7.2问题的定义
5.7.3C语言的解决方案
5.7.4使用C++进行尝试
5.7.5重载操作符
5.7.6对wop类进行增强
5.7.7可重入性
5.7.8使用RTOS
5.7.9封装专业知识
5.7.10其他的可能性
5.7.11前方的路
5.8在C++中使用非易失性RAM
5.8.1程序编制对类定义的需求
5.8.2NVRAM的实现
5.8.3C++的nvram类
5.8.4继续改进nvram类
5.8.5小结
扩展阅读
第6章实时性
6.1实时系统
6.1.1实时系统的实现
6.1.2处理循环
6.1.3中断
6.1.4多任务
6.1.5使用实时操作系统
6.2嵌入式系统的可视化程序模型
6.2.1哪种程序模型最适合用来构建实时系统
6.2.2为何要为实时系统建立模型
6.2.3各种模型之间有什么不同,各有什么优缺点
6.2.4什么是单线程程序模型
6.2.5单线程程序模型有什么优缺点
6.2.6轮询循环是不是一个单线程程序
6.2.7状态机是不是一个单线程程序
6.2.8什么是多线程系统
6.2.9多线程程序模型有哪些优缺点
6.2.10多线程真的同时运行吗
6.2.11如何获取实时系统的多线程环境
6.3嵌入式系统的事件处理
6.3.1事件
6.3.2信号和事件是不是同一回事
6.3.3什么样的事件是时间敏感的
6.3.4当侦测到一个异常,微处理器如何处理
6.3.5所有的异常都一样吗
6.3.6同步异常
6.3.7异步异常
6.3.8中断是如何产生的和服务的
6.3.9CPU保存的状态是什么
6.3.10机器状态就是线程状态吗
6.3.11异常处理程序应该用汇编语言还是C语言来写
6.3.12怎样避免在异常处理程序上花费时间
6.4中断程序
6.4.1设置中断
6.4.2中断服务例程
6.4.3中断向量
6.4.4初始化
6.4.5小结
第7章实时操作系统
7.1RTOS的调试技术
7.1.1概要
7.1.2多进程的概念
7.1.3执行环境
7.1.4与目标机连接
7.1.5调试模式
7.1.6RTOS级的调试功能
7.1.7代码共享
7.1.8任务级的断点
7.1.9任务相关性
7.1.10内存管理单元
7.1.11多处理器
7.1.12小结
7.2自己开发的RTOS调试解决方案
7.2.1任务级调试的实现
7.2.2任务级调试工具
7.2.3小结
7.3调试:堆栈溢出
7.4何时考虑使用商业化RTOS
7.4.1商用化RTOS和自己开发RTOS
7.4.2商业化RTOS的优点
7.4.3商业化RTOS的缺点
7.4.4为什么要自己开发RTOS
7.4.5不自己开发RTOS的理由
7.4.6小结
7.5移植RTOS
7.5.1从一个RTOS转移到另一个RTOS
7.5.2代码移植
7.5.3封装
7.5.4驱动和其他
7.5.5调试问题
7.5.6小结
7.6RTOS驱动程序开发简介
7.6.1设备驱动的两个方面
7.6.2数据损坏
7.6.3线程控制
7.6.4程序逻辑
7.6.5小结
7.7调度算法和优先级反转
7.7.1概要
7.7.2实时性需求
7.7.3调度算法
7.7.4操作系统和应用的含义
7.7.5小结
7.8时间与优先级调度比较
7.8.1RTOS调度
7.8.2理想世界
7.8.3现实世界中的优先级调度
7.8.4不释放控制权的时域限制
7.8.5释放控制权的时域限制
7.8.6小结
7.9嵌入式文件系统
7.9.1嵌入式文件系统的需求
7.9.2MS-DOS文件系统介绍
7.9.3长文件名
7.9.4格式化
7.9.5分区
7.9.6设备
7.10OSEK:一种RTOS标准
7.10.1OSEK简介
7.10.2OSEK需求
7.10.3OSEK的任务
7.10.4报警
7.10.5错误处理
第8章网络
8.1Wi-Fi简介
8.1.1无线数据通信
8.1.2IEEE802.
8.1.3802.11基础知识
8.1.4Wi-Fi和蓝牙
8.1.5发展前景
8.2哪些人需要Web服务器
8.2.1简介
8.2.2三个重要的功能
8.2.3Web服务器的运行
8.2.4Web服务器功能总结
8.2.5其他需要考虑的地方
8.2.6小结
8.3SNMP介绍
8.3.1为什么使用SNMP
8.3.2网络管理者的职责
8.3.3架构模型
8.3.4公众的误解
8.3.5应用级的管理者和代理
8.3.6如何编写MIB
8.3.7术语
8.3.8结论
8.4下一代互联网协议:IPv
8.4.1互联网协议的局限
8.4.2IP第6版介绍
8.4.3双栈简化过渡
8.4.4IPv6如何工作
8.4.5RFC支持
8.5DHCP基础
8.5.1DHCP服务器
8.5.2工作原理
8.5.3RFC支持
8.6NAT详解
8.6.1NAT详解
8.6.2RFC支持
8.6.3支持的协议
8.6.4应用级网关
8.6.5私有网络地址分配
8.7PPP:点对点协议
8.7.1介绍
8.7.2PPP如何工作
8.7.3PPP详解
8.7.4RFC支持
8.8SSL介绍
8.8.1介绍
8.8.2SSL如何工作
8.8.3一些SSL细节
8.9DHCP调试小技巧
8.10IP多播
8.10.1多播初始化
8.10.2IGMP协议
8.10.3多播的实现
8.10.4小结
第9章开源软件、嵌入式Linux和Android
9.1嵌入式开发的GNU工具链:构建还是购买
9.1.1介绍
9.1.2工具链的组件
9.1.3构建工具链
9.1.4验证工具链
9.1.5测试的各种选择
9.1.6小结
9.2嵌入式Linux简介
9.2.1简介
9.2.2使用开源的挑战
9.2.3OpenEmbedded
9.2.4理解元数据
9.2.5项目流程
9.2.6小结
9.3Android架构和开发
9.3.1Android技术简介
9.3.2Android架构
9.3.3应用开发
9.3.4AndroidUI
9.3.5在移动设备以外的市场拓展Android
9.3.6总结
9.4垂直市场上的Android、Meego和嵌入式Linux
9.4.1介绍
9.4.2垂直市场有什么不同
9.4.3Android的吸引力
9.4.4MeeGo的前途
9.4.5多才多艺的嵌入式Linux
9.4.6小结
第10章多核嵌入式系统
10.1多核简介
10.1.1系统架构
10.1.2功耗
10.1.3挑战
10.2多核:多个操作系统
10.2.1AMP的SMP硬件
10.2.2AMP硬件系统
10.2.3AMP软件架构
10.2.4IPC的重要性
10.2.5AMP开发工具
10.2.6困难
10.2.7AMP应用案例
10.2.8使用Hypervisor
10.2.9小结
10.3选择多核的多操作系统
10.3.1介绍
10.3.2操作系统的类型
10.3.3选择操作系统
10.3.4多核系统
10.3.5小结
10.4CPU与CPU的通信:MACPI
10.4.1介绍
10.4.2多核
10.4.3MACPI
10.4.4小结
后记
当我从编辑手里拿到这本书的时候,我一眼就看到作者Colin Walls。虽然当时我的另外一本译作《解读云计算》还没有完成,但是我当即决定接下本书的翻译工作。
认识Colin可以追溯到1994年年底,那个时候我创办的公司开始与美国Microtec Research合作,于是我经常参加公司技术培训和全球的销售会议。来自英国分公司的Colin是资深FAE,他是个个子高高,讲话很慢的人。他的讲演很清楚,在内容上总是能够谈及关于嵌入式软件工具的很深入的问题。更多地了解Colin是通过本书多次提到的《NewBits》杂志,在上面我经常会看到他写的文章,比如《使用背景调试模式》就对我们当时基于Motorola 68360系列芯片软件的开发工作非常有帮助。
Colin在本书第1版前言中就已经提到,本书的许多内容来自《NewBits》。这本杂志原来是Microtec Research的一份季刊,从当初简单的公司新闻刊物变成了一份技术杂志。即使在公司被Mentor Graphic收购之后,该刊仍然坚持出版了一段时间。在1996~1997年期间,我们在中国出版了4期中文版(《嵌入式软件产品与应用》)。中文版除了翻译部分《NewBits》的技术文章外,还邀请北京航空航天大学计算机系金惠华教授和成都电子科技大学熊光泽教授,以及他们的学生为杂志撰文。我和我的同事江文瑞也为中文版撰写过技术文章。当然,Colin的文章总是我们的首选,比如另外一篇《在嵌入式系统中使用C++编程语言》在当时就很受关注。
正如硅谷嵌入式资深人士Jack Ganssle介绍的,Colin是一个老手,本书给大家分享了他丰富经验和实际“如何做”的忠告。通过阅读本书,你会受益匪浅。本书的内容很广泛,覆盖嵌入式软件设计方法、工具、语言、RTOS、网络和USB。这样广泛的题材得益于Colin所工作过的Microtec Research和Mentor Graphic嵌入式事业部,这两家公司都具有嵌入式软件开发完整的产品线。比如Microtec Research的Microtec嵌入式C/C++ 编译器、XRAY调试器和VRTX RTOS都是在历史上极具影响力的技术和产品。
除了Colin本人的文章,书中引用了Jim Ready关于实时内核的文章,Jim是著名的VRTX RTOS的作者,也是提供商业RTOS的第一人,曾经创办过Ready System和后来的嵌入式Linux公司——Montavista。书中还使用了Neil Henderson关于嵌入式网络协议的文章,他曾经是Accelerated Technology的CEO,主持过著名的开源项目Nucleus RTOS的开发。这些重量级人物的文章为本书增色不少。
本书的第1版于2006年出版,第2版则于2012年出版。6年时间嵌入式软件发生了很大的变化,作者也相应进行了更新,比如书中增加了USB 3.0的知识,代码示例也从以前基于68K芯片转为PowerPC。更重要的是第2版新增加了多核设计和开源的嵌入式软件这两章,它们正好体现了嵌入式系统处理器技术和软件技术最新的发展,即在过去6年间,嵌入式硬件平台从使用单片的嵌入式处理器发展成多核的、SoC的嵌入式处理器(包括MCU),嵌入式软件平台也从基于RTOS开发转变到基于开源和面向应用的平台开发,比如基于Linux和Android平台。
本书的第1、2、6、7章是由张皓中翻译,第3、4、5章由何灵渊翻译,第8、9、10章由何小庆翻译,全书由何小庆统稿和审校。在翻译过程中,我们借鉴了由沈建华老师主持翻译的本书第1版——《嵌入式软件概论》(北京航空航天大学出版社),这本书对于我们更好地理解原文起了重要的作用。沈老师主持的翻译工作非常出色,不过我们也按照自己的理解对一些细节的翻译做了修正。我还要感谢本书的策划编辑张国强先生,他申请到的图片和电子稿,为我们工作在不同地区的翻译团队成员带来了极大的方便,他对工作的热情和执着也着实感动了我。
最后,希望本书的读者能从本书的阅读中受益。我们的翻译如有不足和纰漏之处,还请读者指出。
何小庆
序
你期待着什么?完美?
Jack Ganssle的一些想法……
为什么许多固件项目都不能按时完成,而且充满着各种各样的bug?我们可以从很多方面解释这个问题,比如软件太过复杂等。不过,我相信做不好并不是我们的错,因为真正做到完全不出错的一定是超人类,很显然我们都不是。
原始人并不追求每次捕猎都能得手,他们只需要填饱肚子;农民不会期待全部的种子都发芽,总有一些会浪费掉;商人都希望吸引消费者,但他们不可能让所有人都满意。
得到全A的孩子会让爸妈惊喜异常,但是A也不代表着完美,90%的正确率就已经是A了。在生活中,我们并不需要完美,往往达到A的标准就已经足够了。
但是在软件行业,90%的正确率已经是灾难了,做出的产品根本不能用。即使99.9%的正确率,产品也是垃圾一个,因为每十万行代码中就会有100个错误。很明显,这样依然不够。也就是说,虽然我们不是完人,但是我们写出的软件却需要无限趋近完美。
如果系统只有100行,每个人都可以达到完美。但是对于大规模的软件而言,达到完美需要极大的投入。就像牛仔需要不断地将掉队的牛赶回牛群一样,程序员也需要看护好程序中的每一个字节。但是随着牛群的壮大,牛仔会越来越忙,程序员也是如此。
那么解决方案是什么,究竟有解决方案吗?固件需要做到多完美呢?我们对于完美的执著真的是白费力气么?
复杂系统是这个世界的新生事物。早期的半导体收音机中最多有五六个元件,电视机中有15~20个真空管,两者使用的晶体管数目是差不多的。等到了20世纪40年代,由于ENIAC电脑中有18 000个真空管,工程师们不得不用购物车装满元件,不断进行维护工作。而一个有25年历史Z80芯片,就有ENIAC 1/4个晶体管数量,其管芯(Die)面积也只有ENIAC使用的单个电阻一样大。
如今,单独一个奔腾IV处理器之中有4500万个晶体管,一个比较大的内存芯片则有大概2.5亿个晶体管。根据Intel的预测,在几年之内他们制造的处理器将能够搭载10亿个晶体管。即使是最简单的嵌入式系统,比如电子贺卡,其上也会有数千个活动的单元。
软件的发展更加快速,特别是对于嵌入式系统而言。1975年,程序是在纸带和磁带上存储的,控制台则是电传打字机,所以1万行的汇编代码已经是非常庞大的工程了。而在今天,1万行C代码(大约等同于四五万行汇编代码)已经是很小的程序了。另一个例子是我们的手机。手机的开发时间很短,尺寸小和功耗低,但其中却可能有超过500万行的C和C++代码。
存储器占用是另外一个衡量软件规模的指标。1975年256字节(是的,你没有看错)的EPROM可以存储4k大的程序空间,需要16片存储芯片,即使是一个很小的嵌入式系统的造价也不菲。今天呢?128k闪存对于一个小型的应用而言也微不足道。处理器之所以会从8位发展到16位,再到32位,更多的是因为对地址空间需求的增加,而不是处理速度。
在20世纪70年代末期,Seagate推出了首款Winchester硬盘,它的容量是10Mb,重量有4.5公斤,单价则是达到了1500美元。在那时,5MB就已经远远超过人们的需求了。如今,我们可以轻松地把20GB的硬盘买来装在口袋里,并在眨眼间就把它装满。
所以说,我们的系统在规模和复杂性上都已经达到了空前的水平。不过,我们真的应付得来么?即使是很简单的系统,我们也难以做到完美,而大型的系统则永远会有缺陷。随着软件规模的增长,其中组件间的关系也会变得十分复杂。这样的复杂性更多的时候是工程的必需,而不是因为设计得不好。
硬件同样很难达到完美。即便是成熟的处理器,也会有一个错误列表。奔腾系列的一个鲜为人知的除法错误只是冰山一角。像奔腾III的错误列表(后来改名规格更新表)之中就记录了83个问题,Motorola(摩托罗拉)MPC555则有接近100个问题。
现在的嵌入式系统有多可靠?没有人能够回答,也没有人针对这个问题进行研究。事实是,我们手头有不少数据,其中许多都不太乐观。
当年,火星探路者号探测器项目取得了空前的成功,除了在下降阶段出现了一个严重的软件错误。一个在地球上被认为是小瑕疵的优先级反转问题引发了更多的错误。万幸的是,因为看门狗程序设计得很好,探测器的任务最终没有失败。这个例子生动地告诉我们,额外的外部软硬件能帮助我们有效地应对预料之外的软件错误。
硬件和软件的规模和复杂性今非昔比。早先的微处理器中,探路者号上的优先级错误根本不可能出现,因为那时的应用根本就不需要使用RTOS。今天,大多数嵌入式系统都运行着操作系统,这些设备都可能出现类似探路者号的问题。
作为开发者,面对爆炸性增长的系统复杂性,我们应该怎么办?我们肯定需要不断学习新知识和巩固旧知识。从C语言的基础到UML,我们需要不断为自己充电,像你手中的这本书就是非常好的学习资料。Colin是位资深嵌入式专家,他会给你许多关于实际操作的建议。
我们确实可以从经验中学习,但是积累知识毕竟还是更为有效的学习方法。比学习知识更有效的方法则是从大师那里汲取智慧。花一点时间阅读本书,你就能从大师那里得到重要的启示。最终,有了独特的视角和强大的工具,你将能够解决更加复杂的问题。
在追求完美的过程中,我们也许会感到困惑,但是有智慧的开发者会孜孜不倦地寻找通向完美的道路。
前 言
自本书第1版出版之后,世界在前进,许多事情变了,也有许多事情没变。随着处理器和技术的普及,嵌入式软件领域也得到了发展。嵌入式软件工程师的事件也在变化,Elsevier的工程师们建议我升级本书的第1版,而我也欣然同意。
本书第2版的许多章节中都新增了内容,而且增加了关于开源软件和多核的两个章节。除此之外,我还去掉了一些不太相关的内容。
我保留了第1版的前言,不过我需要在这里对下面的贡献者表示诚挚的谢意:Vlad Buzov、Dan Driscoll、Christopher Hallinan、Waqar Humayan、Geoff Kendall、Russel Klein、John Lehmann、Shabtay Matalon、Mark Mitchell。
然后是我个人最近的一些情况。尽管我病重的爱人接受了非常好的治疗,她还是没能坚持得更久,她于2006年6月离开了我们。积极治疗为她争取了两年的时间,也为我们带来了更多宝贵的回忆。现在,我和我的女儿们生活在一起。我依然在Mentor Graphics从事与嵌入式软件相关的工作。
我想再一次感谢我的上司,感谢他们同意将本书的获利捐赠给LINC,我相信这笔钱会花在有用的地方。
Colin Walls
2012
第1版前言
本书的背景
我不知道这个世界有没有拟定生活计划并且严格执行的人,不过我相信是有的。但是对于我们之中的大多数人而言,即使我们有对未来的憧憬和想法,我们也不得不为身边种种的随机事件疲于奔命。我正是处于这样的状况。我为Accelerated Technology工作,它是Mentor Graphics的一个分支,专长是嵌入式软件设计、开发,工具研发和操作系统。多年来,公司几经易手,我也接触到了各式各样的工作。最近我在做一些市场营销,帮助欧洲和北美的人士了解公司的产品和背后的技术。我喜欢我的工作,也喜欢和我的同事们一起工作,我时常称呼自己是一位“专业的爱好者”。 有时这项工作也是十分辛苦的,需要花很多的时间在路上(坐飞机和汽车)或者等待某一样东西。很多的时候我都不在家,不过我觉得这是得到这份好工作的代价。但是,后来发生的一件事情改变了一切……
2004年的仲夏,我的爱人被诊断出患有急性髓细胞白血病,并被收治住院。我需要照顾我的两个女儿,并陪伴我的爱人,因此我的工作生活也就退到了次要的位置。从夏天到年末,我爱人一直在接受放疗。在这期间,我们经历了起起落落,不过效果也很明显。在我撰写本书的时候,她的情况有了很大的好转,每个月会验血检查疗效。
俗话说,患难见真交,此话不假。这段时间之中,我更加确定自己选对了工作的地方。我的上司和同事给予了我莫大的支持,我觉得十分亏欠他们(我会在后面列出他们的名字)。在一段时间内,我肯定不能继续我原来的工作了。我现在没有压力,不过我也在想,我能做些什么有用的,适合我新的生活方式的事情。在很长一段时间内,我一直酝酿着写一本书。我把这个想法告诉了公司管理层,他们认为这是个很好的计划。
本书是从哪里来的
我的上一本书是出版于1986年的《Programming Dedicated Microprocessors》(Macmillan Education,1986),距现在已经接近20年了。那本书是讲述嵌入式软件的,这个概念在那个时候还不是很常用。写一本书是一种个人实现,而那书也是我十分得意的收藏之一。写一本书也十分费时。当我写那一本书的时候,工作并不繁忙,而且我也没有孩子,所以抽出时间并不是很难。在那之后,我时常有写书的新想法,但却一直没有时间付诸实现。
尽管如此,这几年我也一直在写作——大量的技术文章、会议论文、培训材料和演讲稿。后来我有一个新想法:为什么不把这些内容整理成一本书呢?为了简化这一过程,我主要在Accelerated Technology内部收集资料,这家公司拥有这些资料的版权。后来确实得到他人贡献的一些文章,不过这是后话了。
在Microtec Research有一份名叫《NewBits》的季刊,这份刊物从当初简单的新闻刊物变成了一个技术杂志。在20世纪90年代早期,我是这本书的贡献者之一。在Mentor Graphics收购Microtec之后,《NewBits》继续出版了一段时间,但最终还是停刊了。最近,公司收购了Accelerated Technology,并重整了旗下的嵌入式软件团队。在这之后,我们决定继续《NewBits》的出版,而杂志也越办越好。我收集了《NewBits》的每一期,把全部文章都放在手边。我很快确定了数篇适合收录的文章,其中不少来自于我自己,也有一些出自其他作者之手。其他的材料包括一些白皮书和另一份Accelerated Technology的刊物《Nucleus Reactor》。
我尽可能地减少对原文的修改。一些文章基本上完全不需要改动,其他的一些要么需要更新,要么需要去掉和产品相关的信息。每篇文章都通过一个简要的说明来介绍其来源和内容。
本书的内容
在选择本书的原材料时,我的目标是确保每一篇文章都与现今的嵌入式软件开发流程和技术相关。当然了,许多文章是从历史的角度阐述的,不过这并不意味着它们就会被收录。有些文章涉及的技术没有流行起来,或者已经被新的技术所替代,这导致它们被排除在本书之外。这些过时的主题也许会在我撰写《A History of Embedded Software》一书时提到。我计划在嵌入式软件出现50年之际出版那本书(也就是2020年,Intel 4004发布50年纪念的时候)。
本书中包含的文章涵盖了嵌入式软件的方方面面:设计、开发、管理、调试、授权和重用。
本书的目标读者
如果你对嵌入式软件感兴趣,本书一定会有适合你的内容。本书中的文章涵盖了非常广泛的内容,无论你是初学者还是老手,都能从中获益。如果你来自传统的软件领域,一些文章会帮助你从更加偏向硬件的角度看待问题;如果你来自硬件领域,你会有机会了解关于软件的一些内容。
如果你从事教学(学术或者商业培训),书中的许多文章会为你的学生提供很好的背景材料。光盘中的内容考虑到了这样的需要。详情请参考前言后面“光盘中的内容”一节。
如何使用本书
本书并没有一个“正确”的使用方法。我已经将文章的出现次序进行了优化,适合从前往后读的顺序。同时我尽可能地将文章按章节分类,并添加了文章之间的引介,帮助你找到感兴趣的内容。
致谢
下面这段话看起来很像是奥斯卡获奖感言,但这也是没有办法的事情。
在提及具体人名之前,我想要先说一些笼统的感言。我和Accelerated Technology以及Mentor Graphic的许多同事都讨论过这本书,他们给予了我很大的鼓励。他们的热情感染了我,让我受益匪浅。
当我和Elsevier的人们一起工作的时候,Carlos Lewis是我的编辑,也是本书的项目策划。有的时候,任务会被交给Tiffany Gasbarrini,她一路都在支持着我。和他们的合作一直是非常愉快的。他们的专业精神令人钦佩,他们给我的引导也让我颇为受益。
我一直非常喜爱Jack Ganssle的作品,无论是他的书,还是他在《Embedded System Programming》杂志中的专栏。他给我们带来了非常实用的技术信息,还时常通过幽默的方法引导我们思考。当我策划本书的时候,我向他征询意见,他毫无保留。当他同意为本书撰写“序”的时候,我也感到十分高兴。谢谢他,Jack。
我需要感谢我的上司和同事,他们一直在我身边支持我,并在我遇到困难时出手相助。他们帮助我保持理智(也许),让这本书成为可能。Neil Henderson、Robert Day、 Michelle Hale、 Gordon Cameron、 Joakim Hedenstedt等人都帮助了我,当然还有其他更多的人。谢谢他们。
我在前面已经提及,本书中的许多材料来自Microtec Research的技术刊物《NewBits》,所以我对于所有对此刊物有贡献的人都心存感激。Lucille Woo是《NewBits》的责任编辑,他将一个新闻刊物发展成了技术杂志。杂志的图像编辑和设计师是Gianfranco Paolozzi。在Microtec,许多人都对杂志有着不同程度的贡献,比如Eugene Castillo、 Melanie Gill和Rob van Blommestein。《NewBits》在Accelerated Technology的“复活”是由Charity Mason领导的,他提出了一套行之有效的解决问题的方法。
商业领域和“法律”二字相关的内容都让我感到很不自在。虽然所有与此相关的流程都是必需的,但是我依然要感谢Mentor Graphics采购部的Jodi Char
嵌入式软件
本章的文章要么设定一个场景,提供一些关于嵌入式软件究竟是什么的大致观点,要么强调一些在其他章节中不会再涉及的内容。
1.1嵌入式应用的影响
本文很像是一篇“设定场景”的文章,它基于我2003年后半年为《NewBits》写的一篇文章和我在多个研讨会上的演讲稿完成。本文介绍了许多会在本书其他章节更加详细描述的关于嵌入式软件的话题和概念。
——作者
嵌入式系统无处不在,人们已经完全无法离开它们了。一个美国家庭平均拥有将近40个微处理器,这个数字还未将个人电脑(一般每台电脑都贡献了额外的5~10个微处理器)或汽车上(典型的情况是含有几十个微处理器)所拥有的微处理器囊括在内。而且有人预言这些数字将在未来10年或20年内呈现几个数量级的增长。然而,相当具有讽刺意味的是,大多数不从事电子设计的人们还完全不知道“嵌入式”到底意味着什么。
营销人员都喜欢市场分段。这个理论说的是这样的分析以特定的方式通过满足各个分段的需求来生产出更好的产品。对嵌入式来说,我们最终可以将其分割成通信、军事/航天、过程控制、消费电子和自动化等分段。尽管生产的越来越多的设备并不满足这个模型。比如,一个带有摄像头的手机属于电信产品还是消费产品?有谁在乎么?人们可能只对这样的应用的通用性感兴趣。针对它们,我们所能做出的主要评价就是每台设备上的软件数量正以一种今非昔比的速度在增长。本书中,我们将看一看这些软件的内部工作原理。我们找来做例子的应用是从消费电子分段中得到的——?一台数码相机,之所以选择它是因为无论你是否在用消费电子产品,你多少对它们的功能和操作有所清楚。
1.1.1来自开发的挑战
消费电子应用具有严格的上市时间约束,并且对成本极度敏感。这带来了软件开发中的一些有趣的挑战。
多处理器
多处理器的嵌入式系统设计正变得越来越普遍。市场研究表明,在不久的将来,多处理器设计将成为常态。数码相机通常有两个CPU:一个用于图像处理,另一个用于相机的一般操作。多处理器设计面临的最大挑战在于调试。每个独立设备上的代码可能比较好调试,因为用于调试的工具和技术都很好理解。但当两个处理器之间有交互时,挑战就出现了。显然,这时候需要一种用于解决系统调试问题的技术,即多核调试技术。
有限的存储器
嵌入式系统的存储器往往是有限的。存储器容量可能不小,但通常不会根据需要而增加。对于消费电子应用,综合考虑成本和功耗最终使得存储器容量受到约束。传统的嵌入式软件工程师已经练就了在有限存储器环境下的编程技能。如今,汇编语言已经不再是一个明智的选择了。全面了解如何充分利用C语言和最优化的效果和局限性是至关重要的。
如果使用C++(这有可能是一个绝佳的选择),开发人员必须充分了解该语言是如何实现的。否则,可能到了截止时间,项目所需的存储器容量和实时性才会很明确,而此时重新设计软件已经不可能了。谨慎选择C++工具相当重要,特别是为嵌入式系统提供支持的时候。
用户接口
任何设备上的用户界面(UserInterface,UI)都是非常重要的。产品的成功与否直接取决于其质量。对消费产品来说,这是一种势不可挡的影响。如果用户发现用户界面很笨拙或很不方便,他们的坏感觉可能不只针对这款产品,整个品牌都会受到影响。在需要更新产品的时候,消费者就会转而选择其他产品。
所以,一个良好的用户界面并非可有可无。但说得容易做到难。大多数情况下,用户界面并不是由硬件实现的。比如,数码相机的各种功能控制都是由软件来定义的,即便是一个基本模型,都可能会有许多控制操作。因此,理想的开发顺序应该是:
评论
还没有评论。