加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

STM32 eCos 启动代码分析(一)系统复位

发布时间:2020-12-15 06:54:10 所属栏目:百科 来源:网络整理
导读:概述 最近接触了STM32,开始了解CortexM3系列ARM处理器上RTOS的移植和启动。 开始总是艰难的,CortexM3是arm7tdmi的升级产品,但实际上和之前的ARM7有着很大的区别。 首先,我们必须有支持CortexM3的编译器,因为CortexM3采用的是Thumb和Thumb2指令集,而不

概述

最近接触了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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读