assembly 从闪存启动时的STM32 HardFault

55ooxyrt  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(97)

我有一个简单的STM32F103 ARM芯片的裸机程序(我使用GNU工具链和openocd调试器)。
当我从RAM运行它时,它工作得很好。当我使用预装的引导加载程序 Boot 芯片并直接跳到闪存中的Reset_Handler位置时,它也可以工作。但当我尝试从闪存 Boot 时,处理器进入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

kmbjn2e3

kmbjn2e31#

您的错误出现在链接器脚本中:

_estack = 0x20004FFF;

字符串
由于该值在向量表中未改变地使用,因此SP将用奇数值初始化。但ARM规范实际上指定SP可被8整除(对齐到8字节)。
第一次使用堆栈时,奇数值会触发错误。
Fix就是:

_estack = 0x20005000;


编辑:
向量表中存在更多错误:

8000004:       08000120        stmdaeq r0, {r5, r8}
8000008:       08000111        stmdaeq r0, {r0, r4, r8}


8000004处的“reset handler”应该是08000121,但实际上是08000120。这是无效的-最后一位必须为thumb指令集设置。
一旦将该值加载到PC中,这将在重置时触发故障-在第一条指令可以执行之前。
原因是缺少声明:.type Reset_Handler, %function
在我使用的汇编程序启动文件中还有一些声明:

.text
    .thumb
    .thumb_func
    .align 1
    .globl Reset_Handler
    .type Reset_Handler, %function
Reset_Handler:
/* code here ..*/

相关问题