Today I want to introduce the startup code of STM32. I am using the medium-capacity STM32f103c8t6 here. The corresponding startup file is startup_stm32f10x_md.s. My startup file version is V3.6.2
Without further ado, here are the source codes I annotated:
/**
******************************************************************************
* @file startup_stm32f10x_md.s
* @author MCD Application Team
* @version V3.6.2
* @date 28-February-2013
* @brief STM32F10x Medium Density Devices vector table for RIDE7 toolchain.
* This module performs:
* - Set the initial SP - Set the initial SP register value
* - Set the initial PC == Reset_Handler, - Set the initial PC register value == Reset_Handler
* - Set the vector table entries with the exceptions ISR address
* - Configure the clock system
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M3 processor is in Thread mode, the priority is privileged and the top of the stack is set to the main function.
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* @attention
*
*
© COPYRIGHT 2013 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
.syntax unified ; indicates the use of unified assembly language syntax
.cpu cortex-m3; MCU is CM3
.fpu softvfp
.thumb ; instruction set
.global g_pfnVectors; global makes g_pfnVectors available to other target files
.global Default_Handler
/* start address for the initialization values of the .data section. Initialize the starting address of the .data block. This address is defined in the link script.
defined in linker script */
.word _carrying
/* start address for the .data section. defined in linker script. The starting address of the .data block is defined in the linker script*/
.word _sdata
/* end address for the .data section. defined in linker script. The end address of the .data block. This address is defined in the linker script*/
.word _edata
/* start address for the .bss section. defined in linker script. The starting address of the .bss block is defined in the linker script*/
.word _sbss
/* end address for the .bss section. defined in linker script. The end address of the .bss block. This address is defined in the linker script*/
.word _ebss
.equ BootRAM, 0xF108F85F /*This is similar to the macro definition in C, that is, BootRAM = 0xF108F85F, not involved in compilation*/
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM Copy the initialized data segment from flash to SRAM*/
movs r1, #0 ; assign the immediate value 0 to the r1 register
b LoopCopyDataInit ; The program transfers to LoopCopyDataInit
CopyDataInit: ;Copy the code between sdata and edata from FLASH to SRAM
ldr r3, =_sidata ; load _sidata from memory into register r3
ldr r3, [r3, r1] ; read a word (32 bits) from address r3+r1 into r3
str r3, [r0, r1] ; Store the value of register r3 in the memory at address r0+r1
adds r1, r1, #4 ;r1 = r1 + 4
LoopCopyDataInit:
ldr r0, =_sdata ; load _sidata from memory into register r0
ldr r3, =_edata ; load _edata from memory into register r3
adds r2, r0, r1 ;r2=r0+r1
cmp r2, r3; Calculate r2 - r3, if it is less than 0, the flag is 0, otherwise it is 1
bcc CopyDataInit ; If the flag is 0 (no borrow), that is, r2 ldr r2, =_sbss ; load _sbss from memory into register r2 b LoopFillZerobss ; jump to LoopFillZerobss unconditionally /* Zero fill the bss segment. */ FillZerobss: movs r3, #0 ; store the immediate value 0 into register r3 str r3, [r2], #4; store the value of register r3 to the address of register r2, r2 = r2 + 4 LoopFillZerobss: ldr r3, = _ebss ; load _ebss from memory into register r3 cmp r2, r3 ; compare r2, r3, and then update the flag bit bcc FillZerobss ; If the flag is 0 (no borrow), jump to FillZerobss /* Call the clock system intitialization function.*/ /* bl SystemInit */ /* Call the application's entry point.*/ bl main ; transfer to the beginning of the main function bx lr ; transfer to address lr .size Reset_Handler, .-Reset_Handler; equivalent to mov pc lr lr is register r14 /** * @brief This is the code that gets called when the processor receives an * unexpected interrupt. This simply enters an infinite loop, preserving * the system state for examination by a debugger. * @param None * @retval None */ .section .text.Default_Handler,"ax",%progbits Default_Handler: Infinite_Loop: b Infinite_Loop ; Unconditional jump to Infinite_Loop .size Default_Handler, .-Default_Handler /****************************************************************************** * * The minimal vector table for a Cortex M3. Note that the proper constructs Cortex M3's minimal vector table * must be placed on this to ensure that it ends up at physical address * 0x0000.0000. * ******************************************************************************/ .section .isr_vector,"a",%progbits ; define the data segment of the interrupt vector table .type g_pfnVectors, %object .size g_pfnVectors, .-g_pfnVectors g_pfnVectors: .word _estack ; Place a word value at the current position, this value is _estack; the same applies to the following .word Reset_Handler; This block of code means that g_pfnVectors is used as the initial address, and then .word NMI_Handler ; write corresponding data in word units .word HardFault_Handler .word MemManage_Handler .word BusFault_Handler .word UsageFault_Handler .word 0 .word 0 .word 0 .word 0 .word SVC_Handler .word DebugMon_Handler .word 0 .word PendSV_Handler .word SysTick_Handler .word WWDG_IRQHandler .word PVD_IRQHandler .word TAMPER_IRQHandler .word RTC_IRQHandler .word FLASH_IRQHandler .word RCC_IRQHandler .word EXTI0_IRQHandler .word EXTI1_IRQHandler .word EXTI2_IRQHandler .word EXTI3_IRQHandler .word EXTI4_IRQHandler .word DMA1_Channel1_IRQHandler .word DMA1_Channel2_IRQHandler .word DMA1_Channel3_IRQHandler .word DMA1_Channel4_IRQHandler .word DMA1_Channel5_IRQHandler .word DMA1_Channel6_IRQHandler .word DMA1_Channel7_IRQHandler .word ADC1_2_IRQHandler .word USB_HP_CAN1_TX_IRQHandler .word USB_LP_CAN1_RX0_IRQHandler .word CAN1_RX1_IRQHandler .word CAN1_SCE_IRQHandler .word EXTI9_5_IRQHandler .word TIM1_BRK_IRQHandler .word TIM1_UP_IRQHandler .word TIM1_TRG_COM_IRQHandler .word TIM1_CC_IRQHandler .word TIM2_IRQHandler .word TIM3_IRQHandler .word TIM4_IRQHandler .word I2C1_EV_IRQHandler .word I2C1_ER_IRQHandler .word I2C2_EV_IRQHandler .word I2C2_ER_IRQHandler .word SPI1_IRQHandler .word SPI2_IRQHandler .word USART1_IRQHandler .word USART2_IRQHandler .word USART3_IRQHandler .word EXTI15_10_IRQHandler .word RTCAlarm_IRQHandler .word USBWakeUp_IRQHandler .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word BootRAM /* @0x108. This is for boot in RAM mode for STM32F10 series medium capacity series devices in RAM mode STM32F10x Medium Density devices. */ /******************************************************************************* * * Provide weak aliases for each Exception handler to the Default_Handler. * As they are weak aliases, any function with the same name will override * this definition. * *******************************************************************************/ .weak NMI_Handler ; define a weak alias NMI_Handler .thumb_set NMI_Handler,Default_Handler; If this weak alias is not overridden, the default Default_Handler is executed by default, otherwise the overridden NMI_Handler is executed .weak HardFault_Handler .thumb_set HardFault_Handler,Default_Handler .weak MemManage_Handler .thumb_set MemManage_Handler,Default_Handler .weak BusFault_Handler .thumb_set BusFault_Handler,Default_Handler .weak UsageFault_Handler .thumb_set UsageFault_Handler,Default_Handler .weak SVC_Handler .thumb_set SVC_Handler,Default_Handler .weak DebugMon_Handler .thumb_set DebugMon_Handler,Default_Handler .weak PendSV_Handler .thumb_set PendSV_Handler,Default_Handler .weak SysTick_Handler .thumb_set SysTick_Handler,Default_Handler .weak WWDG_IRQHandler .thumb_set WWDG_IRQHandler,Default_Handler .weak PVD_IRQHandler .thumb_set PVD_IRQHandler,Default_Handler .weak TAMPER_IRQHandler .thumb_set TAMPER_IRQHandler,Default_Handler .weak RTC_IRQHandler .thumb_set RTC_IRQHandler,Default_Handler .weak FLASH_IRQHandler .thumb_set FLASH_IRQHandler,Default_Handler .weak RCC_IRQHandler .thumb_set RCC_IRQHandler,Default_Handler .weak EXTI0_IRQHandler .thumb_set EXTI0_IRQHandler,Default_Handler .weak EXTI1_IRQHandler .thumb_set EXTI1_IRQHandler,Default_Handler .weak EXTI2_IRQHandler .thumb_set EXTI2_IRQHandler,Default_Handler .weak EXTI3_IRQHandler .thumb_set EXTI3_IRQHandler,Default_Handler .weak EXTI4_IRQHandler .thumb_set EXTI4_IRQHandler,Default_Handler .weak DMA1_Channel1_IRQHandler .thumb_set DMA1_Channel1_IRQHandler,Default_Handler .weak DMA1_Channel2_IRQHandler .thumb_set DMA1_Channel2_IRQHandler,Default_Handler .weak DMA1_Channel3_IRQHandler .thumb_set DMA1_Channel3_IRQHandler,Default_Handler .weak DMA1_Channel4_IRQHandler .thumb_set DMA1_Channel4_IRQHandler,Default_Handler .weak DMA1_Channel5_IRQHandler .thumb_set DMA1_Channel5_IRQHandler,Default_Handler .weak DMA1_Channel6_IRQHandler .thumb_set DMA1_Channel6_IRQHandler,Default_Handler .weak DMA1_Channel7_IRQHandler .thumb_set DMA1_Channel7_IRQHandler,Default_Handler .weak ADC1_2_IRQHandler .thumb_set ADC1_2_IRQHandler,Default_Handler .weak USB_HP_CAN1_TX_IRQHandler .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler .weak USB_LP_CAN1_RX0_IRQHandler .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler .weak CAN1_RX1_IRQHandler .thumb_set CAN1_RX1_IRQHandler,Default_Handler .weak CAN1_SCE_IRQHandler .thumb_set CAN1_SCE_IRQHandler,Default_Handler .weak EXTI9_5_IRQHandler .thumb_set EXTI9_5_IRQHandler,Default_Handler .weak TIM1_BRK_IRQHandler .thumb_set TIM1_BRK_IRQHandler,Default_Handler .weak TIM1_UP_IRQHandler .thumb_set TIM1_UP_IRQHandler,Default_Handler .weak TIM1_TRG_COM_IRQHandler .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler .weak TIM1_CC_IRQHandler .thumb_set TIM1_CC_IRQHandler,Default_Handler .weak TIM2_IRQHandler .thumb_set TIM2_IRQHandler,Default_Handler .weak TIM3_IRQHandler .thumb_set TIM3_IRQHandler,Default_Handler .weak TIM4_IRQHandler .thumb_set TIM4_IRQHandler,Default_Handler .weak I2C1_EV_IRQHandler .thumb_set I2C1_EV_IRQHandler,Default_Handler .weak I2C1_ER_IRQHandler .thumb_set I2C1_ER_IRQHandler,Default_Handler .weak I2C2_EV_IRQHandler .thumb_set I2C2_EV_IRQHandler,Default_Handler .weak I2C2_ER_IRQHandler .thumb_set I2C2_ER_IRQHandler,Default_Handler .weak SPI1_IRQHandler .thumb_set SPI1_IRQHandler,Default_Handler .weak SPI2_IRQHandler .thumb_set SPI2_IRQHandler,Default_Handler .weak USART1_IRQHandler .thumb_set USART1_IRQHandler,Default_Handler .weak USART2_IRQHandler .thumb_set USART2_IRQHandler,Default_Handler .weak USART3_IRQHandler .thumb_set USART3_IRQHandler,Default_Handler .weak EXTI15_10_IRQHandler .thumb_set EXTI15_10_IRQHandler,Default_Handler .weak RTCAlarm_IRQHandler .thumb_set RTCAlarm_IRQHandler,Default_Handler .weak USBWakeUp_IRQHandler .thumb_set USBWakeUp_IRQHandler,Default_Handler /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ If there are any inaccuracies in the comments, I hope you can point them out to me. Thank you~~ Here, taking the STM32 program running process as the axis, the process of microcontroller startup is introduced one by one. Before powering on the microcontroller, first set the initial position for program startup by connecting high and low levels to BOOT0 and BOOT1. There are three positions for STM32 program startup: 1:Main Flash memory It is the built-in Flash of STM32. Generally, when we use JTAG or SWD mode to download the program, it is downloaded to this, and the program is started directly from here after restart. 2:System memory Boot from system memory. The program functions started in this mode are set by the manufacturer. Generally speaking, this boot mode is rarely used. 3:Embedded Memory Built-in SRAM. Since it is SRAM, it naturally has no program storage capability. This mode is generally used for program debugging. The first method is the most commonly used among these three methods. The following is an introduction to the first startup method as an example: When the chip is restarted, the value of the BOOT pin will be latched at the fourth rising edge of SYSCLK. Then enter the startup file, the specific startup file is startup_stm32f10x_md.s. First, there is a Reset_Handler in the startup file. This assembly function has two functions: a. Copy the program code in FLASH to SRAM b. Initialize the system stack (clear to 0) Then enter main and thus enter the world of c. But the startup file does not end here, there is another part. The function of this part is to define a segment to store the interrupt vector table, and then fill in the interrupt pointers in the form of words. There is another part after this. The purpose of this part is to define a weak alias for the interrupt service. The purpose of this weak alias is that after an interrupt is triggered, if the corresponding weak alias is not overwritten, the program will execute the default interrupt handler function (Default_Handler) by default, otherwise it will execute the overwritten interrupt handler function
Previous article:Solve STM32 HardFault_Handler error logging
Next article:STM32 cannot start after hardware reset
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Brief Analysis of Automotive Ethernet Test Content and Test Methods
- How haptic technology can enhance driving safety
- Let’s talk about the “Three Musketeers” of radar in autonomous driving
- Why software-defined vehicles transform cars from tools into living spaces
- How Lucid is overtaking Tesla with smaller motors
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Help, STM32 address data acquisition HardFault_Handler
- CC2640R2 uses the IDE's post-build function to generate a single firmware file
- ST MEMS waterproof pressure sensor LPS27HHW review summary
- The problem of not receiving data when building lorawan gateway with Raspberry Pi
- Two questions about registers
- UWB, Bluetooth, RFID, WIFI and indoor positioning technology
- 【micropython】NUCLEO_L073RZ and NUCLEO_L452RE have been added to the firmware library
- [NUCLEO-L552ZE Review] + Low Power Measurement Tool
- Lithium battery charging and discharging integrated chip
- Bluetooth module connection problem