打印
[STM32F1]

STM32的启动流程

[复制链接]
4292|31
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
想请教一下,关于STM32的启动流程。

STM32有一个启动文件startup_stm32f10x.s,这个文件烧写到flash后是存放在哪里,是何时被执行的?
按我的理解,根据boot引脚的设置(比如设为flash启动),上电后先从flash的0x08000000地址取得MSP栈顶地址,从0x08000004地址取得复位向量的地址赋给PC,然后执行reset_handler中断服务程序(其中执行SystemInit设置系统时钟,执行_main,最终跳转到c预研的main函数)。

如果按照上面这个流程,虽然reset_handler是在startup.s启动文件中定义的,但是整个完整的startup.s是何时被执行的??
沙发
51xlf| | 2018-7-13 17:09 | 只看该作者
https://blog.csdn.net/tianshi_1988/article/details/51084052

使用特权

评论回复
板凳
i1mcu| | 2018-7-13 17:10 | 只看该作者

使用特权

评论回复
地板
pmp| | 2018-7-13 17:12 | 只看该作者
有3种情况:

    1、 通过boot引脚设置可以将中断向量表定位于SRAM区,即起始地址为0x2000000,同时复位后PC指针位于0x2000000处;

    2、 通过boot引脚设置可以将中断向量表定位于FLASH区,即起始地址为0x8000000,同时复位后PC指针位于0x8000000处;

    3、 通过boot引脚设置可以将中断向量表定位于内置Bootloader区,本文不对这种情况做论述

使用特权

评论回复
5
mmbs| | 2018-7-13 17:12 | 只看该作者
这个好像见过他们分享过这个的

使用特权

评论回复
6
1988020566| | 2018-7-13 17:13 | 只看该作者
楼主是要修改BootLoader吗?

使用特权

评论回复
7
lzbf| | 2018-7-13 17:13 | 只看该作者
flash不是有设置的地址吗

使用特权

评论回复
8
houjiakai| | 2018-7-13 17:14 | 只看该作者
startup.s是开启就执行的文件吧。

使用特权

评论回复
9
youtome| | 2018-7-13 17:14 | 只看该作者
Startup.s文件是系统的启动文件

使用特权

评论回复
10
cemaj| | 2018-7-13 17:14 | 只看该作者
将该程序段放在执行文件的起始位置

使用特权

评论回复
11
lihui567| | 2018-7-13 17:15 | 只看该作者
bootloader修改比较麻烦的,需要对flash进行操作

使用特权

评论回复
12
lihui567| | 2018-7-13 17:15 | 只看该作者
bootloader修改比较麻烦的,需要对flash进行操作

使用特权

评论回复
13
updownq| | 2018-7-13 17:15 | 只看该作者
这个还真没有分析过,不过网上有很多的资料。

使用特权

评论回复
14
cemaj| | 2018-7-13 17:15 | 只看该作者
在51汇编中,使用ORG 0000H语句,也可达成该目的。

使用特权

评论回复
15
51xlf| | 2018-7-13 17:15 | 只看该作者
STM32启动文件详细解析 这个写的不错。

使用特权

评论回复
16
youtome| | 2018-7-13 17:15 | 只看该作者
主要包括堆和栈的初始化配置、中断向量表的配置以及将程序引导到main( )函数等

使用特权

评论回复
17
i1mcu| | 2018-7-13 17:15 | 只看该作者
https://blog.csdn.net/wheat_in_winner/article/details/53583462

使用特权

评论回复
18
houjiakai| | 2018-7-13 17:15 | 只看该作者
执行完startup.s,后面才执行初始化的代码和main函数。

使用特权

评论回复
19
pmp| | 2018-7-13 17:16 | 只看该作者
下面就从ST的启动文件说起,由于库中的startup_stm32f10x_md.s与编译环境有关,所以针对的是库中的

STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\TrueSTUDIO路径下的文件进行分析。

