经常看到网友问:怎么程序跑到了Data Abort或者Prefetch Abort。<br />俺最近在看AT91SAM7S的手册。里面对Abort问题讲得很清楚。<br /><br />首先要说,一般我们所说的ARM芯片,是由ARM内核,以及不同厂家扩展的外围模块和逻辑电路组成的。<br />AT91SAM7S的MC(Memory Controller),就是这样的外围模块。<br />ARM7内核对系统存储空间(ASB总线)的访问,是通过MC来进行的。<br />MC要实现总线地址译码,然后去访问真实的存储器。<br /> 对于AT91SAM7S来说,真实的存储器包括:片内FLASH、片内RAM、内置外设等,它们都有自己的映射地址。<br />MC中包含一个Abort状态单元。这个单元会向ARM7内核发出Abort信号。<br />导致Abort的两种原因:<br /> ARM7内核所访问的总线地址不存在(未定义)。因为MC知道哪些地址是空的,不对应真实的存储器。<br /> 未对齐的访问。ARM7访问32位数据时地址要四字节对齐;访问16位数据时地址要两字节对齐。<br /><br />ARM7内核对Abort信号的处理:<br />如果ARM7内核在访问数据时检测到Abort信号有效,当前指令地址被保存到R14_abt,然后PC会跳转到Data-Abort异常向量(地址0X10)。<br />如果ARM7内核在指令预取时检测到Abort,预取的指令被标志为无效,但异常(Exception)并不会立刻产生。“如果指令没有被执行,举例来讲,在流水线中的一个分支指令,将不会产生异常,如果指令到流水线的出口并将要被执行时,异常产生”。当前指令地址被保存到R14_abt,PC会跳转到Prefetch-Abort异常向量(地址0X0C)。<br /><br /><br />MC还能够通过寄存器提供Abort状态信息:<br /> 造成Abort的那个访问地址。<br /> 请求宽度(32位、16位,还是8位)。<br /> 访问类型:数据读、写,还是指令预取。<br /> 是未定义地址,还是地址未对齐。<br /> 。。。<br />以上信息,可以帮助定位bug。<br />用户可以编写Abort异常处理程序来读出这些信息。<br /><br />另外值得一提的:<br />除了ARM7访问ASB总线会造成Abort以外,外设DMA控制器访问ASB也会导致Abort。<br />对于带MMU的arm芯片,操作系统可以通过处理Abort异常来管理虚拟内存。<br /><br />说回来,什么样的程序错误会导致Abort呢。<br />俺遇到过的问题是数组访问越界,导致数组外的数据被改写。<br /> 例如被改写的恰巧是一个指针变量。<br /> 比如堆栈内容被改写,然后又弹出到PC。<br />比如把0X0C000001,强制转换为指向int的指针,然后再读写这个指针指向的数据。 |
|