1. 简介:
对 stm32f103 工程的分析,需要从启动文件开始2. 固件库中 stm32f103 的启动文件: 文件的名字:startup_stm32f10xhd.s
前边是段的声明
MODULE?cstartup;
;
Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)SECTION .intvec:CODE:NOROOT(2)EXTERN__iar_program_start
EXTERNSystemInit
PUBLIC__vector_table
【1】MODULE 控制指令是用来标记 modules 源码的开始和结束,后边的 ?cstartup 是模块的名字,此文档的最后的 END 表明模块的结束
【2】SECTION 指令是声明段,一个段不能同时包含 public symbol 和 pubweak symbol ,模块只有在相同的名字的模块没有被链接进来的时候才会被链接进来。
语法格式:SECTION section:type [flag] [(align)]
align,是用于指定地址对齐到 2^align,他的取值是 0 到 30
flag,取值NOROOT、ROOT、REORDER、NOREORDER,默认是ROOT,NOROOT表示如果这个段中的符号没有被引用,将会被连接器舍弃,即可被优化。ROOT表示不可被优化。REORDER表示开始一个新的名字是 section 的段(section),NOREORDER表示开始一个新的名字为 section 的片段(fragment),多个片段组成一个段(section)
type,memory 的类型,取值是 CODE、CONST、DATA
section,段的名字
【3】EXTERN 用导入其他模块的 symbol(符号)
【4】PUBLIC 导出 symbol(符号)
DATA__vector_table
DCDsfe(CSTACK)
DCDReset_Handler;
Reset Handler
DCDNMI_Handler;
NMI Handler
DCDHardFault_Handler;
Hard Fault Handler
DCDMemManage_Handler;
MPU Fault Handler
DCDBusFault_Handler;
Bus Fault Handler
DCDUsageFault_Handler;
Usage Fault Handler
DCD0;
Reserved
DCD0;
Reserved
DCD0;
Reserved
DCD0;
Reserved
DCDSVC_Handler;
SVCall Handler
DCDDebugMon_Handler;
Debug Monitor Handler
DCD0;
Reserved
DCDPendSV_Handler;
PendSV Handler
DCDSysTick_Handler;
SysTick Handler;
External Interrupts
DCDWWDG_IRQHandler;
Window Watchdog
DCDPVD_IRQHandler;
PVD through EXTI Line detect
DCDTAMPER_IRQHandler;
Tamper
DCDRTC_IRQHandler;
RTC
DCDFLASH_IRQHandler;
Flash
DCDRCC_IRQHandler;
RCC
DCDEXTI0_IRQHandler;
EXTI Line 0
DCDEXTI1_IRQHandler;
EXTI Line 1
DCDEXTI2_IRQHandler;
EXTI Line 2
DCDEXTI3_IRQHandler;
EXTI Line 3
DCDEXTI4_IRQHandler;
EXTI Line 4
DCDDMA1_Channel1_IRQHandler;
DMA1 Channel 1
DCDDMA1_Channel2_IRQHandler;
DMA1 Channel 2
DCDDMA1_Channel3_IRQHandler;
DMA1 Channel 3
DCDDMA1_Channel4_IRQHandler;
DMA1 Channel 4
DCDDMA1_Channel5_IRQHandler;
DMA1 Channel 5
DCDDMA1_Channel6_IRQHandler;
DMA1 Channel 6
DCDDMA1_Channel7_IRQHandler;
DMA1 Channel 7
DCDADC1_2_IRQHandler;
ADC1 & ADC2
DCDUSB_HP_CAN1_TX_IRQHandler;
USB High Priority or CAN1 TX
DCDUSB_LP_CAN1_RX0_IRQHandler ;
USB LowPriority or CAN1 RX0
DCDCAN1_RX1_IRQHandler;
CAN1 RX1
DCDCAN1_SCE_IRQHandler;
CAN1 SCE
DCDEXTI9_5_IRQHandler;
EXTI Line 9..5
DCDTIM1_BRK_IRQHandler;
TIM1 Break
DCDTIM1_UP_IRQHandler;
TIM1 Update
DCDTIM1_TRG_COM_IRQHandler;
TIM1 Trigger and Commutation
DCDTIM1_CC_IRQHandler;
TIM1 Capture Compare
DCDTIM2_IRQHandler;
TIM2
DCDTIM3_IRQHandler;
TIM3
DCDTIM4_IRQHandler;
TIM4
DCDI2C1_EV_IRQHandler;
I2C1 Event
DCDI2C1_ER_IRQHandler;
I2C1 Error
DCDI2C2_EV_IRQHandler;
I2C2 Event
DCDI2C2_ER_IRQHandler;
I2C2 Error
DCDSPI1_IRQHandler;
SPI1
DCDSPI2_IRQHandler;
SPI2
DCDUSART1_IRQHandler;
USART1
DCDUSART2_IRQHandler;
USART2
DCDUSART3_IRQHandler;
USART3
DCDEXTI15_10_IRQHandler;
EXTI Line 15..10
DCDRTCAlarm_IRQHandler;
RTC Alarm through EXTI Line
DCDUSBWakeUp_IRQHandler;
USB Wakeup from suspend
DCDTIM8_BRK_IRQHandler;
TIM8 Break
DCDTIM8_UP_IRQHandler;
TIM8 Update
DCDTIM8_TRG_COM_IRQHandler;
TIM8 Trigger and Commutation
DCDTIM8_CC_IRQHandler;
TIM8 Capture Compare
DCDADC3_IRQHandler;
ADC3
DCDFSMC_IRQHandler;
FSMC
DCDSDIO_IRQHandler;
SDIO
DCDTIM5_IRQHandler;
TIM5
DCDSPI3_IRQHandler;
SPI3
DCDUART4_IRQHandler;
UART4
DCDUART5_IRQHandler;
UART5
DCDTIM6_IRQHandler;
TIM6
DCDTIM7_IRQHandler;
TIM7
DCDDMA2_Channel1_IRQHandler;
DMA2 Channel1
DCDDMA2_Channel2_IRQHandler;
DMA2 Channel2
DCDDMA2_Channel3_IRQHandler;
DMA2 Channel3
DCDDMA2_Channel4_5_IRQHandler ;
DMA2 Channel4 & Channel5
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
【1】DATA 表示下边中的标签是 32 位的标签,THUMB 表示下边的标签是 16 位的标签,所谓的标签是 地址的别名,不占用代码空间,给编译器看的
【2】 DCD 是数据定义或者 重定位指令,为的是定义一个值,或者保留 memory,DCD 别名是 DC32,用于声明一个 32 位的常量,这部分是中断向量表的内容,需要注意的是,他们的顺序不能改变,此部分会放到 flash 的最开始部分,当系统启动的时候会加载前另个地址,第一个地址是 c 程序的栈的栈顶地址,第二个地址是向量表的开始地址,中断发生时会根据向量表的首地址和偏移量来找到程序的入口
【3】sfe 指令作用是返回栈的结尾,因为栈的增长方向是反方向的
;
;
;
;
Default interrupt handlers.
;
;
THUMBPUBWEAK Reset_Handler
SECTION .text:CODE:REORDER(2)
Reset_Handler
LDRR0, =SystemInit
BLXR0
LDRR0, =__iar_program_start
BXR0PUBWEAK NMI_Handler
SECTION .text:CODE:REORDER(1)
NMI_Handler
B NMI_HandlerPUBWEAK HardFault_Handler
SECTION .text:CODE:REORDER(1)
HardFault_Handler
B HardFault_HandlerPUBWEAK MemManage_Handler
SECTION .text:CODE:REORDER(1)
MemManage_Handler
B MemManage_HandlerPUBWEAK BusFault_Handler
SECTION .text:CODE:REORDER(1)
BusFault_Handler
B BusFault_HandlerPUBWEAK UsageFault_Handler
SECTION .text:CODE:REORDER(1)
UsageFault_Handler
B UsageFault_HandlerPUBWEAK SVC_Handler
SECTION .text:CODE:REORDER(1)
SVC_Handler
B SVC_HandlerPUBWEAK DebugMon_Handler
SECTION .text:CODE:REORDER(1)
DebugMon_Handler
B DebugMon_HandlerPUBWEAK PendSV_Handler
SECTION .text:CODE:REORDER(1)
PendSV_Handler
B PendSV_HandlerPUBWEAK SysTick_Handler
SECTION .text:CODE:REORDER(1)
SysTick_Handler
B SysTick_HandlerPUBWEAK WWDG_IRQHandler
SECTION .text:CODE:REORDER(1)
WWDG_IRQHandler
B WWDG_IRQHandlerPUBWEAK PVD_IRQHandler
SECTION .text:CODE:REORDER(1)
PVD_IRQHandler
B PVD_IRQHandlerPUBWEAK TAMPER_IRQHandler
SECTION .text:CODE:REORDER(1)
TAMPER_IRQHandler
B TAMPER_IRQHandlerPUBWEAK RTC_IRQHandler
SECTION .text:CODE:REORDER(1)
RTC_IRQHandler
B RTC_IRQHandlerPUBWEAK FLASH_IRQHandler
SECTION .text:CODE:REORDER(1)
FLASH_IRQHandler
B FLASH_IRQHandlerPUBWEAK RCC_IRQHandler
SECTION .text:CODE:REORDER(1)
RCC_IRQHandler
B RCC_IRQHandlerPUBWEAK EXTI0_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI0_IRQHandler
B EXTI0_IRQHandlerPUBWEAK EXTI1_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI1_IRQHandler
B EXTI1_IRQHandlerPUBWEAK EXTI2_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI2_IRQHandler
B EXTI2_IRQHandlerPUBWEAK EXTI3_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI3_IRQHandler
B EXTI3_IRQHandlerPUBWEAK EXTI4_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI4_IRQHandler
B EXTI4_IRQHandlerPUBWEAK DMA1_Channel1_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel1_IRQHandler
B DMA1_Channel1_IRQHandlerPUBWEAK DMA1_Channel2_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel2_IRQHandler
B DMA1_Channel2_IRQHandlerPUBWEAK DMA1_Channel3_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel3_IRQHandler
B DMA1_Channel3_IRQHandlerPUBWEAK DMA1_Channel4_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel4_IRQHandler
B DMA1_Channel4_IRQHandlerPUBWEAK DMA1_Channel5_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel5_IRQHandler
B DMA1_Channel5_IRQHandlerPUBWEAK DMA1_Channel6_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel6_IRQHandler
B DMA1_Channel6_IRQHandlerPUBWEAK DMA1_Channel7_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA1_Channel7_IRQHandler
B DMA1_Channel7_IRQHandlerPUBWEAK ADC1_2_IRQHandler
SECTION .text:CODE:REORDER(1)
ADC1_2_IRQHandler
B ADC1_2_IRQHandlerPUBWEAK USB_HP_CAN1_TX_IRQHandler
SECTION .text:CODE:REORDER(1)
USB_HP_CAN1_TX_IRQHandler
B USB_HP_CAN1_TX_IRQHandlerPUBWEAK USB_LP_CAN1_RX0_IRQHandler
SECTION .text:CODE:REORDER(1)
USB_LP_CAN1_RX0_IRQHandler
B USB_LP_CAN1_RX0_IRQHandlerPUBWEAK CAN1_RX1_IRQHandler
SECTION .text:CODE:REORDER(1)
CAN1_RX1_IRQHandler
B CAN1_RX1_IRQHandlerPUBWEAK CAN1_SCE_IRQHandler
SECTION .text:CODE:REORDER(1)
CAN1_SCE_IRQHandler
B CAN1_SCE_IRQHandlerPUBWEAK EXTI9_5_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI9_5_IRQHandler
B EXTI9_5_IRQHandlerPUBWEAK TIM1_BRK_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM1_BRK_IRQHandler
B TIM1_BRK_IRQHandlerPUBWEAK TIM1_UP_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM1_UP_IRQHandler
B TIM1_UP_IRQHandlerPUBWEAK TIM1_TRG_COM_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM1_TRG_COM_IRQHandler
B TIM1_TRG_COM_IRQHandlerPUBWEAK TIM1_CC_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM1_CC_IRQHandler
B TIM1_CC_IRQHandlerPUBWEAK TIM2_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM2_IRQHandler
B TIM2_IRQHandlerPUBWEAK TIM3_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM3_IRQHandler
B TIM3_IRQHandlerPUBWEAK TIM4_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM4_IRQHandler
B TIM4_IRQHandlerPUBWEAK I2C1_EV_IRQHandler
SECTION .text:CODE:REORDER(1)
I2C1_EV_IRQHandler
B I2C1_EV_IRQHandlerPUBWEAK I2C1_ER_IRQHandler
SECTION .text:CODE:REORDER(1)
I2C1_ER_IRQHandler
B I2C1_ER_IRQHandlerPUBWEAK I2C2_EV_IRQHandler
SECTION .text:CODE:REORDER(1)
I2C2_EV_IRQHandler
B I2C2_EV_IRQHandlerPUBWEAK I2C2_ER_IRQHandler
SECTION .text:CODE:REORDER(1)
I2C2_ER_IRQHandler
B I2C2_ER_IRQHandlerPUBWEAK SPI1_IRQHandler
SECTION .text:CODE:REORDER(1)
SPI1_IRQHandler
B SPI1_IRQHandlerPUBWEAK SPI2_IRQHandler
SECTION .text:CODE:REORDER(1)
SPI2_IRQHandler
B SPI2_IRQHandlerPUBWEAK USART1_IRQHandler
SECTION .text:CODE:REORDER(1)
USART1_IRQHandler
B USART1_IRQHandlerPUBWEAK USART2_IRQHandler
SECTION .text:CODE:REORDER(1)
USART2_IRQHandler
B USART2_IRQHandlerPUBWEAK USART3_IRQHandler
SECTION .text:CODE:REORDER(1)
USART3_IRQHandler
B USART3_IRQHandlerPUBWEAK EXTI15_10_IRQHandler
SECTION .text:CODE:REORDER(1)
EXTI15_10_IRQHandler
B EXTI15_10_IRQHandlerPUBWEAK RTCAlarm_IRQHandler
SECTION .text:CODE:REORDER(1)
RTCAlarm_IRQHandler
B RTCAlarm_IRQHandlerPUBWEAK USBWakeUp_IRQHandler
SECTION .text:CODE:REORDER(1)
USBWakeUp_IRQHandler
B USBWakeUp_IRQHandlerPUBWEAK TIM8_BRK_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM8_BRK_IRQHandler
B TIM8_BRK_IRQHandlerPUBWEAK TIM8_UP_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM8_UP_IRQHandler
B TIM8_UP_IRQHandlerPUBWEAK TIM8_TRG_COM_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM8_TRG_COM_IRQHandler
B TIM8_TRG_COM_IRQHandlerPUBWEAK TIM8_CC_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM8_CC_IRQHandler
B TIM8_CC_IRQHandlerPUBWEAK ADC3_IRQHandler
SECTION .text:CODE:REORDER(1)
ADC3_IRQHandler
B ADC3_IRQHandlerPUBWEAK FSMC_IRQHandler
SECTION .text:CODE:REORDER(1)
FSMC_IRQHandler
B FSMC_IRQHandlerPUBWEAK SDIO_IRQHandler
SECTION .text:CODE:REORDER(1)
SDIO_IRQHandler
B SDIO_IRQHandlerPUBWEAK TIM5_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM5_IRQHandler
B TIM5_IRQHandlerPUBWEAK SPI3_IRQHandler
SECTION .text:CODE:REORDER(1)
SPI3_IRQHandler
B SPI3_IRQHandlerPUBWEAK UART4_IRQHandler
SECTION .text:CODE:REORDER(1)
UART4_IRQHandler
B UART4_IRQHandlerPUBWEAK UART5_IRQHandler
SECTION .text:CODE:REORDER(1)
UART5_IRQHandler
B UART5_IRQHandlerPUBWEAK TIM6_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM6_IRQHandler
B TIM6_IRQHandlerPUBWEAK TIM7_IRQHandler
SECTION .text:CODE:REORDER(1)
TIM7_IRQHandler
B TIM7_IRQHandlerPUBWEAK DMA2_Channel1_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA2_Channel1_IRQHandler
B DMA2_Channel1_IRQHandlerPUBWEAK DMA2_Channel2_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA2_Channel2_IRQHandler
B DMA2_Channel2_IRQHandlerPUBWEAK DMA2_Channel3_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA2_Channel3_IRQHandler
B DMA2_Channel3_IRQHandlerPUBWEAK DMA2_Channel4_5_IRQHandler
SECTION .text:CODE:REORDER(1)
DMA2_Channel4_5_IRQHandler
B DMA2_Channel4_5_IRQHandlerEND
【1】THUMB 表明下边是 thumb 指令
【2】Reset_Handler 在开机或者复位的时候执行
R0 = SystemInit
跳转到 SystemInit 函数,并将处理器切换到 thumb 状态
R0 = __iar_program_start
跳转到 __iar_program_start 函数,状态也是切换到 thumb 状态
【3】此处的 __iar_program_start 在程序中找不到是因为它已经被封装到了 IAR 自带的C库启动代码中了,当我们编译的时候,在项目属性的 linker,library中勾选了 Automatic runtime library ,就告诉了编译器用库中的 __iar_program_start ,具体实现了什么,我们可以查看 IAR 工具为我们提供的源码,具体路径在 IAR 安装目录下的 arm\src\lib\thumb ,我们可以看到有的文件分别的提供了 汇编代码和 c 代码。
其中的 cstartup_M.s 文件中有
#pragma required=__vector_table
void __iar_program_start( void )
{
__iar_init_core();
__iar_init_vfp();
__cmain();
}
【1】此段的程序中前两个函数是弱函数,在工程共没有定义
【2】__cmain 函数作用是初始化段和底层硬件,最后调用main
至此,库文件中的启动文件先分析到这里
3. FreeRTOS 中的汇编代码: 当 FreeRTOS 和 stm32 移植好后,会用到 FreeRTOS 中的源码文件portasm.s 中的函数
xPortPendSVHandler 函数:
xPortPendSVHandler:
mrs r0, psp
isb
ldr r3, =pxCurrentTCB/* 获取当前任务的控制块(TCB)指针. */
ldr r2, [r3] stmdb r0!, {r4-r11}/* 保存 R4-R11 到该任务的堆栈. */
str r0, [r2]/* 将最后的堆栈指针保存到任务控制块的 pxTopOfStack. */ stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY /* 关闭中断 */
msr basepri, r0
dsb
isb
bl vTaskSwitchContext /* 切换任务上下文,pxCurrentTCB 已指向新的任务 */
mov r0, #0
msr basepri, r0
ldmia sp!, {r3, r14} ldr r1, [r3]/* 恢复新任务的上下文到各寄存器 */
ldr r0, [r1]/* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers. */
msr psp, r0
isb
bx r14
【1】这个函数的功能是请求切换任务
【2】任务切换的示意图如下:
【FreeRTOS 第二课(启动文件分析)】
文章图片
vPortSVCHandler 函数:直接切换任务用于vPortStartFirstTask第一次启动任务时初始化堆栈和各寄存器
vPortSVCHandler:
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r1, [r3]
ldr r0, [r1]
/* Pop the core registers. */
ldmia r0!, {r4-r11}
msr psp, r0
isb
mov r0, #0
msr basepri, r0
orr r14, r14, #13
bx r14
函数:启动第一个任务的汇编实现
vPortStartFirstTask
/* Use the NVIC offset register to locate the stack. */
ldr r0, =0xE000ED08 /* 向量表偏移量寄存器 (VTOR) */
ldr r0, [r0]
ldr r0, [r0]
/* Set the msp back to the start of the stack. */
msr msp, r0 /* 将堆栈地址保存到主堆栈指针msp中 */
/* Call SVC to start the first task, ensuring interrupts are enabled. */
cpsie i /* 触发SVC软中断,由vPortSVCHandler()完成第一个任务的具体切换工作 */
cpsie f
dsb
isb
svc 0
【1】此部分参照 (伟研科技 http://www.gzweiyan.com) 资料
【2】内核调度器启动的流程如下:
文章图片
推荐阅读
- stm32|基于STM32和freeRTOS智能门锁设计方案
- #|FreeRTOS(1)---FreeRTOS 内核配置说明
- FreeRTOS|FreeRTOS开发实战_FreeRTOS内核配置项目解析
- LwIP|LwIP移植到FreeRTOS(STM32F107+DP83848)