热度 23
2014-7-21 17:50
3115 次阅读|
2 个评论
UAL的指令描述格式的参考 嵌入式系统( Embedded system) 开发的核心, 往往围绕着 uController 的开发而进行. 也即是说, 在 hardware 的 designe 上, 我们致力于形成一个最小的可实现 uController 的系统, 并以此为核心, 构建从属的数据采样/控制的 hardware 子系统. 它可以是开环的, 更可能是闭环的. 在 PCB 的实现上, 随着近年来 uController 的不断进步, 尽管有着内部倍频的存在, 但是系统核心频率与总线(bus)频率仍然在不断提高, 它们共同影响了 uController 稳定运行. 在 PCB 的layout 上, 为了保证 uController 的正常工作状态, 以及外部高速bus 的信号的传输, 工程师们设计时往往小心翼翼对尺寸, 布局, 分层, 线宽, 射频等多方因素进行权衡. 同样, 软件体系构建在 uController 内部. 其设计调试编程的一般过程, 需要汇编器, 编译器, 链接器, 模拟器, 调试器的诸多配合. 今天的设计不断在复杂性上进行提升, 也就是工程师开始不仅仅要熟悉以往的前后台编程模式, 更可能自行设计一个简单的任务调度器(而不是操作系统, 因为任务没有通过stack 的方式独立), 而较复杂的应用, 即使在类似 cortex 的 microController variant 也就是 M variant 上, 都引入了(嵌入式)实时操作系统的应用. 今天的设计, 也仍然延续着以往嵌入式软件设计的一些固有特性, 特别是着重对软件的健壮性进行各种保护, 无论从多个冗余的条件语句还是到所谓的软件陷阱技术, 莫不体现了这一点. 如果我们回归到刚刚进入 embedded world 世界, 点亮第一个 led 的story 的源头, 从那个时候, 到多个项目结束的今天, 我们大致能够推出一些既成经验: 在嵌入式系统的开发过程中, 硬件设计在不断的总结过程中, 电路经验不断积累, 阶段性(而不是跃进性)的突破在层级进步. 故而硬件设计往往最终以积累与继承为主. 而软件设计, 从最初的功能实现型的开发, 到多个复杂难解的 bug 出现折磨, 软件开发的趋势, 往往向时序的理解, 以及任务的分派, 和对软件健壮性的强调为主. 所以, 我们觉得, 嵌入式设计, 最终是以 uController 为设计核心, 硬件上为 uController 提供最少干扰的环境, 软件上提供任务时序清晰, 健壮性较高, 容易移植的软件模块. 这样, 在新的嵌入式项目开发时, 工作经验就容易继承, 开发项目的成功率也提高. 如果说嵌入式设计围绕以 uController 为核心, 那么 uController 的设计/应用/学习的核心又在何处, 不同的工程师会从不同角度, 根据自己的项目体会与经验来理解. 如果从应用的角度出发, 我们抛开微控制器内部的运算器控制器, memory, io 硬件部分(它们往往基于某个总线协议, 如 AHB/APB 或者 AXI/APB 而连接在一起). 如果我们同时也不理会沙子中提纯si, 以及各种材质渗入与蚀刻以构建晶体管, 也不论最后的芯片封装. 那么我个人就觉得, 架构就是一颗 uController 的核心. 谈到架构, 这个汉语词汇似乎能让我们发散思维, 将诸多领域的概念纳入其中. 但实际上, 架构对应的专业词汇 Architecuture 在比如说 ARM 的文档中, 以及被赋予了专门的定义. 首先, 架构的核心就是指令集. 这并不让人感到意外. 好吧, 假设上帝赋予我们凭空创建 uController 的权利. 那么我最想做的, 就是, 啊` 请创建一颗 32-bit 或者 16-bit 的 uController 给我! 在 encoding diagram 方案上, 我要求 ADC 在 16-bit 上, 编码表要是: 0100000101RmRn, 其中 Rm 与 Rn 都是 3-bit 用来方便 encoding-specific psuedocode 的表达. 没错, 我说的其实就是 ARM 的 encoding diagram. 当我们完全按照 ARM 的编码表完成 instrution set 后, 想想看这是多么令人激动的事情! 这意味着 KEIL 和 IAR 几乎不加修改能够被我们使用, 数以万计的代码资源不浪费能够被我们项目移植... 但是, 如果上帝不帮我的话, 那么最终我必将因为触犯 ARM 的知识产权而被严惩. 这个荒诞的剧目可能深刻揭示, 作为架构的核心的指令集, 就是收到知识产权严密保护的基本企业知识产权的财富. 我们可以想当然创造一个新的RISC指令集, 引入合理不合理的新的编码表, 但是就是不能与 ARM 现有的指令集一致, 哪怕我们对今天已经如此成熟的 ARM 生态链垂涎三尺也不成. 当然, 架构不仅仅不包括指令集, 作为 programmer's model. 架构还包括了: 基本数据类型的定义(哪怕是我们假设中的微控制器仅仅只有 4-byte 的 word 类型, 我们至少也要定义它). register(包括有 core register, 以及 system register, 它们往往被 mapped memory).异常(包括了Interrupt)行为. 还有就是 memory 的 type , 属性, 以及 memory address 的空间分配. 回到文章标题(UAL的指令描述格式)的议题上来: 如我们在上文中提到的, 嵌入式设计以微控制器为核心, 微控制器以架构为核心, 架构以指令集为核心, 让我们观察一下指令集的例子, 无论是学习或者应用的目的. 最好的例子是 ADC. 原因就是, 以字母为序的指令集详解中, ADC 往往占据榜首. 研习 ADC instruction 的例子, 让我们容易进行各个指令集的历史继承关系的比较. 而且, 也对初学者有相当帮助, 可以作为学习笔记来进行理解. 让我们一起来观察 ADC 的例子(来自于 ARMv6-M ARM 文档, 后面一个 ARM 是 Architecture Reference Manual 的缩写): (1) section title: 基本上, 每个 instrution 对应着一个 section. (2) introduce: 说明了 instruction 执行的内容. (3) encodings : 讲解了 instruction encoding. 我们用 (3a)...(3d) 作了具体的笔记如下: (3a) 用来说明从属哪个 instruction set 的版本. 在这个例子中, "All versions of the Thumb instruction set", 指的是来自 ARMv4T 往后的全部支持 Thumb 的版本. 提示一下, ARMv4T 就是构建当年的 ARM7 的指令集版本. (3b) 使用该 instruction 的汇编语法 (3c) encoding diagram: 可能有很多种, 我们观察到被罗列在这里, 用于举例的 encoding diagram 往往是最简单的编码表中的一种. (3d) 编码界定赝代码, 正如同将 3-bit 的 Rm 进行 m=UInt(Rm) 的解释这样, 它有助于在后面操作内容中, 利用赝代码对 instruction 进行理解. (4) Assember syntax (4a) prototype line, 在原型行中定义了汇编器语法 (4b) where line, 在 where 行中, 跟随在后文中解释了对 field 的用法与意义. 值得一提的是, c, q 域, 由于可以在绝大多数的指令中使用, 而被特成为标准域(standard field). (5) Opration 啊, Operation 是用 psuedocode 来实现的, 这给了我们一个提示, 我们日常使用的语言太高级, 太模糊而不够明确... 让我们简单看看这里的 ADC 的赝代码说了什么: ConditionPassed(): 无意义, 在整个 ARMv6-M 中, 只有条件跳转 B 指令, 才有用到该功能, 并有专门的 bit-field. 我们注意到在其他的 instrutions 中, encoding diagram 根本就没有 condition bit field. 如果我们注意看本例中的 ADC 的 encoding diagram 也会明白这点. EncodingSpecificOperations(): 已经解释过, 在 encoding diagram 中, 有数个 bit field 可能代表某些类别的用法, 如 Rm, Rn, Rd 的例子. 另外也值得一提的就是, InITBlock() 也是无意义的, 因为 v6-M 不支持 IT 指令. 同样, shift_n 被赋值为0. 也有着深刻的含义, 我们看 Rm 尽管被成为 optionally shifted operator, 其实它根本就不能做 shift, 因为在编码表中根本就没有 shift 这个立即数所占据的 bit field. 如果说远一点, 在 ARMv7-M, 倒真的有 shift operator 选项, 但是是在 32-bit 的 ARMv7-M 支持的 Thumb 指令集中. 所以, shifted 的计算是无意义的. 事实上, 我觉得它就是 R . 也就是 shifted = R ; 赝代码的内联函数(姑且这么称呼) AddWithCarry 实现了带进位的加法. setflags 已解释无意义, 永远为真(在 ARMv6-M) 中, 故在加法完成后, APSR 必得到状态升级. (6) exception: 该 instruction 可能造成的异常效果列举. 研习比较 instruction set 的例子是有趣的. 正如同 ADC, 我们注意到 ARMv6-M 与 ARMv6 的架构手册中, ADC 的 encoding diagram 完全相同, 这大致说明了 ARMv6-M 被命名 variant 6 的原因, 两者之间在指令集上是兼容的. 但是, 正如同我们提到的, 在 ARMv7-M 指令集中, ADC 除了上述兼容指令外, 并多了一个仅仅在 ARMv7-M 中表达的 32-bit encoding 的 thumb 指令. 这大致说明 ARMv6-M 是 ARMv7-M 向下兼容的指令集. 同时, 观察 pseudocode 的 operation 内容, 我们比较得知, ARMv6-M 与 ARMv7-M 指令家构架文档的格式完全类似, 暗示我们 ARMv6-M 更应该看待为 ARMv7-M 的子集. 而非 ARMv6 构架代表的上一个时代. 说明: ARM ARM文档, 对于部分或全部内容的发布(也可能包括翻译)较为敏感. 我这里图例引用 ADC指令 的目的, 仅仅为了教育与讨论使用, 没有参与任何 pratice 与 implement 而对ARM公司引发大不敬之意(如有任何对我正式提及, 我们会修改该图例用其他格式替代).毕竟上帝许可我们, 按思维构想随心所欲完成微控制器, 只是我们随口说说. 令人黯然的是, 今天中国大陆的IC产业, 据说还远远落后于时代先进吧. Allen Zhan 作于深圳, 发表于 EETC 2014.7.21