我有一个简单的裸机程序用于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
答案 0 :(得分:3)
您的错误在链接描述文件中:
import numpy as np
from collections import deque
queue = deque([], maxlen=10)
queue.appendleft(31)
queue.appendleft(32)
queue.appendleft(33)
cond1 = 35
cond2 = 30
A_1 = np.array(queue)
print(cond2 > A_1 < cond1)
# print(A_1 > 30) # works
# array([ True, True, True], dtype=bool)
print(((cond2 > A_1 < cond1).sum() == A_1.size).astype(np.int))
# print(((A_1 > 30).sum() == A_1.size).astype(np.int)) # works
# 1
由于该值在向量表中未使用,因此将使用奇数值初始化SP。但是ARM规范实际上指定SP可以被8分割(对齐到8个字节)。
奇数值在第一次使用堆栈时立即触发故障。
修复很简单:
_estack = 0x20004FFF;
编辑:
向量表中有更多错误:
_estack = 0x20005000;
8000004: 08000120 stmdaeq r0, {r5, r8}
8000008: 08000111 stmdaeq r0, {r0, r4, r8}
处的“重置处理程序”应为8000004
,但实际上是08000121
。这是无效的 - 为拇指指令集设置最后一位必须。
一旦将该值加载到PC中,这将在复位时触发故障 - 在执行第一条指令之前。
原因是缺少声明:
08000120
在我使用的汇编程序启动文件中有一些声明:
.type Reset_Handler, %function