1. 项目概述:深入理解ARM Cortex-A9 MPU子系统
在嵌入式系统开发,尤其是高性能应用处理器(Application Processor)的设计与调试中,我们常常会面对一个核心的“黑盒”——微处理器单元(MPU)子系统。它不像某个具体的外设驱动那样有明确的输入输出,也不像操作系统调度那样有清晰的逻辑流程。它更像是一个精密的交通枢纽,默默协调着CPU核心、高速缓存、内存控制器以及整个片上系统(SoC)内部的数据洪流。很多工程师在初期接触时,往往只关注CPU主频和内存大小,却忽略了MPU子系统的架构设计对系统整体性能、功耗乃至稳定性的决定性影响。
我最初接触TI的AM335x这类基于Cortex-A9的芯片时,也曾对数据手册中MPU子系统那一章感到头疼。里面充斥着SCU、GIC、PL310、AXI、OCP等一堆缩写,框图复杂得像一张地铁线路图。直到有一次,我们在进行高帧率图像处理时遇到了严重的性能瓶颈,CPU占用率并不高,但系统就是“卡”。经过层层排查,最终发现是L2缓存配置不当,导致CPU核心频繁等待低速的片外DDR内存,整个数据通路出现了拥堵。那次经历让我深刻意识到,不理解MPU子系统,就无法真正驾驭一颗高性能的处理器。
简单来说,MPU子系统是连接CPU核心与外部世界(主要是片内互连和内存)的桥梁与调度中心。它的核心价值在于:通过多级缓存、高效的总线桥接和智能的中断管理,在物理层面最大化CPU的计算效率,同时为软件提供一个稳定、可预测的硬件执行环境。以本文将要详细解析的ARM Cortex-A9 MPU子系统为例,它不仅仅是一个Cortex-A9核心,而是一个包含L1/L2缓存、一致性控制单元、中断控制器、调试单元和总线接口的完整解决方案包。理解它的工作机理,对于进行驱动开发、性能调优、功耗管理乃至硬实时系统设计都至关重要。
2. MPU子系统整体架构与核心模块解析
当我们拿到一颗集成了Cortex-A9的SoC芯片手册,翻到MPU子系统章节时,通常会看到一张类似下面描述的高层框图。这张图是理解整个子系统的钥匙,我们需要把它拆解成几个功能明确的模块来理解。
2.1 核心处理单元:Cortex-A9 MPCore
MPU子系统的“大脑”自然是ARM Cortex-A9处理器。在这个具体的实现中,它是一个单核配置的Cortex-A9。虽然名为“MPCore”暗示多核能力,但单核配置在成本敏感的嵌入式领域非常常见。这颗核心是ARMv7-A架构,采用双发射、8级流水线设计,意味着在每个时钟周期内,它可以同时从指令缓存中取出两条指令进行解码,极大地提升了指令吞吐量。
关键特性与设计考量:
- 流水线与乱序执行:虽然A9是“按序发射、乱序完成”,这听起来有点矛盾,但实际意味着取指和解码是按顺序的,但到了执行阶段,如果后续指令不依赖前面指令的结果,就可以提前开始执行。这种设计能有效隐藏内存访问等长延迟操作带来的停顿。
- 内存管理单元(MMU):集成了两级TLB(转译后备缓冲器)。第一级是分别位于指令和数据侧的32项全关联微TLB,用于极速转换最近使用的地址;第二级是统一的128项两路组关联主TLB。MMU的存在是运行Linux、Android等复杂操作系统的基石,它负责虚拟地址到物理地址的转换,实现内存保护和多任务隔离。
- NEON与VFP:集成了一颗NEON媒体处理引擎和VFPv3-D16浮点单元。NEON是SIMD(单指令多数据)引擎,能一次性处理多个数据,对于图像处理、音频编解码、基带信号处理等多媒体任务有数倍的加速效果。VFP则负责标准的单/双精度浮点运算。在软件层面,编译器自动向量化或手动调用NEON intrinsics可以极大释放这部分硬件性能。
2.2 缓存层次结构:L1与L2缓存
缓存是提升性能最关键的设计之一,其核心思想是用快速但容量小的存储(SRAM)来缓存慢速但容量大的存储(DRAM)中的数据。
- L1缓存:紧密耦合在CPU核心内部。在这个子系统中,指令缓存(I-Cache)和数据缓存(D-Cache)各为32KB,采用4路组相联,行大小(Cache Line)为32字节。L1缓存的速度最快,通常能在1-2个时钟周期内响应,是CPU性能的第一道保障。
- L2缓存:通过一个名为PL310的控制器管理,容量为256KB,采用更大的16路组相联,行大小同样为32字节。L2缓存作为CPU核心与系统互连(L3)之间的缓冲,其速度比L1慢,但比访问片外DDR内存快一个数量级以上。PL310控制器支持“关键字优先”填充,即当CPU需要的数据不在缓存中时,它会先从内存中读取CPU当前请求的那个字(32位),立刻返回给CPU让其继续工作,同时后台再读取该缓存行的剩余部分。这有效降低了缓存缺失带来的性能惩罚。
注意:缓存一致性(Cache Coherency)。在多主设备(如多核CPU、DMA)共享内存的系统中,确保每个主设备看到的内存数据是一致的,是个复杂问题。Cortex-A9 MPU子系统通过侦听控制单元(SCU)来维护L1缓存之间以及L1与L2之间的一致性。但需要注意的是,SCU不管理指令缓存的一致性。这意味着如果某个主设备(如DMA)修改了正在被CPU作为指令执行的内存区域,软件必须手动清洗(clean)或无效化(invalidate)CPU的指令缓存,否则CPU可能执行到旧的指令。这是一个常见的驱动开发陷阱。
2.3 系统互连与桥接:数据高速公路的立交桥
CPU和缓存产生的数据访问请求,最终要到达内存或外设。MPU子系统通过两类重要的桥接模块与SoC的其他部分通信:
- AXI2OCP桥:这是连接ARM世界(使用AXI总线协议)与TI SoC内部传统互连世界(使用OCP总线协议)的关键通道。它负责协议转换、事务标识(Tag)映射。在这个设计中,它连接在PL310的一个从端口(Slave Port M1)上,主要服务于那些对延迟不那么敏感、或需要接入OCP架构外设的访问路径。
- 内存适配器(Memory Adaptor):这是高性能数据通路的核心。它也连接在PL310的一个从端口(Slave Port M0)上,但直接面向片上的L3高速互连(通常是128位甚至更宽的总线)。它内部包含优化逻辑,旨在最小化缓存缺失的延迟。例如,它可能支持更深的读写缓冲、预取机制,或者更高效的突发传输管理。CPU对DDR内存的绝大部分访问,理想情况下都应该通过这条路径。
为什么需要两个桥?这是一种典型的设计权衡。内存适配器为高带宽、低延迟的内存访问优化;而AXI2OCP桥则为接入种类繁多、协议可能稍旧的外设控制器提供了标准化的接口。将流量分开,有助于避免低速外设访问阻塞高速内存通道。
2.4 中断管理与唤醒:系统的神经中枢
一个实时响应系统离不开高效的中断管理。MPU子系统集成了一个通用中断控制器(GIC),它符合ARM的GIC架构,可以看作是中断信号的“路由器”和“调度器”。
- 中断源:GIC支持多达224个共享外设中断(SPI),这些中断来自SoC内部的各种外设(如GPIO、定时器、USB等)。此外,还有约32个私有中断(如CPU私有定时器、性能监控中断等)在内部处理。
- 中断分发:GIC可以配置每个中断的优先级、目标CPU(在多核系统中)和触发方式(边沿/电平)。当多个中断同时发生时��高优先级的中断会被优先递送给CPU。
- 唤醒生成器(WakeUpGen):这是低功耗管理的关键组件。当CPU进入低功耗状态(如WFI/WFE指令触发的睡眠)时,并不是所有中断都能唤醒它。WakeUpGen提供了一组寄存器(如
WkUpGenEnb_0A到WkUpGenEnb_10),软件可以精确配置哪些中断线具有唤醒能力。例如,你可以设置只有RTC闹钟中断和某个关键外部GPIO中断能唤醒深度睡眠的系统,而忽略网络数据包到达的中断,从而实现极低的待机功耗。
2.5 调试与追踪:开发者的眼睛
对于复杂系统的调试,仅靠打印日志是远远不够的。该MPU子系统集成了CoreSight调试架构组件:
- 交叉触发接口(CTI/CTM):允许不同调试组件(如CPU调试单元、跟踪单元)之间相互触发事件,实现复杂的调试场景。
- 程序跟踪宏单元(PTM):能够实时捕获CPU的执行流(指令地址),并以极高的压缩率输出跟踪数据。通过分析这些数据,我们可以重构出程序崩溃前究竟执行了哪些指令,对于解决偶发的、难以复现的宕机问题无比珍贵。PTM通常只在特定的“路点”生成跟踪数据,以减少数据量。
3. 核心功能模块的深度剖析与配置实践
理解了宏观架构,我们需要深入到几个关键模块的内部,看看它们具体如何工作,以及我们在软件层面该如何与之交互。
3.1 PL310 L2缓存控制器的精细化管理
PL310不仅仅是一个缓存,它提供了一系列可配置的寄存器,让软件可以精细地控制其行为。这对于性能调优和特定场景下的功能实现至关重要。
关键寄存器组与功能:
- 控制寄存器(0x100 - 0x1FC):用于全局启用/禁用L2缓存、配置替换策略(通常是伪随机)、启用奇偶校验(本例中未实现)等。
- 中断与计数器控制寄存器(0x200 - 0x2FC):PL310可以监控多种缓存事件(如命中、缺失、写回等),并通过中断报告。这对于性能剖析(Profiling)非常有用。你可以配置当某个事件计数器溢出时产生中断,然后在中断服务程序中记录数据,分析缓存效率。
- 缓存维护操作寄存器(0x700 - 0x7FC):这是软件与缓存交互最频繁的窗口。通过向特定地址写入操作码,可以执行清洗(Clean)、无效化(Invalidate)或清洗并无效化整个缓存、或指定地址范围的缓存行。在DMA传输前后,必须正确使用这些操作来保证数据一致性。
- 地址过滤寄存器(0xC00 - 0xCFC):这是一个强大但容易被忽略的功能。PL310可以将特定的物理地址范围排除在缓存之外,或者强制指定其缓存策略(如直写、回写)。例如,你可以将一段用于DMA描述符链表的内存区域设置为“非缓存”,确保CPU和DMA控制器看到完全一致的数据,无需频繁执行缓存维护操作。
L2缓存作为SRAM使用的特殊模式:这是一个非常实用的特性。在某些对确定性延迟要求极高的场景(如中断服务程序、关键实时任务的数据区),我们希望数据始终在最快的SRAM中,避免缓存命中/缺失带来的时间抖动。PL310支持将整个256KB L2缓存配置为静态RAM(SRAM)来使用。
操作流程与重要警告:
- 系统复位后,L2缓存默认是禁用的。
- 软件通过配置
CTRL_MPU_L2寄存器中的PIUSEL2SRAM信号,将路径从PL310切换到OCMC(片上内存控制器)模块。 - OCMC模块的时钟(
L2SRAMCLK)由MPU时钟分频而来(/2, /3, /4, /6),通过PIL2SRAMCLKDIV[1:0]引脚配置。这里有一个至关重要的限制:OCMC的时钟频率必须小于或等于芯片级L3互连的时钟频率。因为连接两者的异步桥不支持反压流控,如果OCMC响应过快,会导致数据丢失和系统挂死。 - 在此模式下,MPU电源域必须保持开启,因为OCMC控制器位于该域。为了省电,只能依赖CPU内部的时钟门控。
严重警告:绝对禁止在系统运行时动态切换
PIUSEL2SRAM或改变PIL2SRAMCLKDIV的分频比。这种操作会导致不可预测的内存访问错误和系统崩溃。必须在初始化阶段,系统处于稳定、空闲状态时一次性配置完成。
3.2 通用中断控制器(GIC)的软件视图
对驱动工程师而言,GIC的编程模型主要涉及两个部分:分发器(Distributor)和CPU接口(CPU Interface)。
- 分发器寄存器:负责全局中断管理。例如:
GICD_ISENABLERn:用于启用或禁用某个中断。GICD_IPRIORITYRn:设置中断优先级(0-255,数值越低优先级越高)。GICD_ITARGETSRn:在多核系统中,指定中断由哪个CPU核心处理。GICD_ICFGRn:配置中断触发类型(电平触发或边沿触发)。
- CPU接口寄存器:每个CPU核心都有自己的一套,用于处理送达该核心的中断。最关键的两个是:
GICC_IAR:中断应答寄存器。CPU读取该寄存器会获取当前最高优先级 pending 中断的ID,并自动将其状态改为“active”。GICC_EOIR:中断结束寄存器。CPU在处理完中断后,向此寄存器写入之前读取的中断ID,告知GIC该中断处理已完成。
一个典型的中断处理流程(以Linux内核驱动为例):
- 外设触发中断信号。
- GIC分发器根据优先级和目标CPU,将中断递送给对应的CPU接口。
- CPU核心响应IRQ异常,跳转到异常向量表。
- 内核的中断通用处理代码读取
GICC_IAR获取中断号。 - 根据中断号,调用预先注册的中断处理函数(ISR)。
- ISR执行设备特定的操作(如读取数据寄存器)。
- ISR返回后,内核代码向
GICC_EOIR写入中断号,完成中断处理。
配置心得:对于实时性要求高的中断,除了设置高优先级,还应考虑将其绑定到特定的CPU核心,并确保该核心的本地中断(如定时器中断)优先级设置合理,避免被内部中断抢占。同时,电平触发的中断在ISR中必须清除外设的中断标志位,否则GIC会认为中断一直有效,导致中断风暴。
3.3 时钟、复位与电源管理集成
MPU子系统不是一个孤岛,它的时钟、复位和电源状态受SoC顶层电源与时钟管理模块(PRCM)的统一控制。
- 时钟:MPU PLL为整个MPU子系统生成核心工作时钟(
MPU_CLK)。SCU、GIC、定时器等模块的时钟通常由此分频或直接使用。 - 电源域:参考框图,MPU子系统可能被划分到不同的电源域。例如,调试追踪模块(PTM)可能位于常开(Always-On)域,以便在CPU深度睡眠时仍能记录唤醒事件。而CPU核心和L1缓存可能位于一个可关断的域。理解电源域的划分对实现低功耗功能至关重要。你需要查阅具体的芯片手册,了解将CPU置入各种低功耗模式(如
WFI,CPUIDLE)时,具体会关断哪些模块的时钟和电源。 - 看门狗定时器:集成在SCU中的看门狗定时器位于MPU系统电源域。这意味着,即使CPU核心因为
WFI指令被时钟门控,只要MPU域还在供电,看门狗计数器依然在运行。如果你希望CPU睡眠时看门狗暂停,必须在进入睡眠前在软件中禁用看门狗,否则可能会被意外复位。
4. 系统互连(L3 NoC)与MPU子系统的协同
MPU子系统通过其主端口(Master Port)连接到SoC的L3网络互连(NoC)。理解L3 NoC的拓扑和访问规则,才能明白数据如何高效地在CPU、DMA、外设和内存之间流动。
4.1 L3 NoC拓扑与端口映射
���提供的文档图4-1可以看出,L3互连是一个分层、分时钟域的结构:
- L3F(Fast):高速时钟域,连接对带宽和延迟要求最高的主设备和从设备。MPU子系统的128位主端口(M1)和64位主端口(M2)、图形加速器(SGX530)、DMA控制器(TPTC)等都连接在此。
- L3S(Slow):低速时钟域,连接各类外设控制器,如USB、以太网、MMC/SD等。
MPU子系统的访问路径:
- MPUSS M1 (128-bit):这是一个高性能端口,从表4-1可知,它只连接到外部内存接口(EMIF)。这意味着CPU通过此端口发起的内存访问(尤其是大数据块、高带宽操作)会直接、高效地通往DDR内存,是性能的关键路径。
- MPUSS M2 (64-bit):这是一个通用端口,可以访问几乎所有的L3从设备,包括片上RAM(OCMC)、外设配置空间(L4_PER)、调试子系统等。对大多数外设寄存器的读写操作都通过这个端口。
4.2 连接ID(ConnID)与调试、性能监控
L3 NoC中的每个事务都带有一个6位的主连接标识符(MConnID),它唯一标识了事务的发起者。如表4-2所示,MPU子系统的两个主端口M1和M2分别被赋予了固定的MConnID(0x00和0x01)。
这个设计在系统调试和性能分析中极其有用:
- 错误定位:当L3互连报告一个访问错误(如地址错误、权限错误)时,错误日志中会包含MConnID。开发者可以迅速定位是哪个主设备(例如是CPU的M2端口还是某个DMA控制器)发起了非法访问。
- 性能剖析:SoC内部通常集成有性能监控计数器,可以统计通过特定路径的流量、延迟等信息。通过过滤特定的MConnID,我们可以单独分析CPU访问内存的带宽利用率、访问延迟分布,从而精准定位性能热点是在CPU端、L3网络还是内存控制器端。
- 数据流追踪:高级的调试工具可以利用MConnID来追踪特定主设备发起的数据流在整个芯片中的传播路径,对于诊断复杂的数据一致性问题非常有帮助。
4.3 实际应用中的配置与优化思路
基于以上架构知识,在实际项目中我们可以进行多项优化:
1. 内存属性与缓存策略优化:在设置MMU页表时,针对不同的内存区域采用不同的缓存策略。
- 代码区:设置为“可执行、缓存使能、写回”。利用L1 I-Cache和L2缓存加速取指。
- 堆栈、全局变量区:设置为“可读写、缓存使能、写回”。利用数据缓存提升访问速度。
- DMA缓冲区:设置为“可读写、非缓存、或直写”。避免缓存一致性问题。对于频繁被CPU和DMA交替访问的大缓冲区,可以考虑使用“直写”策略,CPU写操作同时更新缓存和内存,简化维护。
- 外设寄存器区:必须设置为“设备内存、非缓存、非缓冲”。确保每次读写都直接到达设备,且访问顺序被严格保持。
2. 中断延迟优化:
- 将关键实时中断的优先级在GIC中设为最高。
- 确保该中断的服务程序(ISR)放在L1或L2 SRAM中执行,避免因指令缓存缺失引入额外延迟。
- 在ISR中尽量避免复杂的函数调用和可能引起缓存缺失的内存访问。
3. 低功耗场景下的注意事项:
- 在让CPU进入深度睡眠前,检查所有可能唤醒CPU的中断是否已在WakeUpGen中正确使能。
- 如果使用L2作为SRAM来保存唤醒后的快速恢复上下文,需确保该SRAM区域所在的电源域在睡眠期间不会掉电。
- 仔细处理看门狗定时器,根据睡眠深度决定是暂停还是保持运行。
5. 常见问题排查与实战经验分享
即便理解了原理,在实际开发和调试中,依然会遇到各种棘手的问题。下面分享几个我踩过的“坑”以及排查思路。
5.1 数据一致性问题:CPU与DMA看到的“世界”不同
现象:CPU向一段内存写入数据,然后启动DMA从该内存读取数据并发送出去,但DMA读到的却是旧数据(全0或随机值)。或者反过来,DMA向内存写入数据,CPU却读不到新数据。
根本原因:缓存一致性未正确维护。CPU写入的数据可能还停留在自己的缓存(L1 D-Cache或L2 Cache)中,并未真正写回内存。DMA控制器是总线主设备,它直接访问内存,绕过了CPU的缓存,因此看不到缓存中的新数据。
解决方案与步骤:
- 正确设置内存属性:将用作DCA缓冲区的内存区域在MMU页表中标记为“非缓存”(Non-cacheable)或“直写”(Write-Through)。这是最根本、最高效的解决方法,但可能损失一些CPU访问性能。
- 手动维护缓存一致性:如果该缓冲区也需要被CPU高效访问(例如作为计算中间结果),则需要在关键节点执行缓存维护操作:
- DMA读取前(CPU写 -> DMA读):在CPU写完数据后、启动DMA传输前,调用
clean操作(如ARM的CP15指令或Linux的dma_clean_range),将指定地址范围的缓存数据写回内存。 - CPU读取前(DMA写 -> CPU读):在DMA传输完成后、CPU读取数据前,调用
invalidate操作(如dma_inv_range),无效化CPU缓存中对应地址的数据,迫使CPU下次访问时从内存重新加载。 - 双向频繁访问:使用
clean and invalidate操作(如dma_flush_range),它先写回再无效化,保证两端看到一致的数据。
- DMA读取前(CPU写 -> DMA读):在CPU写完数据后、启动DMA传输前,调用
排查工具:使用芯片的硬件性能计数器(如果支持)监控L1 D-Cache和L2 Cache的
clean和invalidate操作次数。如果这些次数异常高,说明缓存一致性维护开销很大,应考虑调整内存属性或缓冲区使用策略。
5.2 系统在低功耗唤醒后行为异常或卡死
现象:系统成功进入低功耗状态(如WFI),也能被中断唤醒,但唤醒后程序跑飞、外设不工作或很快再次卡死。
排查思路:
- 检查时钟与电源域恢复:确认在唤醒流程中,所有必要的外设时钟和电源域都已正确恢复。有些外设在深度睡眠下会完全掉电,其寄存器内容会丢失,唤醒后需要像上电一样重新初始化。MPU子系统的某些模块(如GIC、定时器)可能也需要重新配置。
- 检查WakeUpGen配置:确认唤醒CPU的中断确实在对应的
WkUpGenEnb寄存器中被使能。一个常见的疏忽是只配置了GIC的中断使能,却忘了配置WakeUpGen。 - 检查栈和关键数据:如果低功耗模式下CPU的通用寄存器内容不保存(有些深度睡眠模式会丢失),那么唤醒后CPU会从睡眠指令后的地址开始执行。确保唤醒后的初始化代码不依赖于睡眠前栈上的局部变量。将唤醒后必须用到的上下文保存在非缓存SRAM(如配置为SRAM的L2)或始终保持供电的存储器中。
- 检查中断状态:唤醒后,检查GIC的中断状态寄存器,确认是否是预期的中断源产生了唤醒。有时多个中断可能几乎同时发生,需要妥善处理。
5.3 L2缓存性能未达预期或功能异常
现象:系统运行速度慢,性能分析工具显示L2缓存命中率极低,或者当尝试将L2配置为SRAM时系统挂死。
排查与解决:
- 确认L2缓存已使能:系统复位后L2缓存默认是关闭的。在启动早期(通常在Bootloader或内核非常初期的汇编代码中),需要通过写PL310的控制寄存器来启用它。忘记启用L2缓存会导致所有访问直接穿透到更慢的L3或DDR,性能损失巨大。
- 检查地址过滤配置:如果无意中通过PL310的地址过滤寄存器将大量频繁访问的地址范围(如代码区)排除在了缓存之外,会导致L2形同虚设。检查相关配置。
- L2作为SRAM的时钟配置错误:这是最危险的错误之一。如前所述,必须保证OCMC(L2 SRAM模式)的时钟频率不高于L3互连的时钟频率。如果
PIL2SRAMCLKDIV配置不当,会导致异步桥数据丢失,表现为往SRAM写数据后读回错误,或直接导致总线挂死。务必严格按照芯片数据手册推荐的时钟分频比进行配置。 - 动态切换模式:绝对不要在系统运行时动态切换L2的工作模式(缓存<->SRAM)。这种操作必须在系统完全静止、没有访问L2的情况下进行,通常只在启动初始化阶段完成。
5.4 中断无法触发或中断响应延迟高
现象:外设中断已经产生,但CPU没有响应,或者响应速度很慢。
排查步骤:
- 信号通路排查:使用示波器或逻辑分析仪检查物理中断信号线是否有跳变。确认外设的中断输出已使能,并且中断标志位已置起。
- GIC配置检查:
- 分发器级:确认该中断在
GICD_ISENABLERn中已使能。确认中断优先级GICD_IPRIORITYRn已设置(不能是默认的0xFF,即最低优先级)。确认中断目标CPUGICD_ITARGETSRn已设置正确(单核系统通常设为0x01)。 - CPU接口级:确认CPU核心已通过写
GICC_PMR寄存器设置了中断优先级阈值(只有优先级高于此值的中断才会被递送)。确认已通过写GICC_CTLR寄存器全局启用了CPU接口的中断处理。
- 分发器级:确认该中断在
- 中断触发类型:检查
GICD_ICFGRn寄存器,确认配置的触发类型(边沿/电平)与外设实际产生的中断类型匹配。电平触发的中断,必须在ISR中清除外设的中断源,否则GIC会持续认为中断有效。 - 中断屏蔽:检查CPU的CPSR寄存器中的I位(IRQ屏蔽位)和F位(FIQ屏蔽位)是否被意外清除。在关键的临界区,操作系统或驱动可能会屏蔽中断。
- 性能问题:如果中断响应慢,检查ISR是否过长、是否包含了可能导致大量缓存缺失的代码、或者是否被更高优先级的中断或任务长时间阻塞。使用L2 SRAM存放最关键的ISR代码和数据可以显著减少延迟抖动。
理解ARM Cortex-A9 MPU子系统,是一个从模糊到清晰,再从清晰到熟练运用的过程。它不像编写一个驱动那样有立竿见影的成就感,但它的影响是全局性的、基础性的。当你为一个性能瓶颈焦头烂额时,当你为一次诡异的系统宕机苦苦追踪时,对MPU子系统架构的深刻理解,往往能让你拨云见日,找到那条最根本的解决路径。这份手册中的框图、寄存器描述和连接表格,就是为你绘制的一张通往系统核心地带的地图,值得在项目初期就花时间仔细研读,并在整个开发周期内时常回顾。