ARM 引导加载程序 : Disable MMU and Caches

标签 arm bootloader mmu

根据一些教程,我们会在 bootlaoder 开始时禁用 MMU 和 I/D-Caches。如果我理解正确,它的目的是在程序中直接使用物理地址,所以如果我错了,请纠正我。谢谢!
其次,我们这样做是为了禁用 MMU 和缓存:

mrc P15, 0, R0, C1, C0, 0

bic R0, R0, #0x00002300 @ clear bits 13, 9:8

bic R0, R0, #0x00000087 @ clear bits 7, 2:0

orr R0, R0, #0x00000002 @ set bit 2 (A) Align

orr R0, R0, #0x00001000 @ set bit 12 (I) I-Cache

mcr P15, 0, R0, C1, C0, 0


D-Cache、MMU 和数据地址对齐故障检查已被清除位 2:0 禁用,但为什么我们在以下仪器中立即启用位 2?确保这种操作有效?
最后一个问题是为什么 D-cache 被禁用而 I-caches 可以?加快仪器进程?

最佳答案

最后一个问题是为什么 D-cache 被禁用而 I-caches 可以?加快仪器进程?

MMU 具有确定哪些内存区域可缓存或不可缓存的设置。如果您没有打开 mmu 但您打开了数据缓存(如果可能),那么您将无法安全地与外围设备通信。例如,如果您读取 uart 状态寄存器,它就像任何其他数据操作一样通过缓存,那么无论该状态是什么,都将保留在缓存中以供后续读取,直到该缓存线被逐出并且您再获得一次实际登记。例如,假设您有一些代码轮询 uart 状态寄存器以等待 rx 缓冲区中的字符。如果第一次读取显示没有字符,则该状态进入缓存,您将永远留在循环中,因为您将永远无法再次与状态寄存器交谈,您只会获得寄存器的缓存副本。如果那里有一个字符,那么该状态也会被缓存,你读取 rx 寄存器,也许做一些事情,如果当你再次回来时,如果状态没有从数据缓存中被驱逐,那么你会得到陈旧的状态,它显示有一个字符,您读取的 rx 缓冲区可能会也可能不会被缓存,因此您可能会在缓存中获得过时的值,您可能会获得过时的值或读取时外围设备所做的任何事情并且没有新值,或者您可能获得一个新值,但在这些情况下你得不到的是对外围设备的正确访问。当 mmu 打开时,您使用 mmu 将该外设使用的地址空间标记为不可(数据)缓存,并且您没有这个问题。关闭 mmu 后,您需要关闭 arm 系统的数据缓存。

保持 I-cache 处于打开状态是可以的,因为指令只获取读取指令......对于裸机应用程序来说是可以的,例如,如果您使用具有读取干扰潜力的闪存(spi 或 i2c 闪存),它会有所帮助.问题是这个应用程序是一个引导加载程序,所以你必须格外小心。例如,您的引导加载程序在地址 0x8000 处有一些代码,它至少运行一次,然后您选择将其用作引导加载程序,引导加载程序可能位于地址 0x10000000 允许您在 0x8000 加载新程序,此加载使用数据访问,因此它不会通过指令缓存。因此,指令缓存有可能包含您上次在 0x8000 区域时的部分或全部代码,当您跳转到 0x8000 处的引导加载代码时,您将从缓存中获取旧程序或令人讨厌的混合缓存和未缓存部分的旧程序和新程序。因此,如果您的引导加载程序允许启用 i-cache,则您需要在跳转到引导加载代码之前使缓存无效。

最后,如果您或任何使用此引导加载程序的人想要使用 jtag,那么您会遇到同样的问题,但更糟糕的是,当您告诉 jtag 调试器时,不通过 i-cache 的数据周期将用于将新程序写入 ram然后运行新程序,您将获得 1) 只有新程序,2) 缓存中的新程序和旧程序片段的混合 3) 缓存中的旧程序。

因此,没有 mmu 的 d-cache 很糟糕,因为它不在 ram、外围设备等中。 i-cache 是一种使用风险自负的东西,除了 jtag 用于调试的时间外,您可以减轻这种风险.

如果您有顾虑或已确认(外部)闪存中存在读取干扰,那么我建议打开 i-cache,使用紧密循环将您的应用程序复制到 ram,分支到 ram 副本并在那里运行,关闭i-cache(或自担风险使用)并且不要再次接触闪存,当然不是对小区域的大量读取访问。像命令行解析器那样的紧密 uart 轮询循环,是遇到读取干扰的好地方。

关于ARM 引导加载程序 : Disable MMU and Caches,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21262014/

相关文章:

memory - CPU物理地址空间如何映射到物理DRAM?

memory-management - 查找 Solaris 中从虚拟页到物理页的映射

linux - 无法使用 libcurl(为 arm 交叉编译)应用程序发送电子邮件

optimization - 针对 ARM : Why different CPUs affects different algorithms differently (and drastically) 进行优化

assembly - 程序计数器不前进

x86 - int 13h 42h 在 Bochs 中不加载任何东西

assembly - 访问跨 MMU 页边界的变量

visual-studio - 如何定义一个占用多个其他变量空间的变量?

assembly - 如何通过BIOS中断在实模式下处理键盘?

linux-kernel - Linux ARM 启动中地址 ZTEXTADDR 的使用