STM32单片机Bootloader设计(上)

文 / Edward

   STM32的启动文件

STM32作为一款单片机,它的启动方式很简单,即当Boot配置了从内部Flash启动模式之后,一上电程序就会从0x8000000地址处开始执行文件,因此我们在使用Keil设置程序起始地址的时候,需要将这个Flash地址设置成0x8000000,只有将这个地址设置成0x8000000,生成的hex文件才可以被正常烧录到此地址,单片机上电之后才可以正常启动。而如果使用J-Flash工具烧写Hex文件时,这个地址会自动根据Hex文件解析出来。然而如果当你烧写二进制Bin文件时,还需要手动将单片机的起始地址制定出来,关于Hex文件和Bin文件的异同点,这个又是可以长篇大论一番了,我们下次特别写文章来讲。

图1 Keil设置起始地址和空间

STM32启动文件

;********************* (C) COPYRIGHT 2017 STMicroelectronics ********************;* File Name : startup_stm32l151xb.s;* Author : MCD Application Team;* Description : STM32L151XB Devices vector for MDK-ARM toolchain.;* This module performs:;* - Set the initial SP;* - Set the initial PC == Reset_Handler;* - Set the vector table entries with the exceptions ISR ;* address.;* - Configure the system clock;* - Branches to __main in the C library (which eventually;* calls main()).;* After Reset the Cortex-M3 processor is in Thread mode,;* priority is Privileged, and the Stack is set to Main.;********************************************************************************;*;* Copyright (c) 2017 STMicroelectronics. All rights reserved.;*;* This software component is licensed by ST under BSD 3-Clause license,;* the "License"; You may not use this file except in compliance with the;* License. You may obtain a copy of the License at:;* opensource.org/licenses/BSD-3-Clause;*;*******************************************************************************;* <<< Use Configuration Wizard in Context Menu >>>;; Amount of memory (in bytes) allocated for Stack; Tailor this value to your application needs; <h> Stack Configuration; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem SPACE Stack_Size__initial_sp

; <h> Heap Configuration; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>
Heap_Size EQU 0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3__heap_baseHeap_Mem SPACE Heap_Size__heap_limit
PRESERVE8 THUMB

; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler
; External Interrupts DCD WWDG_IRQHandler ; Window Watchdog DCD PVD_IRQHandler ; PVD through EXTI Line detect DCD TAMPER_STAMP_IRQHandler ; Tamper and Time Stamp DCD RTC_WKUP_IRQHandler ; RTC Wakeup DCD FLASH_IRQHandler ; FLASH DCD RCC_IRQHandler ; RCC DCD EXTI0_IRQHandler ; EXTI Line 0 DCD EXTI1_IRQHandler ; EXTI Line 1 DCD EXTI2_IRQHandler ; EXTI Line 2 DCD EXTI3_IRQHandler ; EXTI Line 3 DCD EXTI4_IRQHandler ; EXTI Line 4 DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 DCD ADC1_IRQHandler ; ADC1 DCD USB_HP_IRQHandler ; USB High Priority DCD USB_LP_IRQHandler ; USB Low Priority DCD DAC_IRQHandler ; DAC DCD COMP_IRQHandler ; COMP through EXTI Line DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 DCD 0 ; Reserved DCD TIM9_IRQHandler ; TIM9 DCD TIM10_IRQHandler ; TIM10 DCD TIM11_IRQHandler ; TIM11 DCD TIM2_IRQHandler ; TIM2 DCD TIM3_IRQHandler ; TIM3 DCD TIM4_IRQHandler ; TIM4 DCD I2C1_EV_IRQHandler ; I2C1 Event DCD I2C1_ER_IRQHandler ; I2C1 Error DCD I2C2_EV_IRQHandler ; I2C2 Event DCD I2C2_ER_IRQHandler ; I2C2 Error DCD SPI1_IRQHandler ; SPI1 DCD SPI2_IRQHandler ; SPI2 DCD USART1_IRQHandler ; USART1 DCD USART2_IRQHandler ; USART2 DCD USART3_IRQHandler ; USART3 DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line DCD USB_FS_WKUP_IRQHandler ; USB FS Wakeup from suspend DCD TIM6_IRQHandler ; TIM6 DCD TIM7_IRQHandler ; TIM7 __Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
; Reset handler routineReset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ENDPHardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] B . ENDPMemManage_Handler\ PROC EXPORT MemManage_Handler [WEAK] B . ENDPBusFault_Handler\ PROC EXPORT BusFault_Handler [WEAK] B . ENDPUsageFault_Handler\ PROC EXPORT UsageFault_Handler [WEAK] B . ENDPSVC_Handler PROC EXPORT SVC_Handler [WEAK] B . ENDPDebugMon_Handler\ PROC EXPORT DebugMon_Handler [WEAK] B . ENDPPendSV_Handler PROC EXPORT PendSV_Handler [WEAK] B . ENDPSysTick_Handler PROC EXPORT SysTick_Handler [WEAK] B . ENDP
Default_Handler PROC
EXPORT WWDG_IRQHandler [WEAK] EXPORT PVD_IRQHandler [WEAK] EXPORT TAMPER_STAMP_IRQHandler [WEAK] EXPORT RTC_WKUP_IRQHandler [WEAK] EXPORT FLASH_IRQHandler [WEAK] EXPORT RCC_IRQHandler [WEAK] EXPORT EXTI0_IRQHandler [WEAK] EXPORT EXTI1_IRQHandler [WEAK] EXPORT EXTI2_IRQHandler [WEAK] EXPORT EXTI3_IRQHandler [WEAK] EXPORT EXTI4_IRQHandler [WEAK] EXPORT DMA1_Channel1_IRQHandler [WEAK] EXPORT DMA1_Channel2_IRQHandler [WEAK] EXPORT DMA1_Channel3_IRQHandler [WEAK] EXPORT DMA1_Channel4_IRQHandler [WEAK] EXPORT DMA1_Channel5_IRQHandler [WEAK] EXPORT DMA1_Channel6_IRQHandler [WEAK] EXPORT DMA1_Channel7_IRQHandler [WEAK] EXPORT ADC1_IRQHandler [WEAK] EXPORT USB_HP_IRQHandler [WEAK] EXPORT USB_LP_IRQHandler [WEAK] EXPORT DAC_IRQHandler [WEAK] EXPORT COMP_IRQHandler [WEAK] EXPORT EXTI9_5_IRQHandler [WEAK] EXPORT TIM9_IRQHandler [WEAK] EXPORT TIM10_IRQHandler [WEAK] EXPORT TIM11_IRQHandler [WEAK] EXPORT TIM2_IRQHandler [WEAK] EXPORT TIM3_IRQHandler [WEAK] EXPORT TIM4_IRQHandler [WEAK] EXPORT I2C1_EV_IRQHandler [WEAK] EXPORT I2C1_ER_IRQHandler [WEAK] EXPORT I2C2_EV_IRQHandler [WEAK] EXPORT I2C2_ER_IRQHandler [WEAK] EXPORT SPI1_IRQHandler [WEAK] EXPORT SPI2_IRQHandler [WEAK] EXPORT USART1_IRQHandler [WEAK] EXPORT USART2_IRQHandler [WEAK] EXPORT USART3_IRQHandler [WEAK] EXPORT EXTI15_10_IRQHandler [WEAK] EXPORT RTC_Alarm_IRQHandler [WEAK] EXPORT USB_FS_WKUP_IRQHandler [WEAK] EXPORT TIM6_IRQHandler [WEAK] EXPORT TIM7_IRQHandler [WEAK]
WWDG_IRQHandlerPVD_IRQHandlerTAMPER_STAMP_IRQHandlerRTC_WKUP_IRQHandlerFLASH_IRQHandlerRCC_IRQHandlerEXTI0_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerDMA1_Channel1_IRQHandlerDMA1_Channel2_IRQHandlerDMA1_Channel3_IRQHandlerDMA1_Channel4_IRQHandlerDMA1_Channel5_IRQHandlerDMA1_Channel6_IRQHandlerDMA1_Channel7_IRQHandlerADC1_IRQHandlerUSB_HP_IRQHandlerUSB_LP_IRQHandlerDAC_IRQHandlerCOMP_IRQHandlerEXTI9_5_IRQHandlerTIM9_IRQHandlerTIM10_IRQHandlerTIM11_IRQHandlerTIM2_IRQHandlerTIM3_IRQHandlerTIM4_IRQHandlerI2C1_EV_IRQHandlerI2C1_ER_IRQHandlerI2C2_EV_IRQHandlerI2C2_ER_IRQHandlerSPI1_IRQHandlerSPI2_IRQHandlerUSART1_IRQHandlerUSART2_IRQHandlerUSART3_IRQHandlerEXTI15_10_IRQHandlerRTC_Alarm_IRQHandlerUSB_FS_WKUP_IRQHandlerTIM6_IRQHandlerTIM7_IRQHandler
B .
ENDP
ALIGN
;*******************************************************************************; User Stack and Heap initialization;******************************************************************************* IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap
LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR
ALIGN
ENDIF
END
;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****

