【发布时间】:2018-11-01 17:50:09
【问题描述】:
我有一个简单的 STM32F103 ARM 芯片裸机程序(我使用 GNU 工具链和 openocd 调试器)。
当我从 RAM 运行它时,它工作正常。当我使用预装的引导加载程序启动芯片并直接跳转到闪存中的Reset_Handler 位置时,它也可以工作。但是当我尝试从 Flash 启动时,处理器会进入 HardFault 模式。
处理器复位后,pc 寄存器立即指向Reset_Handler 位置。当我迈出一步时,如果落入Hardfault_Handler。
为什么会这样?我怀疑这是一个糟糕的内存访问,但一切似乎都是对齐的。
汇编代码:
.syntax unified
.cpu cortex-m3
.arch armv7-m
.fpu softvfp
.thumb
.section .text
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.align 4
Reset_Handler:
mov r0, #0
mov r1, #0
mov r2, #0
b Reset_Handler
.section .vector,"a",%progbits
.type Vectors, %object
.size Vectors, .-Vectors
Vectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.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 0
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word 0
.word 0
.word SPI1_IRQHandler
.word 0
.word USART1_IRQHandler
.word USART2_IRQHandler
.word 0
.word EXTI15_10_IRQHandler
.word RTC_Alarm_IRQHandler
.word USBWakeUp_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
b Reset_Handler
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.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 I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak USBWakeUp_IRQHandler
.thumb_set USBWakeUp_IRQHandler,Default_Handler
.end
RAM 链接描述文件:
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
MEMORY {
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20k
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64k
}
_estack = 0x20004FFF;
SECTIONS {
.isr_vector : {
. = ALIGN(4);
KEEP(*(.vector))
. = ALIGN(8);
} > RAM
.text : {
. = ALIGN(4);
*(.text)
} > RAM
}
Flash 链接器脚本:
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
MEMORY {
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20k
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64k
}
_estack = 0x20004FFF;
SECTIONS {
.isr_vector : {
. = ALIGN(4);
KEEP(*(.vector))
. = ALIGN(8);
} > FLASH
.text : {
. = ALIGN(4);
*(.text)
} > FLASH
}
.text段的拆解:
08000110 <ADC1_2_IRQHandler>:
8000110: e7fe b.n 8000110 <ADC1_2_IRQHandler>
8000112: bf00 nop
8000114: f3af 8000 nop.w
8000118: f3af 8000 nop.w
800011c: f3af 8000 nop.w
08000120 <Reset_Handler>:
8000120: f04f 0000 mov.w r0, #0
8000124: f04f 0100 mov.w r1, #0
8000128: f04f 0200 mov.w r2, #0
800012c: e7f8 b.n 8000120 <Reset_Handler>
800012e: bf00 nop
.isr_vector部分的拆解(部分):
08000000 <Vectors>:
8000000: 20004fff strdcs r4, [r0], -pc ; <UNPREDICTABLE>
8000004: 08000120 stmdaeq r0, {r5, r8}
8000008: 08000111 stmdaeq r0, {r0, r4, r8}
800000c: 08000111 stmdaeq r0, {r0, r4, r8}
8000010: 08000111 stmdaeq r0, {r0, r4, r8}
...
8000108: 08000111 stmdaeq r0, {r0, r4, r8}
800010c: 00000000 andeq r0, r0, r0
【问题讨论】:
-
向量表的反汇编或其他转储显示什么?第一个单词应该是您的堆栈指针预设值,第二个单词应该是 0x08000121 如果它是 0x080000120 然后在 Reset_Handler 标签之前的行上尝试 .thumb_func
-
@PeterJ_01 我正在查看
pc和xPSR寄存器。pc指向0x8000120(Reset_Handler),然后指向0x8000110(Default_Handler)。xPST重置后是0,然后是0x01000003。3是硬故障代码。MSP、PSP和SP是0x20004FFC,它比栈尾低 4 个字节。 -
@old_timer 成功了!但这是怎么回事?
Reset_Handler函数地址是08000120,向量表中指向它的指针是08000121。我认为它应该是指向处理程序的指针。为什么少了 1 个字节? -
@Sergey
PC的最低位表示实际指令集,0是 4 字节 ARM,1是 Thumb。由于 Cortex-M 仅支持 Thumb,因此最低位必须始终设置为1,但仍会从偶数地址 (PC & 0xFFFFFFFE) 获取指令。 -
拇指指令不在奇数地址上。一些指令使用 lsbit 来确定切换到 arm 或 thumb 的模式。也许出于未来的原因,向量表不是一个全尺寸的手臂,它使用 lsbit 来指示在该地址的代码中启动什么模式。通过实验很容易看出 lsbit 被剥离,因为它被启动hander 或 bx 或 blx 或 pop 或其他的逻辑所消耗。指令在偶数地址上对齐,因为否则不会使用 lsbit,因此通过 ... 的指令使用该位是有意义的
标签: assembly arm stm32 cortex-m3 stm32f1