system_stm32f10x.c

    SystemInit():在"startup_stm32f10x_xx.s"文件中被调用,功能是设置系统时钟(包括时钟源,PLL系数,AHB/APBx的预分频系数还有 flash的设定),这个函数会在系统复位之后首先被执行。文件中默认的一些设置:允许HSE(外部时钟),FLASH(允许预取缓冲区,设置2个等待周 期),PLL系数为9,开启PLL并选择PLL输出作为时钟源(SYSCLK),后续设置SYSCLK = HCLK = APB2 = 72MHz,APB1 = HCLK/2 = 36MHz,HCLK即AHB的时钟。

    SystemCoreClockUpdate():在系统时钟HCLK变化的时候调用,以更新一个全局变量SystemCoreClock,这个变量可以为应用程序使用,必须保证正确。默认不调用这个函数,因为SystemCoreClock默认被设置为设定的频率了(72MHz)

    另外,下面这种设置寄存器的方法值得借鉴,先用位名清除相应的位,再进行设置,例如:

#define  RCC_CFGR_PLLSRC                     ((uint32_t)0x00010000)        /*!< PLL entry clock source */

#define  RCC_CFGR_PLLXTPRE                   ((uint32_t)0x00020000)        /*!< HSE divider for PLL entry */

#define  RCC_CFGR_PLLMULL                    ((uint32_t)0x003C0000)        /*!< PLLMUL[3:0] bits (PLL multiplication factor) */

#define  RCC_CFGR_PLLSRC_HSE                ((uint32_t)0x00010000)        /*!< HSE clock selected as PLL entry clock source */

#define  RCC_CFGR_PLLMULL9                  ((uint32_t)0x001C0000)        /*!< PLL input clock*9 */

/*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */   

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));

RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

    startup_stm32f10x_md.s:(针对F103RBT6为中容量的产品)

    这个文件里面首先定义了复位中断(复位入口矢量被硬件固定在地址0x0000_0004)的处理函数:Reset_Handler,它的作用就是将保存于flash中的初始化数据复制到sram中,调用上面说到的SystemInit来初始化时钟,接着跳转到main执行。

    接着定义了Default_Handler, 这个是作为其他所有中断的默认处理函数,作用就是死循环,所以你假如开启了某个中断,请按照这里面的中断函数名给它写中断处理函数,例如串口中断处理函数名是 USART1_IRQHandler,你开了串口中断,如果不重写USART1_IRQHandler,就默认执行Default_Handler,死循环了。而如果你有重写,那么中断向量表中的处理函数的地址就会更新为你自己写的那个函数的地址了。为什么会这样呢?因为此文件的末尾用了类似这样的语句:

   .weak    USART1_IRQHandler

   .thumb_set USART1_IRQHandler,Default_Handler

它给中断处理函数提供了弱(weak)别名(Default_Handler),如果不重写,中断了默认执行Default_Handler,如果重写了,因为是弱别名,所以会被你写的同名函数覆盖。

最后定义了一个中断向量表的段(.section    .isr_vector,"a",%progbits),这个表将会放置在0x0000 0000那里,第二个字(0x0000 0004)是复位向量,复位之后从这地址所指的函数执行。

那么,如何保证.isr_vector这个段将放在flash的最开始(0x08000000)呢?这就需要链接脚本了,即我们用的那个stm32_flash.ld文件了,查看一下就知道了,里面先定义了堆栈的地址:

_estack

/* Highest address of the user mode stack */

_estack = 0x20005000;    /* end of 20K RAM */

接着定义了堆和栈的大小:

/* Generate a link error if heap and stack don't fit into RAM */

_Min_Heap_Size = 0;      /* required amount of heap  */

_Min_Stack_Size = 0x100; /* required amount of stack */

接着声明了各个内存的区域(定义了几个代表某个线性空间的名字,如下面的FLASH):

/* Specify the memory areas */

MEMORY

{

FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 128K  

RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K  

MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K }

接着下面再介绍上面这三个名字里面都放了什么东西,首先是FLASH的:

/* Define output sections */

SECTIONS

{

/* The startup code goes first into FLASH */

.isr_vector :

{

   . = ALIGN(4);    KEEP(*(.isr_vector)) /* Startup code */

   . = ALIGN(4);  } >FLASH

/* The program code and other data goes into FLASH */

使用特权

评论回复
20
lzbf| | 2018-7-13 17:16 | 只看该作者
就是在设置的地址上。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

27

帖子

0

粉丝