STM32
直播中

张静

8年用户 1497经验值
私信 关注
[问答]

startup_stm32f2xx.s文件的启动流程是怎样的?

startup_STM32f2xx.s文件的启动流程是怎样的?

回帖(1)

刘洋

2021-11-29 10:09:05
项目硬件验证环境: STM32F205
项目码云git地址: https://gitee.com/liwandong/ShareRTOS
通常情况下可以直接使用ST公司提供的startup_stm32f2xx.s 这个文件进行mcu启动的引导,不是很喜欢汇编,所以将其启动过程改为使用C语言来实现,首先分析一下startup_stm32f2xx.s这个文件的启动流程大概如下所示:
          

其中大体的流程是系统上电之后会获取中断向量表,然后运行Rest_Handle函数,然后运行初始化时钟接口,最后在调用main函数,使用mdk等IDE时数据拷贝的工作被隐藏起来,可以通过查看map文件来进行分析,基于以上流程,写我们自己的启动文件过程如下:文件路径在mcudevice/src/stm32f205_startup.c


建立中断向量表,代码如下:
__attribute__ ((section("vectors"))) void (* const VectorArray[])(void)={
    //内核中断
    (void*)STACK_TOP,
    Reset_Handler,
    NMI_Handler,
    HardFault_Handler,
    MemManage_Handler,
    BusFault_Handler,
    UsageFault_Handler,
    0,  
    0,  
    0,  
    0,  
    SVC_Handler,
    DebugMon_Handler,
    0,  
    PendSV_Handler,
    SysTick_Handler
    //外设中断
};


这里使用了两个知识点,一个是__attribute__ ((section(“vectors”))) 将部分内容定义为一个段,另一个使用函数指针数组包含多个函数,使其地址按照定义顺序排列。


拷贝数据和数据初始化的函数
void stm32_copydata(unsigned int *form,unsigned int *section_begin,unsigned int *section_end)
{
    unsigned int *p;
    p = section_begin;
    while(p     {
        *p++ = *form++;
    }
}


void stm32_bssinit(unsigned int *startbss,unsigned int *endbss)
{
  unsigned int *p;
  p = startbss;
  while(p   {
    *p++ = 0;
  }


有了基本的这些函数之后,就在Reset_Handler 函数中copy bbs,ro,rw数据,初始化时钟,调用main函数
void Reset_Handler(void){
    stm32_copydata(&_sidata,&_sdata,&_edata);
    stm32_bssinit(&__bss_start__,&__bss_end__);
    SystemInit();
    main();
}


数据段的来自链接脚本文件,脚本文件的情况如下:
/*
指定函数入口
*/
ENTRY(Reset_Handler)
/*定义堆和栈大小*/
_Min_Heap_Size =  0x0000;
_Min_Stack_Size  = 0x10000;


/*flash和ram的分布情况*/
MEMORY
{
    FLASH (rx):     ORIGIN = 0x08000000, LENGTH = 1024K
    RAM   (rwx):    ORIGIN = 0x20000000, LENGTH = 128K
}


SECTIONS
{
    /*向量表放在最头部*/
    .vectors :
    {
        . = ALIGN(4);
        KEEP(*(vectors))
        . = ALIGN(4);
    } > FLASH
    /*代码段*/
    .text :
    {
        . = ALIGN(4);
        *(.text);
        *(.text*);
        *(.rodata);
        *(.rodata*);
        *(.glue_7)
        *(.glue_7t)
        *(.eh_frame)
        . = ALIGN(4);
        _etext = .; /*代码段结束*/
    }>FLASH


    /*数据段*/
    _sidata = .;
    .data :  AT ( _sidata )
    {
        . = ALIGN(4);
        _sdata  = .;
        *(.data);
        *(.data*);
        . = ALIGN(4);
        _edata = .;
    }>RAM
    . = ALIGN(4);
    /*bss段*/
    .bss :
    {
        _***ss = .;
        __bss_start__ = _***ss;
        *(.bss);
        *(.bss*);
        *(COMMON);
        . = ALIGN(4);
        _ebss = .;
        __bss_end__ = _ebss;
    }>RAM
    /*导出符号可以在c中使用*/
    PROVIDE ( end = _ebss );
    PROVIDE ( _end = _ebss );
    ._user_heap_stack :
    {
        . = ALIGN(4);
        . = . + _Min_Heap_Size;
        . = . + _Min_Stack_Size;
        . = ALIGN(4);
    } >RAM
     /DISCARD/ :
    {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
    }
}


经过上面的步骤之后,stm32就可以被启动起来。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分