首先让我们来看下STM32启动文件,当MCU上电复位之后,整个程序会跳转到以0x8000000为基址,偏移0的地址处,即还是0x8000000。但是STM32的0x8000000地址处存放的并不是整个芯片的第一句指令,而是整个芯片的堆栈初始化程序,如图2所示。

图2 0x8000000偏移0地址处的堆栈初始化程序指针

由于STM32的地址空间都是4字节对齐的,因此这个栈顶指针的存放空间为4字节,所以STM32复位之后跳转的地址应该是0x8000000基址偏移4个字节,即0x8000004。如同3所示。

图3 STM32复位跳转地址

图3中的程序非常浅显易懂,第136和137行,即将程序跳转到SystemInit处,这是个C语言函数,定义在“system_stm32l1xx.c”文件里,它的目的就是对中断向量表起始地址进行指定,也就是图2中的“__Vector”处。当然CM3内核和CM0内核关于SCB(系统控制块)的定义有些许差别,CM0不在本文讨论中,但是CM3和CM4的中断向量表映射机制还是很相似的。

图4 SystemInit函数映射中断向量表

图4中我们可以看到,SCB中关于Vector的地址是通过符号FLASH_BASE和VECT_TAB_OFFSET计算出来的,我们可以找到关于它们的定义,如图5所示。

图5 FLASH_BASE和VECT_TAB_OFFSET的定义

通过图5中的计算,正好可以得出整个中断向量表被映射到了0x8000000地址处。

    STM32的FLASH分配

前面的大段文章内容中,频繁提及了一个关键的数值,即0x8000000,那么这个0x8000000到底是怎么来的呢?这个数值并不是平白无故拍脑袋想出来的。之前我们就说过,ARM体系的存储器结构是其一大特色,而这个0x8000000正是整个STM32内置FLASH的起始地址。我们随便打开一份STM32的数据手册,在存储器章节里面就可以看到STM32全部的存储器定义。如图6所示。

图6 STM32内部FLASH的起始地址

   STM32的Bootloader思路

抛开所有的Bootloader高级功能来说,我们设计STM32 Bootloader的主要目的有两个,第一个为方便程序烧写和更新,第二个目前是从Bootloader程序中跳转(引导)用户的应用程序。这两个目的中,对于Bootloader来说程序跳转尤其重要,因为程序跳转成不成功将会严重影响整个用户程序的运行状态。因而,怎么跳,何时跳,跳到哪里,则是下篇文章的着重讨论部分。

前面一个FLASH烧写,可以根据自己的特殊要求来定制,只要严格安装HEX文件指定的地址和数据的关系,一般不会出错。

