代码之家  ›  专栏  ›  技术社区  ›  Sergey

从闪存启动时出现STM32硬故障

  •  1
  • Sergey  · 技术社区  · 7 年前

    我有一个简单的STM32F103 ARM芯片裸机程序(我使用GNU工具链和OpenOCD调试器)。

    当我从RAM运行它时,它工作正常。当我使用预装的引导加载程序引导芯片时,直接跳到 Reset_Handler 位置在闪存,它也工作。但当我尝试从闪存启动时,处理器进入硬故障模式。

    处理器复位后, pc 将点注册到 重置处理程序 位置。当我迈出一步时,如果 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
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   Turbo J    7 年前

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

    _estack = 0x20004FFF;
    

    由于该值在向量表中的使用是不变的,因此将使用奇数值初始化sp。但是ARM规范实际上指定SP可以8分(与8字节对齐)。

    一旦第一次使用堆栈,奇数值就会触发故障。

    修复方法很简单:

    _estack = 0x20005000;
    

    编辑:

    矢量表中有更多错误:

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

    “重置处理程序”位于 8000004 应该是 08000121 ,但实际上是 08000120 . 这是无效的-最后一位 必须 为拇指指令集设置。

    一旦该值加载到PC中,在第一条指令可以执行之前,这将在重置时触发故障。

    原因是缺少声明: .type Reset_Handler, %function

    在我使用的汇编程序启动文件中还有一些声明:

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