嵌入式软件开发之: 进一步存储器映射考虑事项
13.6 进一步存储器映射考虑事项
上一节介绍了如何使用Scatter文件对程序的代码和数据进行放置。但这些方法只有在外设和堆栈限制在源文件或头文件中定义好的前提下才能使用。为了增加程序的灵活性,最好在Scatter文件中设置这些信息,本节将介绍这些方法。
13.6.1 在Scatter文件中定位目标外设
通常情况下,外设寄存器的内存映射地址是在源文件或头文件中定义的“硬编码(hard-code)”。但为了增加代码的可移植性,可以在源文件中声明一个映射到外设寄存器的结构,并在这个结构在Scatter文件中定位。
下面的例子定义了映射32位寄存器的定时器的C结构。
struct {
volatile unsigned ctrl; /* timer 控制寄存器 */
volatile unsigned tmr; /* timer值 */
} timer_regs;
要把该结构放在存储器映射的特定地址,需创建一个新的执行区来装入该结构。
下面的例子说明了在Scatter文件中将timer_regs结构定位在0x40000000地址处。
ROM_LOAD 0x24000000 0x04000000
{
; ...
TIMER 0x40000000 UNINIT
{
timer_regs.o (+ZI)
}
; ...
}
需要特别注意的是,在应用程序启动过程中不将这些寄存器的内容初始化为零,因为这些地址对应的是外设寄存器,如果将其初始化为0,很可能改变系统的状态。必须将执行域的属性标记为UNINIT,这样可避免该区中的ZI数据初始化为零。
13.6.2 在Scatter文件中放置堆和栈
ARM公司建议,在Scatter文件中指定堆和栈的位置。这主要有两个主要优点:
· 有关存储器映射的所有信息保存在一个文件中;
· 改变堆和栈只要求重新链接,而不需要重新编译。
1.显示放置标号
为了在Scatter文件中放置堆栈,必须在源文件中定义Scatter文件的参照符号。下面的例子在名为stackheap.s的汇编文件中创建标有stack_base和heap_base的符号。这样就可以在Scatter文件的执行域中定位每个符号。
AREA stacks, DATA, NOINIT
EXPORT stack_base
stack_base SPACE 1
AREA heap, DATA, NOINIT
EXPORT heap_base
heap_base SPACE 1
END
下面的Scatter文件说明了如何在地址0x20000放置堆基址,如何在地址0x40000放置栈基址。堆基址和栈基址的位置可通过分别编辑其执行区予以改变。但该方法的缺点是在该栈区的上部占用一个字的内存区域放置SPACE(stack_base)变量。
LOAD_FLASH 0x24000000 0x04000000
{
; ...
HEAP 0x20000 UNINIT
{
stackheap.o (heap)
}
STACKS 0x40000 UNINIT
{
stackheap.o (stacks)
}
; ...
}
评论