基于ARM的嵌入式系统程序开发要点(三)——如何满足嵌入式系统的灵活需求
时间:03-20
来源:互联网
点击:
4.存储器地址重映射(memory remap)
存储器地址重映射是当前很多先进控制器所具有的功能。在上一节中已经提到了 0 地址处存储器重映射的例子,简而言之,地址重映射就是可以通过软件配置来改变一块存储器物理地址的一种机制或方法。
当一段程序对运行自己的存储器进行重映射的时候,需要特别注意保证程序执行流程在重映射前后的承接关系。下面是一种典型的存储器地址重映射情况:
图-5 存储器重映射举例 1
系统上电后的缺省状态是 0地址上放有 ROM,这块 ROM 有两个地址:从0起始和从0x10000 起始,里面存储了初始化代码。当进行地址 remap以后,从 0起始的地址被定向到了 RAM 上,ROM 则只保留有唯一的从 0x10000 起始的地址了。
如果存储在 ROM 里的 Reset_Handler 一直在0 – 0x4000的地址上运行,则当执行完remap以后,下面的指令将从RAM 里预取,必然会导致程序执行流程的中断。根据系统特点,可以用下面的办法来解决这个问题:
(1) 上电后系统从 0 地址开始自动执行,设计跳转指令在 remap 发生前使 PC指针指向0x10000 开始的 ROM 地址中去,因为不同地址
指向的是同一块ROM,所以程序能够顺利执行。
(2) 这时候 0 - 0x4000的地址空间空闲, 不被程序引用, 执行remap后把 RAM引进。因为程序一直在 0x10000 起始的 ROM 空间里
运行,remap 对运行流程没有任何影响。
(3) 通过在 ROM 里运行的程序,对 RAM 进行相应的代码和数据拷贝,完成应用程序运行的初始化。
下面是一段实现上述步骤的例程:
-------------------------------------------------------------------------------------------------------
ENTRY
;启动时,从 0 开始,设法跳转到“真”的ROM 地址(0x10000 开始的空间里)
LDR pc, =start
;insert vector table here
…
Start ;Begin of Reset_Handler
; 进行 remap设置
LDR r1, =Ctrl_reg ;假定控制 remap的寄存器
LDR r0, [r1]
ORR r0, r0, #Remap_bit ;假定对控制寄存器进行 remap设置
STR r0, [r1]
;接下去可以进行从 ROM 到 RAM 的代码和数据拷贝
-------------------------------------------------------------------------------------------------------
除此之外,还有另外一种常见的remap方式,如下图:
图-6 存储器重映射举例 2
原来 RAM 和 ROM 各有自己的地址, 进行重映射以后 RAM 和 ROM 的地址都发生了变化,这种情况下,可以采用以下的方案:
(1) 上电后,从 0 地址的 ROM 开始往下执行。
(2) 根据映射前的地址,对 RAM 进行必要的代码和数据拷贝。
(3) 拷贝完成后,进行 remap操作。
(4) 因为 RAM 在 remap 前准备好了内容,使得 PC 指针能继续在 RAM 里取到正确的指令。
不同的系统可能会有多种灵活的 remap方案,根据上面提到的两个例子,可以总结出最根本的考虑是: 要使程序指针在 remap以后能继续往下得到正确的指令。
5. 根据目标存储器系统分散加载映像(scatterloading)
Scatterloading 文件是 ARM 的工具链里面的一个特性,作为程序编译过程中给连接器使用的一个参数,用来指定最终生成的目标映像文件运行时的分布状态。如果用户程序映像只是如图7 所示的最简状态,所有的可执行代码都集合放置在一起,那么可以不使用 Scatterloading 文件,直接用连接器的命令行选项就能够完成设置:
RO = 0x00000:表示映像的第一条指令开始地址;
RW = 0x10000:表示变量区的起始地址,变量区一定要位于 RAM 区。
图-7 简单的映像分布举例
但是一个复杂的系统可能会把映像分割成几个部分。如图 8,系统中存在多种类型的存储器,不能的代码部分根据执行性能优化的考虑分布与不同的地方。
图-8 复杂的映像分布举例
这时候不能通过简单的 RO、RW 参数来完成实现上述配置,就要用到scatterloading 文件了。在 scatterloading文件里,可以给编译出来的各个目标模块指定运行地址,下面的例子是针对图8 的。
FLASH 0x20000 0x8000
{
FLASH 0x20000 0x8000
{
init.o (Init, +First)
* (+RO)
}
32bitRAM 0x0000
{
vectors.o (Vect, +First)
handlers.o (+RO)
}
STACK 0x1000 UNINIT
{
stackheap.o (stack)
}
:
:
16bitRAM 0x10000
{
* (+RW,+ZI)
}
HEAP 0x15000 UNINIT
{
stackheap.o (heap)
}
}
关于 scatterloading文件的详细语法,请参阅 ARM 公司的相关手册。
存储器地址重映射是当前很多先进控制器所具有的功能。在上一节中已经提到了 0 地址处存储器重映射的例子,简而言之,地址重映射就是可以通过软件配置来改变一块存储器物理地址的一种机制或方法。
当一段程序对运行自己的存储器进行重映射的时候,需要特别注意保证程序执行流程在重映射前后的承接关系。下面是一种典型的存储器地址重映射情况:
图-5 存储器重映射举例 1
系统上电后的缺省状态是 0地址上放有 ROM,这块 ROM 有两个地址:从0起始和从0x10000 起始,里面存储了初始化代码。当进行地址 remap以后,从 0起始的地址被定向到了 RAM 上,ROM 则只保留有唯一的从 0x10000 起始的地址了。
如果存储在 ROM 里的 Reset_Handler 一直在0 – 0x4000的地址上运行,则当执行完remap以后,下面的指令将从RAM 里预取,必然会导致程序执行流程的中断。根据系统特点,可以用下面的办法来解决这个问题:
(1) 上电后系统从 0 地址开始自动执行,设计跳转指令在 remap 发生前使 PC指针指向0x10000 开始的 ROM 地址中去,因为不同地址
指向的是同一块ROM,所以程序能够顺利执行。
(2) 这时候 0 - 0x4000的地址空间空闲, 不被程序引用, 执行remap后把 RAM引进。因为程序一直在 0x10000 起始的 ROM 空间里
运行,remap 对运行流程没有任何影响。
(3) 通过在 ROM 里运行的程序,对 RAM 进行相应的代码和数据拷贝,完成应用程序运行的初始化。
下面是一段实现上述步骤的例程:
-------------------------------------------------------------------------------------------------------
ENTRY
;启动时,从 0 开始,设法跳转到“真”的ROM 地址(0x10000 开始的空间里)
LDR pc, =start
;insert vector table here
…
Start ;Begin of Reset_Handler
; 进行 remap设置
LDR r1, =Ctrl_reg ;假定控制 remap的寄存器
LDR r0, [r1]
ORR r0, r0, #Remap_bit ;假定对控制寄存器进行 remap设置
STR r0, [r1]
;接下去可以进行从 ROM 到 RAM 的代码和数据拷贝
-------------------------------------------------------------------------------------------------------
除此之外,还有另外一种常见的remap方式,如下图:
图-6 存储器重映射举例 2
原来 RAM 和 ROM 各有自己的地址, 进行重映射以后 RAM 和 ROM 的地址都发生了变化,这种情况下,可以采用以下的方案:
(1) 上电后,从 0 地址的 ROM 开始往下执行。
(2) 根据映射前的地址,对 RAM 进行必要的代码和数据拷贝。
(3) 拷贝完成后,进行 remap操作。
(4) 因为 RAM 在 remap 前准备好了内容,使得 PC 指针能继续在 RAM 里取到正确的指令。
不同的系统可能会有多种灵活的 remap方案,根据上面提到的两个例子,可以总结出最根本的考虑是: 要使程序指针在 remap以后能继续往下得到正确的指令。
5. 根据目标存储器系统分散加载映像(scatterloading)
Scatterloading 文件是 ARM 的工具链里面的一个特性,作为程序编译过程中给连接器使用的一个参数,用来指定最终生成的目标映像文件运行时的分布状态。如果用户程序映像只是如图7 所示的最简状态,所有的可执行代码都集合放置在一起,那么可以不使用 Scatterloading 文件,直接用连接器的命令行选项就能够完成设置:
RO = 0x00000:表示映像的第一条指令开始地址;
RW = 0x10000:表示变量区的起始地址,变量区一定要位于 RAM 区。
图-7 简单的映像分布举例
但是一个复杂的系统可能会把映像分割成几个部分。如图 8,系统中存在多种类型的存储器,不能的代码部分根据执行性能优化的考虑分布与不同的地方。
图-8 复杂的映像分布举例
这时候不能通过简单的 RO、RW 参数来完成实现上述配置,就要用到scatterloading 文件了。在 scatterloading文件里,可以给编译出来的各个目标模块指定运行地址,下面的例子是针对图8 的。
FLASH 0x20000 0x8000
{
FLASH 0x20000 0x8000
{
init.o (Init, +First)
* (+RO)
}
32bitRAM 0x0000
{
vectors.o (Vect, +First)
handlers.o (+RO)
}
STACK 0x1000 UNINIT
{
stackheap.o (stack)
}
:
:
16bitRAM 0x10000
{
* (+RW,+ZI)
}
HEAP 0x15000 UNINIT
{
stackheap.o (heap)
}
}
关于 scatterloading文件的详细语法,请参阅 ARM 公司的相关手册。
- 嵌入式系统的定义与发展历史(11-15)
- 嵌入式系统亲密接触(11-22)
- 嵌入式系统设计中的USB OTG方案(02-01)
- 嵌入式线控驾驶系统开发过程中设计和测试考虑(02-02)
- 一个典型的嵌入式系统设计和实现 (02-02)
- DDR SDRAM在嵌入式系统中的应用(02-07)