概述
最近接触了STM32,开始了解CortexM3系列ARM处理器上RTOS的移植和启动。
开始总是艰难的,CortexM3是arm7tdmi的升级产品,但实际上和之前的ARM7有着很大的区别。
首先,我们必须有支持CortexM3的编译器,因为CortexM3采用的是Thumb和Thumb2指令集,而不是ARM指令集。
好在eCos 3.0以后ecoscentric提供的toolchain已经支持了CortexM3虽然可能没有采用Thumb2指令集,但是编译和运行eCos是没问题的。
因为CortexM3的中断和异常的特殊性决定了它上面运行的启动代码的不同,这也是为什么我们看到ecos把cortexm的体系结构和之前
的ARM平行放置了。
我们首先看看eCos的第一条语句是怎么运行的,这样我们就比较容易理解后面硬件初始化和中断入口表的代码了。
纵观CortexM启动代码
要了解eCos的CortexM启动代码,需要理清下面几个文件的编译和链接关系。
packages/hal/cortexm/arch/current/src/vector.S
packages/hal/cortexm/arch/current/src/hal_misc.c
packages/hal/cortexm/stm32/stm3210e_eval/current/include/pkgconf/mlt_cortexm_stm3210e_eval_rom.ldi
packages/hal/cortexm/arch/current/src/vector.S
//==========================================================================
.syntaxunified
.thumb
//==========================================================================
//Initial exception vector table
//
//This only contains the stack and entry point for reset. The table
//to be used at runtime is constructed by code in hal_reset_vsr().
.section ".vectors","ax"
.global hal_vsr_table
hal_vsr_table_init:
.long??? hal_startup_stack // 0 Reset stack
.long??? hal_reset_vsr // 1 Reset entry
这里我们可以看到,hal_vsr_table_init开始的预留了8个byte,我们可以猜想这个就是系统的启动部分。
但是,要想了解eCos的启动代码,我们必须知道hal_startup_stack和hal_reset_vsr来源于何处如何设定。
packages/hal/cortexm/stm32/stm3210e_eval/current/include/pkgconf/mlt_cortexm_stm3210e_eval_rom.ldi
//eCos memory layout
#include<pkgconf/hal.h>
#include<cyg/infra/cyg_type.inc>
MEMORY
{
sram : ORIGIN = 0x20000000,LENGTH =0x00010000-CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
flash: ORIGIN = 0x08000000,LENGTH = 0x00080000
rom : ORIGIN = 0x64000000,LENGTH = 0x01000000
ram : ORIGIN = 0x68000000,LENGTH = 0x00100000
}
SECTIONS
SECTIONS_BEGIN
SECTION_rom_vectors(flash,0x08000000,LMA_EQ_VMA)
SECTION_RELOCS(flash,ALIGN (0x8),monospace">SECTION_text(flash,monospace">SECTION_fini(flash,monospace">SECTION_rodata(flash,monospace">SECTION_rodata1(flash,monospace">SECTION_fixup(flash,monospace">SECTION_gcc_except_table(flash,monospace">SECTION_eh_frame(flash,monospace">SECTION_got(flash,monospace">SECTION_sram(sram,0x20000400,FOLLOWING (.got))
SECTION_data(ram,0x68000000,FOLLOWING (.sram))
SECTION_bss(ram,monospace">CYG_LABEL_DEFN(__heap1)= ALIGN (0x8);
SECTIONS_END
hal_vsr_table= 0x20000000;
hal_virtual_vector_table= hal_vsr_table + 128*4;
hal_startup_stack= 0x20000000 + 1024*64;
这里我们可以看到,这个链接管理脚本设置了hal_startup_stack的大小。
观察map文件
我们通过arm-eabi-nm这样的工具把elf文件生成几个map文件看一看这些symbol的具体位置。
hal_reset_vsr

hal_startup_stack

hal_reset_vsr是系统初始化的一个重要函数
hal_reset_vsr还调用了stm32变体层的初始化函数hal_system_init。

分析一下生成的binary文件
以ROM类型的二进制文件为例,如果我们把STM32的芯片设定为从内部的ROM启动。
他会默认的执行0x0000000也就是0x0800000,我们通过Linux的ghex来看这个二进制文件的前8个字节。
我们会看到
0x20010000
0x08003085
而之前我们通过map文件查到的
0x20010000? hal_startup_stack
0x08003084? hal_reset_vsr


那么为什么这两个地址会差1呢,如果我们能合理的解释。那么我们基本上就清晰的了解了CortexM的启动部分了。
查阅CorteM3权威指南
查阅以后我们看到有这样的解释,
在离开复位状态后,CM3 做的第一件事就是读取下列两个 32 位整数的值:
-从地址 0x0000,0000 处取出 MSP 的初始值。
-从地址 0x0000,0004 处取出 PC 的初始值——这个值是复位向量,LSB 必须是 1。然后从这个值所对应的地址处取指。

因为 CM3 使用的是向下生长的满栈,所以 MSP 的初始值必须是堆栈内存的末地址加 1。
?
举例来说,如果你的堆栈区域在 0x20007C00
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!