一、问题
单片机经常存在这么一种结构:BOOT+配置+APP。BOOT与配置一次性开发完,更改的概率较低,但APP一直处于维护过程中。
APP维护经常使用仿真器进行DEBUG,大部分情况下是编译在首地址0x8000000并且运行,这里编译需要更改两个地方:
1.IDE指定的FLASH首地址,或.sct文件:
LR_IROM1 0x08020000 0x00040000 { ; 定义一个加载时域,域基址:0x08020000,域大
; 小为 0x00040000,对应实际 Flash 的大小
ER_IROM1 0x08000000 0x00040000 { ; 定义一个运行时域,第一个运行时域必须和加载
; 时域起始地址相同,否则库不能加载到该时域的
; 错误,其域大小一般也和加载时域大小相同
*.o (RESET, +First) ; 将 RESET 段最先加载到本域的起始地址外,即
; RESET 的起始地址为 0,RESET 存储的是向量表
*(InRoot$$Section)
.ANY (+RO) ; 加载所有匹配目标文件的只读属性数据,包含:
; Code、RW-Code、RO-Data。
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00040000 { ; 定义一个运行时域,域基址:0x20000000,域大
; 小为 0x00040000,对应实际 RAM 大小
* (+RW +ZI) ; 加载所有区配目标文件的 RW-Data、ZI-Data
; 这里也可以用.ANY 替代*号
}
ARM_LIB_HEP 0x20040000 EMPTY 0x70000 { ; 定义一个运行时域,域基址:0x20040000,域大小为0x70000,预留给启动代码里的堆用
}
ARM_LIB_STACK 0x200BFFC0 EMPTY -0x BFFC0 { ; 定义一个运行时域,域基址:0x200BFFC0,域大小为0x BFFC0,预留给启动代码里的栈用
;启动代码汇编使用__
;IMPORT |Image$$ARM_LIB_STACK$$ZI$$Linit|
;__Vector DCD |Image$$ARM_LIB_STACK$$ZI$$Linit| ;Top of Stack
}
BOOT_INFO 0x200BFFC0 EMPTY 0x10 { ; 定义一个运行时域,域基址:0x200BFFC0,域大小为0 x10,预留引导信息用
;C/C++使用:
;extern unsigned int Image$$BOOT_INFO$$ZI$$Base;//起始
;extern unsigned int Image$$BOOT_INFO$$ZI$$Limit; //结束
;#define BOOT_INFO_BASE_ADDR ((unsigned int)(&Image$$BOOT_INFO$$ZI$$Base))//0x200BFFC0
;#define BOOT_INFO_END_ADDR ((unsigned int)(&Image$$BOOT_INFO$$ZI$$Limit))//0x200BFFD0
}
MCU_SELF_TEST_RESULT 0x200BFFD0 EMPTY 0x10 { ; 定义一个运行时域,域基址:0x200BFFD0,域大小为0 x10,预留自检信息用
}
}
2.程序运行起来指定的中断向量表由0x8020000改为0x8000000:
#define VECTORTABLE_OFFSET 0x20000
Set_Vector_Tabel(VECTORTABLE_OFFSET);//赋值给寄存器0xE000ED08
//FreeRTOS中没有亚优先级处理,必须在第一个任务前配置为Group4
Set_Nvic_Priority_Group_Config(NVIC_PriorityGroup_4);
因此,为了避免每次仿真器DEUBG都要修改第2个步骤的代码,想办法SCT的地址与代码关联起来。
二、问题解决:
定义中断向量地址:
IMPORT |Image$$ARM_LIB_STACK$$ZI$$Linit|
__Vector DCD |Image$$ARM_LIB_STACK$$ZI$$Linit| ;Top of Stack
在启动代码的初始化与进入MAIN之间增加几句代码:
;重映射中断向量
LDR R0, =0xE000ED08
LDR R1, = __Vector
STR R1, [R0];从栈的首地址取出中断向量地址,写入寄存器0xE000ED08