本文分析了STM32启动时比较重要的一些定义和函数跳转,下篇将会开始着手设计一个STM32 Bootloader。

(0)

相关推荐

  • 编写自己的启动代码

    编写自己的启动代码 上一篇扯了一些关于启动代码的应用方面的内容,列举了4种我自己遇到过的常见的启动代码应用,当然实际的应用肯定不止上一篇文章中提到的那几种,关键是大家懂了原理后根据实际的需求添加自己的 ...

  • 深度:单片机到底是如何软硬件结合的

    我们通过IO和串口的软件开发,已经体验了嵌入式软件开发.不知道大家有没有疑惑,为什么软件能控制硬件?反正当年我学习51的时候,有这个疑惑.今天我们就暂停软件开发,分析单片机到底是如何软硬件结合的.并通 ...

  • 解决STM32 Flash擦写操作导致USART接收丢数据

    问题: 该问题由客户提出,发生在STM32F103VDT6器件上.据客户工程师讲述,在其产品设计中使用了STM32片上Flash模拟了EEPROM的功能,用于存贮数据.在软件调试时,发现开启此功能,会 ...

  • STM32单片机Bootloader设计(下)

    之前一篇的<STM32单片机的Bootloader设计(上)>文章中,主要介绍了STM32的启动流程和内存主要空间的分配,这篇文章将在上一篇文章的基础上,来阐述一下STM32 Bootlo ...

  • STM32单片机学习板之|7PCB设计及展示

    重磅消息 亲爱的各位朋友,个人网站目前已经上线,目前主要有两大块:文章版块和论坛版本.这两个版块目前都能正常访问,快去注册发帖吧.说不定,以后你就是论坛的管理员呢 . 网址:www.picmcu.co ...

  • 学术︱基于STM32单片机测风系统的设计

    中国电工技术学会定于2016年7月10~11日在北京铁道大厦举办"2016第十一届中国电工装备创新与发展论坛",主题为"电工行业十三五规划研究与解读",并设&q ...

  • ​直线如诗,曲线如画~设计上也追求曲线美,视觉的转换!

    直线如诗,曲线如画. 设计上也追求曲线美,视觉的转换. 德信弘阳 · 湖畔云璟 From:成都因澈思明景观设计有限公司 以婉转小道组织动线与场景 通过空间开合.层级跌水与艺术装置 营造天光云影的意境观 ...

  • 克服搜题软件负面影响,需在作业设计上求突破

    王营 手机一拍,答案就来.近年来,拍照搜题App成为很多在线教育平台的引流工具."贴心"的用户体验也让不少学生对其高度依赖.随之而来的,还有持续升温的争议:此类App到底是帮助孩子 ...

  • 美国都是在顶层设计上,布局上玩阴谋诡计,执行上合同上很讲诚信,是因为要保证布局

    癌症行业打着创新的旗号,做消费者承担后果与研究费用的时代,已经几十年了,是老规矩,也是一边数钱赚钱养各种活动费,一边实验,一边不断淘汰对象,不断学习新技术,这明明是以犯养吸. 以合法犯罪的创新技术养吸 ...

  • 用2个按键控4路led解决方案stm32单片机89c51

    用2个按键控4路led解决方案stm32单片机89c51

  • 秦汉与唐宋皇宫相比较,为何设计上规制越来越多,布局越来越紧凑

    建筑艺术,一直被视为是人类文化艺术的集大成者,不仅代表着一个时代的文化水平,也体现着当时的科技水平. 而纵观中国古代建筑艺术的发展,历代皇宫无疑是其巅峰之作,充满着当时的时代特色和印记.从秦始皇建立大 ...

  • 智能手机PCB设计上如何改善散热?

    本文导读:从智能手机小米10案例解读散热设计架构,从而引出如何从PCB设计上改善散热的文章主旨. 小米10 智能手机热设计架构 小米10智能手机的热设计核心理念可以概况为"均温和高效热传导& ...