3. Bootloader与应用程序内存分区规划
任务目标
为Bootloader与应用程序规划独立的内存分区,明确起始地址、分区大小及访问保护机制,确保两者在Flash中互不干扰,并为后续跳转与升级功能奠定地址基础。
内存布局设计
以瑞萨RH850/P1x系列(32位MCU,Flash起始地址0x00000000)为例,设计如下布局:
- Bootloader区:0x00000000 ~ 0x0000FFFF(64KB),存放启动代码与升级驱动
- 应用程序区:0x00010000 ~ 0x0007FFFF(448KB),存放应用逻辑
- Flash保护状态寄存器区:0x00000000 起始的专用配置字(由芯片选项字节控制)
链接脚本实现(GHS Linker Script)
以下链接脚本定义物理分区与访问权限,是内存规划落地的核心文件:
/* memory_layout.ld */
MEMORY
{
/* Bootloader区:64KB,只读+可执行 */
FLASH_BOOT (rx) : ORIGIN = 0x00000000, LENGTH = 64K
/* 应用程序区:448KB,只读+可执行 */
FLASH_APP (rx) : ORIGIN = 0x00010000, LENGTH = 448K
/* 内部RAM:用于Bootloader与App共享的跳转参数 */
RAM (rwx) : ORIGIN = 0xFED00000, LENGTH = 64K
}
SECTIONS
{
/* Bootloader向量表与代码 */
.boot_vector :
{
KEEP(*(.boot_vector))
} > FLASH_BOOT
.boot_text :
{
*(.boot_text)
*(.text*)
} > FLASH_BOOT
/* 应用程序向量表:必须4字节对齐 */
.app_vector 0x00010000 :
{
KEEP(*(.app_vector))
} > FLASH_APP
.app_text :
{
*(.app_text)
*(.text*)
} > FLASH_APP
.rodata :
{
*(.rodata*)
} > FLASH_APP
/* 跳转参数块:固定地址,用于Bootloader与App通信 */
.boot_param 0xFED00000 :
{
KEEP(*(.boot_param))
} > RAM
}
分区保护配置
通过芯片选项字节(Option Bytes)设置Flash访问保护,防止应用程序意外写入Bootloader区。RH850系列在Flash编程时通过FLASH_ACR寄存器配置写保护窗口:
/* flash_protect.c */
#include "rh850_flash.h"
void Flash_Protect_Init(void)
{
/* 设置Bootloader区为只读(禁止应用代码擦写) */
FLASH_ACR &= ~(0xFFFF0000u); /* 清除旧配置 */
FLASH_ACR |= (0x00000000u << 16); /* 保护0x00000000-0x0000FFFF */
/* 使能保护 */
FLASH_ACR |= (1u << 0); /* PRG保护使能 */
FLASH_ACR |= (1u << 1); /* ERS保护使能 */
/* 验证保护生效 */
if ((FLASH_ACR & 0x3u) != 0x3u)
{
/* 保护配置失败,进入错误处理 */
while(1);
}
}
编译与链接命令
# 编译Bootloader(使用上述链接脚本)
ghs_rh850 -c boot_main.c -o boot_main.o
ghs_rh850 -c flash_protect.c -o flash_protect.o
ghs_rh850 -o bootloader.elf boot_main.o flash_protect.o -T memory_layout.ld
# 编译应用程序(使用相同链接脚本,但只链接app部分)
ghs_rh850 -c app_main.c -o app_main.o
ghs_rh850 -o app.elf app_main.o -T memory_layout.ld
# 生成烧录文件
elfdump -e bootloader.elf -o bootloader.hex
elfdump -e app.elf -o app.hex
验证方法
- 地址映射检查:使用
elfdump -l bootloader.elf确认Bootloader的.text段起始地址为0x00000000,应用程序的.text段起始地址为0x00010000。 - 分区隔离验证:在应用程序中尝试调用
Flash_Write(0x00000000, data),应返回错误码或触发硬件异常,证明Bootloader区受到写保护。 - 跳转地址验证:在Bootloader中读取
0x00010000处的前4字节(应为应用程序栈顶指针),确认与app.elf的__stack符号值一致。
通过条件:上述地址检查全部匹配,且写保护操作被硬件拒绝,即判定内存分区规划正确落地。