STM32 HardFault при загрузке с Flash - PullRequest
0 голосов
/ 23 мая 2018

У меня есть простая голая программа для ARM-чипа STM32F103 (я использую набор инструментов GNU и отладчик openocd).

Когда я запускаю его из ОЗУ, он работает нормально.Когда я загружаю микросхему с помощью предустановленного загрузчика и сразу перепрыгиваю на 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

Сценарий компоновщика ОЗУ:

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 Ответ

0 голосов
/ 27 мая 2018

Ваша ошибка в сценарии компоновщика:

_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.Это неверно - последний бит должен быть установлен для набора команд большого пальца.

Это вызовет ошибку при сбросе, как только это значение будет загружено в ПК - до того, как будет выполнена первая инструкция.

Причина - пропущенная декларация: .type Reset_Handler, %function

В файле запуска ассемблера, который я использую, есть еще несколько объявлений:

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