Arm Cortex-M4 处理器采用哈佛结构,可以使用相互独立的总线来读取指令和加载/存储 数据。指令代码和数据都位于相同的存储器地址空间,但在不同的地址范围。程序存储器, 数据存储器,寄存器和I/O端口都在同一个线性的4 GB(Cortex-M4的地址总线宽度是32位的,最大地址为 0xFFFF FFFF)的地址空间之内。
借助总线矩阵,可以实现主控总线到被控总线的访问(访问仲裁管理采用循环调度算法),这样即使在多个高速外设同时运行期间,系统也可以实现并发访问和高效运行。
1. 存储器映射
在明白什么是存储器映射前,我们需要明白什么是映射?在数学里,映射是个术语,指两个元素的集之间元素相互“对应”的关系,为名词。
如图1所示,两个非空集合A与B间存在着对应关系f,而且对于A中的每一个元素x,B中总有唯一的一个元素y与它对应,就这种对应为从A到B的映射,记作f:A→B。其中,y称为元素x在映射f下的像 ,记作:y=f(x)。x称为y关于映射f的原像 。集合A中所有元素的像的集合称为映射f的值域,记作f(A)。
存储器(Memory)是单片机最重要的功能单元之一,是众多存储单元的集合,而存储器(Memory)本身并不具有地址信息,那么CPU(ARM Cortex-M4内核)要准确的找到存储某个信息的存储单元,就必须为这些单元分配一个相互区别的标识,这个标识就是我们通常所说的地址编码。
例如在STM32微控制器(MCU)STM32F407中,集成了多种类型的 Memory,同一类型的 Memory 为一个 Memory Block(block 0 ~ block 7),每一个都被分配一个数值连续、存储单元数相等、以16进制表示的自然数集合作为 Memory Block 的地址编码。这种自然数集合与 Memory Block 的对应关系,就是 Memory Map(存储器映射),有时也叫 Address Map(地址映射)。实际上,Address Map在字面意义上更加贴切。
需要强调的是,Memory Map 是一个逻辑概念,是计算机系统在(上电)复位后才建立起来的。Memory Map 相当于这样一个数学函数:函数的输入量是地址编码,输出量被寻址单元中的数据。当微控制器(MCU)掉电后或复位时,这个数学函数不复存在,只剩下微控制器(MCU)中实现这个数学函数的物理基础——电路连接。也可以这样认为:Memory Map 是微控制器(MCU)(上电)复位时的预备动作,是一个将CPU所拥有的地址编码资源向系统内各个物理存储器块分配的自动过程。简而言之,存储器映射就是为物理存储器按一定编码规则分配地址的行为。
在完成存储器映射后,用户就可以按照存储器地址去访问对应的物理存储器。比如我要访问 SRAM,只需要访问0x2000 0000到0x2001 FFFF的地址即可。
值得注意,一部分地址空间由 Arm Cortex-M4 的系统外设所占用,且不可更改。此外,其余部分地址空间可由芯片供应商(ST,意法半导体)定义使用。用户只能用而不能改(为了降低不同客户在相同应用时 的软件复杂度)。用户只能在挂外部RAM或FLASH的情况下可进行自定义。
Arm Cortex-M4只有一个单一固定的存储器映射,这一点方便了我们在该系列之间的移植。
2. 存储器重映射
通常系统启动都是从0地址处开始,但是为了支持不同的存储介质,不同的存储介质被分配了一个非0地址区域。这就是为什么要进行重映射。
因此重映射主要发生在两种情况下,一系统启动的过程中;二如果中途遇到需要在不同的存储器之间进行切换的时候也需要进行重映射。
存储器采用固定的存储器映射,代码区域起始地址为 0x0000 0000(通过 ICode/DCode 总 线访问),而数据区域起始地址为 0x2000 0000(通过系统总线访问)。STM32F4xx 微控制器实施一种特殊机制,
将各自存储空间的地址映射到0x00000000中。
在 STM32F4xx 中,可通过 BOOT[1:0] 引脚选择三种不同的 boot modes。
1)从Flash启动,将Flash地址0x08000000映射到0x00000000,这样启动以后就相当于从0x08000000开始的,这是我们最常用的模式;
当选择从主Flash启动模式后,芯片一上电,Flash的0x0800 0000地址被映射到0地址处,不影响CM4内核的读取,所以这时的CM4既可以在0地址处访问中断向量表,也可以在0x0800 0000地址处访问中断向量表,而代码还是在0x0800 0000地址处存储的。
2)从SRAM启动,将SRAM地址0x20000000映射到0x00000000,这样启动以后就相当于从0x20000000开始的,用于调试;
3)从系统存储器启动,将系统存储器地址0x1FFFF000映射到0x00000000,这样启动以后就相当于从0x1FFFF000开始执行的,值得注意的是这个系统存储器里面存储的其实是STM32自带的Bootloader代码,这其实是一个官方的IAP,它提供了可以通过UART1接口将用户的代码下载到Flash中的功能,下载完以后再切换到从Flash中启动就可以正常运行了。
当然还可以通过SYSCFG Memory Remap(存储器重映)寄存器(SYSCFG_MEMRMP)对存储器重映射进行配置:
参考资料
-
【百度百科】映射(数学名词)