第1篇 高性能嵌入式系统的基础知识
第1章 高性能嵌入式系统 3
1.1 技术要求 3
1.2 嵌入式系统的元素 3
1.2.1 电源 5
1.2.2 时基 5
1.2.3 数字处理 6
1.2.4 内存 6
1.2.5 软件和固件 6
1.2.6 专用集成电路 7
1.2.7 来自环境的输入 7
1.2.8 输出到环境 8
1.2.9 网络通信 8
1.3 嵌入式系统架构设计 8
1.4 物联网 9
1.5 实时运行 10
1.5.1 周期性操作 10
1.5.2 事件驱动操作 12
1.5.3 实时操作系统 13
1.6 嵌入式系统中的 FPGA 14
1.6.1 数字逻辑门 15
1.6.2 触发器 17
1.7 FPGA的元素 18
1.7.1 查找表 18
1.7.2 触发器 19
1.7.3 块RAM 19
1.7.4 DSP切片 19
1.7.5 其他功能元件 20
1.8 FPGA综合 20
1.8.1 硬件设计语言 20
1.8.2 在嵌入式系统设计中使用FPGA的好处 22
1.8.3 赛灵思FPGA和开发工具 23
1.9 小结 24
第2章 感知世界 25
2.1 技术要求 25
2.2 无源、有源和智能传感器介绍 25
2.3 应用模数转换器 27
2.4 嵌入式系统中使用的传感器类型 30
2.4.1 光 30
2.4.2 温度 31
2.4.3 压力 31
2.4.4 湿度 32
2.4.5 流体流量 32
2.4.6 力 32
2.4.7 超声波 33
2.4.8 音频 33
2.4.9 磁 33
2.4.10 化学 34
2.4.11 电离辐射 34
2.4.12 雷达 35
2.4.13 激光雷达 35
2.4.14 视频和红外线 35
2.4.15 惯性 36
2.4.16 全球定位系统 36
2.5 与传感器通信 37
2.5.1 通用输入/输出接口 37
2.5.2 模拟电压 41
2.5.3 I2C 42
2.5.4 SPI 44
2.5.5 CAN总线 45
2.5.6 无线 46
2.6 处理传感器数据 47
2.7 小结 48
第3章 实时操作 49
3.1 技术要求 49
3.2 实时的概念 49
3.3 实时嵌入式系统的属性 50
3.3.1 执行多项任务 51
3.3.2 速率单调调度 58
3.4 了解关键的RTOS功能和挑战 60
3.4.1 互斥锁 60
3.4.2 信号量 61
3.4.3 队列 62
3.4.4 事件标志 62
3.4.5 定时器 63
3.4.6 动态内存分配 63
3.4.7 内存泄漏 64
3.4.8 堆碎片 64
3.4.9 死锁 65
3.4.10 优先级反转 66
3.5 流行的实时操作系统 70
3.5.1 实时操作系统的关键技术属性 70
3.5.2 实时操作系统的非技术属性 71
3.5.3 embOS 72
3.5.4 FreeRTOS 72
3.5.5 INTEGRITY 73
3.5.6 Neutrino 73
3.5.7 µc/OS-III 74
3.5.8 VxWorks 74
3.6 小结 75
第2篇 设计和构建高性能嵌入式系统
第4章 开发你的第一个FPGA项目 79
4.1 技术要求 79
4.2 在实时嵌入式系统设计中使用FPGA 79
4.2.1 块RAM和分布式RAM 80
4.2.2 FPGA I/O引脚和相关功能 82
4.2.3 专用硬件资源 83
4.2.4 处理器核心 84
4.3 FPGA实现语言 84
4.3.1 VHDL 84
4.3.2 Verilog 86
4.3.3 原理图 86
4.3.4 C/C++ 88
4.4 FPGA开发过程 88
4.4.1 定义系统需求 88
4.4.2 将功能分配给FPGA 89
4.4.3 确定所需的FPGA功能 89
4.4.4 实现FPGA设计 90
4.4.5 设计入口 90
4.4.6 输入/输出规划 91
4.4.7 综合 91
4.4.8 布局和布线 91
4.4.9 比特流生成 92
4.4.10 测试实现 92
4.5 开发第一个FPGA项目 93
4.5.1 项目描述 93
4.5.2 安装Vivado工具 93
4.5.3 创建项目 96
4.5.4 创建VHDL源文件 99
4.5.5 测试逻辑行为 105
4.5.6 定义I/O信号 112
4.5.7 创建顶级VHDL文件 113
4.5.8 综合和实现FPGA比特流 115
4.5.9 将比特流下载到板上 117
4.5.10 将比特流编程到板载闪存 118
4.6 小结 122
第5章 使用FPGA实现系统 123
5.1 技术要求 123
5.2 FPGA编译过程 123
5.2.1 设计输入 124
5.2.2 逻辑综合 128
5.2.3 设计优化 129
5.2.4 高级综合 132
5.2.5 优化和约束 138
5.3 最适合FPGA实现的算法类型 140
5.3.1 处理高速数据流的算法 140
5.3.2 并行算法 140
5.3.3 使用非标准数据大小的算法 141
5.4 示波器FPGA项目 141
5.4.1 项目描述 142
5.4.2 基准Vivado项目 142
5.4.3 原理图设计 143
5.4.4 定义时钟 147
5.4.5 生成比特流 148
5.4.6 创建并运行TCP回显服务器 148
5.4.7 调试程序 151
5.5 小结 154
第6章 使用KiCad设计电路 155
6.1 技术要求 155
6.2 关于KiCad 155
6.3 KiCad设计基础 157
6.3.1 放置和连接电路元件 158
6.3.2 添加稳压器 162
6.3.3 KiCad原理图编辑器应用技巧 163
6.3.4 创建元件符号 164
6.4 开发项目原理图 169
6.4.1 添加文本注释 170
6.4.2 添加信号标签 171
6.4.3 添加全局标签 171
6.4.4 创建差分信号对 171
6.4.5 创建板外连接 172
6.4.6 符号注释和电气规则检查 172
6.5 印刷电路板布局 173
6.5.1 为电路元件分配封装 173
6.5.2 构建PCB布局 174
6.5.3 布局规则 176
6.5.4 元件布局示例 177
6.5.5 定义板层集 178
6.5.6 创建填充区域 179
6.5.7 绘制电路走线 179
6.5.8 查看电路板的3D图像 180
6.6 电路板原型制作 182
6.7 小结 183
第7章 构建高性能数字电路 185
7.1 技术要求 185
7.2 电路板组装工具和过程 185
7.2.1 光学放大镜 186
7.2.2 镊子 187
7.2.3 助焊剂 187
7.2.4 焊料 188
7.2.5 静电放电保护 190
7.2.6 手工焊接方式 190
7.2.7 吸锡线 192
7.2.8 焊膏应用 193
7.2.9 回流焊接工艺 196
7.2.10 焊接安全提示 198
7.3 准备组装和放置零部件 199
7.4 回流焊接和手工焊接 201
7.4.1 回流焊接 201
7.4.2 手工焊接 202
7.4.3 回流焊接后的修复 202
7.4.4 安装通孔元件 203
7.5 组装之后的电路板的清洁和检查 204
7.5.1 助焊剂残留物需要清洗的原因 204
7.5.2 助焊剂残留物去除 204
7.5.3 组装后的目视检查 205
7.5.4 电气短路检查 206
7.6 小结 207
第3篇 实现和测试实时固件
第8章 首次给电路板通电 211
8.1 技术要求 211
8.2 为电路板通电做准备 211
8.2.1 谨慎操作 212
8.2.2 为电路板供电 212
8.3 检查电路的基本功能 213
8.3.1 测试电路板电源 214
8.3.2 故障排除 216
8.3.3 测试模拟放大器 216
8.3.4 测试ADC 219
8.3.5 配置ADC 221
8.4 出现问题时调整电路 226
8.4.1 切割PCB走线 227
8.4.2 安装焊料跳线 227
8.4.3 移除元件 228
8.4.4 添加元件 229
8.5 添加FPGA逻辑并检查I/O信号 229
8.5.1 生成ADC编码器时钟和1kHz校准信号 229
8.5.2 检查I/O信号 232
8.6 小结 234
第9章 固件开发过程 235
9.1 技术要求 235
9.2 FPGA算法的设计与实现 235
9.2.1 数字示波器系统概述 236
9.2.2 添加解串器 238
9.2.3 添加FIFO缓冲区 242
9.2.4 添加总线接口 245
9.3 添加MQTT协议 247
9.3.1 关于MQTT协议 247
9.3.2 在添加MQTT协议时要解决的问题 248
9.3.3 调用MQTT API 249
9.4 编码风格 252
9.4.1 命名规则 252
9.4.2 代码中的注释 253
9.4.3 避免文字数值 253
9.4.4 花括号、缩进和垂直间距 253
9.4.5 优先考虑可读性和正确性 254
9.4.6 避免过早优化 255
9.4.7 避免由实现定义的行为 255
9.4.8 避免无条件跳转 256
9.4.9 最小化标识符的作用域 256
9.4.10 将不变的事物指定为常量 257
9.4.11 自动代码格式化程序 257
9.5 静态源代码分析 257
9.5.1 关于静态代码分析 258
9.5.2 静态代码分析工具 258
9.5.3 高效使用静态代码分析 259
9.5.4 使用现有代码 259
9.5.5 从仅显示最严重的错误消息开始 261
9.5.6 解析分析器输出消息 262
9.5.7 常见的源代码分析器消息 262
9.6 源代码版本控制 263
9.7 测试驱动开发 264
9.8 小结 265
第10章 测试和调试嵌入式系统 267
10.1 技术要求 267
10.2 设计系统级测试 267
10.2.1 需求驱动的测试 268
10.2.2 在标称和非标称条件下进行测试 270
10.2.3 单元测试与功能测试 271
10.2.4 负面测试和渗透测试 273
10.2.5 在模拟环境中测试 273
10.2.6 获得可重复的测试结果 274
10.2.7 制订测试计划 274
10.3 进行测试并记录结果 275
10.3.1 确定要收集的数据 275
10.3.2 配置被测系统 276
10.3.3 执行测试程序 277
10.3.4 测试结果的快速评估 277
10.3.5 必要时重复测试 277
10.4 对现有代码进行回归测试 278
10.5 确保全面的测试覆盖率 279
10.5.1 需求可追溯性矩阵 279
10.5.2 跟踪代码覆盖率 282
10.5.3 建立充分测试的标准 283
10.6 有效调试技术 284
10.6.1 处理语法和编译错误 284
10.6.2 使用静态代码分析和单元测试 285
10.6.3 清楚地定义问题并尝试重现它 286
10.6.4 判断输入是否正确 286
10.6.5 寻找获得系统可见性的方法 287
10.6.6 使用二分搜索调试过程 288
10.6.7 暂时删除部分功能 289
10.6.8 制作演示问题的最小程序 289
10.7 高性能嵌入式系统开发的最佳实践总结 290
10.7.1 测试设计 290
10.7.2 留出成长空间 290
10.7.3 设计硬件时考虑未来功能 291
10.7.4 仅开发你现在需要的代码 292
10.7.5 保持严格的版本控制 292
10.7.6 在开发代码的同时开发单元测试 293
10.7.7 及时开始系统级测试 293
10.8 小结 294