再上一篇:13.4 自复位控制
上一篇:第14章
主页
下一篇:14.2 MPU 的寄存器组
再下一篇:14.3 启用MPU
文章列表

14.0 译者添加的引子

《Cortex-M3 权威指南》,嵌入式处理器开发教程。

MPU进入单片机还是很新鲜的事,为了让读者预先对它更有一点认识,译者加入了引文:

引子 1:野指针与 C语言

回顾一下,什么是指针?指针在内存中实际上是一个无符号整数(unsigned int),但是它的值被 赋予特殊的解释:表示变量或函数的地址。所以才被形象地称为“指针”,就好像指向谁家似的。 在使用指针前,都必须先让它指向有意义的,并且允许由程序使用的实体——数据和代码。而所谓 “野指针”,就是指某个指针变量的值因故超出合法的范围,使其“枪口”乱指。程序逻辑错误、 数组越界、堆栈溢出、指针未经初始化、对缓存与缓冲的处理不当、多任务环境中的紊乱危象,甚 至是恶意地破坏等,都可以制造出野指针。如果使用野指针去读取或修改内存,则被读取或修改的 位置是不可预料的。前者导致读回来的都是垃圾数据,后者则更是“血口喷人”——会破坏未知用 途的数据。这常常导致系统发生莫名其妙的功能紊乱,严重时会使系统毫无征兆,没有理由地失控、 死机。

野指针就像“肉里的刺,酱里的蛆”一般:一个野指针就足以崩溃整个系统,而且极其隐蔽, 很难通过症状来找出是哪里存在野指针,甚至都不能判定症状是否因野指针造成(程序大了其它 bug 也很多,并且也能导致相同的症状)。野指针的发作概率越小,就越隐蔽,后患也越无穷。对于通 常的单片机系统,是没有任何办法来防止野指针的破坏的,完全靠程序员的素质和自律。但智者千 虑,必有一失。尤其是当程序规模变得很大时,复杂度会呈指数上升,千头万绪纠缠不清,就算是 谨慎如诸葛亮,聪明如比尔·盖茨的天才,也不敢保证没有漏网之鱼。

嵌入式系统开发的首选语言是 C 语言。C 语言的指针功能非常灵活、生猛、桀骜不驯,它是电, 它是光,它是 C 语言中最闪亮的“Super Star”。C 语言允许我们几乎随心所欲地把玩各种地址,离 汇编语言中“放任自流”的程度也差不远了。可是,要是像汇编那样“明坏”倒也好,偏偏 C 语言 中的指针还因为语言特性附加了许多十分微妙的“潜规则”,令人防不胜防;更加暧昧的是指针与 数组的关系,一维数组与多维数组的关系,多维数组与“星星”点灯的关系,指针与”[]”的二重 唱,指针在宏中使用时极易弄巧成拙的暗箱操作……用 C 语言的指针功能就像在玩一场勾魂的“野 蛮游戏”,不知不觉其实你已“上线”,指针飞舞的世界战火连天,如果不想每天因爆发了却查不出 来的 bug 而以泪洗面,提高警觉快张大双眼是必要的,但年深日久 0 还是难免有看不清楚而迟早粉 身碎骨的时候。在系统程序的开发中,指针更是满天飞遍地爬,程序员在这无间世界里没有想过要 逃脱,为什么要逃脱?完全是“你主宰,我崇拜,没有更好的办法,只能爱你,u r my super star”。

这里再说句题外话。如果读者不幸与被 C 语言的指针给沾上了,就要特别重视内功的修炼。除 了要把《C 程序设计》以及《C 和指针》夜夜放在床头外,更要千方百计地弄到《C 陷阱与缺陷》, 以及《C 专家编程》这两本书,它们两个堪比《葵花宝典》和《九阳真经》。

引子 2:使命-关键系统

这种系统往往都用于性命攸关的场合,且必须连续无故障地工作,比如,火车调度系统、生命 维持系统、大型发动机驱动器、核子反应堆控制、网络/电信的数据交换中枢等。如果失能,将导 致惨重的经济与损失,甚至会使无数人死于非命。因此,决不允许这类系统出现上述情况。然而, 这些系统的复杂度往往都非常高,几乎不可能由开发人员保证这种可靠性。

因此,需要在硬件水平上加入一个“公安机关”。通过它设置各种类型的“禁地”,并且施加多 种规章条例。一旦发现违章,则强制改变执行流和处理器的工作状态,以便可以由软件做进一步的 处理。这样,就可以为不同的程序限定一个内存使用范围,从而使野指针或恶意破坏无法影响不允 许访问的区域。此即存储器保护单元(MPU)。

有时,对存储器的管理更进一步,做到可以对地址执行变换的程度,此时程序使用的地址未必 是真实的存储器地址。它在 MPU 的基础上,还消灭了内存碎片和浪费,并且能进一步地让应用程 序拥有方便舒适的地址空间,从而使程序规模可以扩大甚至数百倍。此即为“存储器管理单元”

(MMU)。带 MMU 的系统,往往也带 cache,动态 RAM 等。这种系统对 RAM 容量的计量是以 MB

为单位的。可见,MMU 是一个对处理器定位的“分水岭”。对 MMU 的介绍已经超出了本书的范围。

(本章篇幅虽然较长,但很多内容都是在寄存器的介绍,以及示例代码的反刍上,读者请放松阅读)

14.1 MPU 概览

在Cortex-M3处理器中可以选配一个存储器保护单元(MPU),它可以实施对存储器(主要是内 存和外设寄存器)的保护,从而使软件更加健壮和可靠。如果打算启用MPU,则在使用前,必须根 据需要对其编程。如果没有启用MPU,则等同于系统中没有配MPU。MPU有如下的能力可以提高系 统的可靠性:
 阻止用户应用程序破坏操作系统使用的数据
 阻止一个任务访问其它任务的数据区,从而把任务隔开。
 可以把关键数据区设置为只读,从根本上消除了被破坏的可能。
 检测意外的存储访问,如,堆栈溢出,数组越界。
 此外,还可以通过MPU设置存储器regions的其它访问属性,比如,是否缓区,是否缓冲等。

MPU在执行其功能时,是以所谓的“region”为单位的。一个region其实就是一段连续的地址, 只是它们的位置和范围都要满足一些限制(对齐方式,最小容量等)。CM3的MPU共支持8个regions。 怎么,嫌少?是少了点,不过,还允许把每个region进一步划分成更小的“子region”。此外,还允 许启用一个“背景region”(即没有MPU时的全部地址空间),不过它是只能由特权级享用。在启 用MPU后,就不得再访问定义之外的地址区间,也不得访问未经授权的region。否则,将以“访问 违例”处理,触发MemManage fault。

MPU定义的regions可以相互交迭。如果某块内存落在多个region中,则访问属性和权限将由编 号最大的region来决定。比如,若1号region与4号region交迭,则交迭的部分受4号region控制。