3. 编写链接脚本控制内存布局
任务目标
在VxWorks BSP开发中,链接脚本(Linker Script)决定了内核镜像各段(代码段、数据段、BSS段等)在目标板内存中的具体放置位置。本案例要求修改链接脚本,将代码段(.text)放置到指定的Flash/ROM区域,将数据段(.data)放置到指定的RAM区域,并确保BSS段紧随数据段之后。
环境与依赖
- VxWorks 7 或 VxWorks 6.9+ BSP开发环境
- 目标架构:以ARM Cortex-A9为例(不同架构语法略有差异,但原理相同)
- 需要修改的文件:BSP目录下的
linkerScript.ld(或linker.cmd,取决于BSP模板)
关键实现
以下链接脚本将内存划分为两个区域:FLASH(起始地址0x00000000,大小1MB)用于存放代码段和只读数据;RAM(起始地址0x80000000,大小256MB)用于存放可读写数据。通过>FLASH和>RAM指令将各段显式映射到对应内存区域。
/* linkerScript.ld - 控制内存布局 */
ENTRY(_start)
MEMORY
{
/* 指定内存区域:名称、起始地址、长度 */
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1M
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 256M
}
SECTIONS
{
/* 代码段:放置在FLASH区域 */
.text :
{
*(.text*)
*(.rodata*)
*(.got*)
} > FLASH
/* 数据段:放置在RAM区域 */
.data :
{
__data_start = .;
*(.data*)
__data_end = .;
} > RAM
/* BSS段:紧随数据段之后,仍位于RAM */
.bss :
{
__bss_start = .;
*(.bss*)
*(COMMON)
__bss_end = .;
} > RAM
/* 堆栈区域:放置在RAM末尾 */
.stack (NOLOAD) :
{
__stack_start = .;
. = . + 0x10000; /* 64KB栈空间 */
__stack_end = .;
} > RAM
}
编译与集成
- 将上述脚本内容替换BSP中原始的链接脚本文件。
- 在BSP的
config.h或Makefile中确认链接脚本路径被正确引用(通常通过LDSCRIPT变量指定)。 - 重新编译BSP:
make clean && make(或使用Workbench的Build菜单)。
验证方法
编译完成后,通过以下方式验证内存布局是否符合预期:
- 检查map文件:编译生成的
vxWorks.map文件中,查看.text段的起始地址应位于0x00000000附近(FLASH区域),.data段的起始地址应位于0x80000000附近(RAM区域)。 - 查看符号地址:在map文件中查找
__data_start和__bss_start的地址,确认它们均落在RAM区域内。 - 运行验证:将镜像烧录到目标板后,在VxWorks shell中执行
lkup命令查看内核模块加载地址,或使用d命令检查指定内存地址的内容,确认代码在Flash中执行、数据在RAM中读写正常。
通过条件:map文件中各段地址与MEMORY指令定义的区域一致;目标板启动后系统正常运行,无内存访问异常。
常见问题
- 启动时数据段未初始化:若代码段在Flash中而数据段在RAM中,必须在启动代码(
sysInit或romInit)中增加将.data从Flash拷贝到RAM的步骤(使用__data_start/__data_end符号定位),否则RAM中的数据无初始值。 - 地址溢出:若代码段超过FLASH区域长度(1MB),链接会报错。此时需增大FLASH的LENGTH或优化代码体积。
- 缓存一致性:若代码在Flash中执行,需确保MMU配置中该区域被标记为可执行且缓存属性正确(通常设为写保护+缓存使能)。