程序计数器不会从堆栈返回

时间:2017-08-06 17:28:31

标签: assembly arm stm32

我正在尝试学习arm汇编程序(在stm32上)并遇到了问题。我在TIM2上配置了定时器中断。 ISR已执行,但是在从加载0的中断程序计数器返回时。我已经调查了中断如何调用并检查了堆栈的主线程寄存器值。在堆栈程序中,计数器值是正确的,但NVIC不接受它。有没有人有想法为什么会如此?

.thumb
.syntax unified

.text
.org 0x00000000                 
SP: .word STACKINIT             
RESET: .word main + 1
NMI_HANDLER: .word nmi_fault + 1
HARD_FAULT: .word hard_fault + 1
MEMORY_FAULT: .word memory_fault + 1
BUS_FAULT: .word bus_fault + 1
USAGE_FAULT: .word usage_fault + 1
.org 0x000000B0
TIMER2_INTERRUPT: .word timer2_interupt + 1

main:
    push {lr}
    bl cpu_init
    pop {lr}

    push {lr}
    bl sleep_mode_init
    pop {lr}

    push {lr}
    bl timer2_init
    pop {lr}

    cpsie i

    push {lr}
    bl timer2_enable
    pop {lr}

_main_loop: 
    b _main_loop
    bx lr

@ initialize timer 2 for using
timer2_init:
    push {r0, r1}

    @ TIM2 timer clock enable
    @ load value from RCC_APB1ENR register
    ldr r1, =RCC_APB1ENR
    ldr r0, [r1]

    @ set bit 0 (TIM2 timer clock enable)
    orr r0, r0, 0x01

    @ store r0 to RCC_APB1ENR
    str r0, [r1]

    @ load value from TIM2_CR1 register
    ldr r1, =TIM2_CR1
    ldr r0, [r1]

    @ set timer2 Clock division bits (to 00), Auto-reload preload enable bit, Update request source bit and Counter enable bit
    ldr r0, =0x8D
    str r0, [r1]

    @ set timer2 prescaler register
    ldr r1, =TIM2_PSC
    ldr r0, =0x10000            @ maximum prescaler value
    str r0, [r1]

    @ set auto-reload value to 1 (The counter is blocked while the auto-reload value is null.)
    ldr r1, =TIM2_ARR
    ldr r0, =0xFFFF @=0x01
    str r0, [r1]    

    @ clear pending state for TIM2 interrupt
    ldr r1, =NVIC_ICPR0
    ldr r0, [r1]

    orr r0, r0, 0x10000000
    str r0, [r1]

    @ set timer2 interrupt priority (each priority register contains priority for 4 interrrupts (each priority 8bit long))
    ldr r1, =NVIC_IPR7
    ldr r0, =0x23000000                             @ priority 35 as defined in manuals

    str r0, [r1]

    @ set 28th bit in NVIC_ISER0 register, this should enable TIM2 interrupt
    ldr r1, =NVIC_ISER0
    ldr r0, [r1]

    orr r0, r0, 0x10000000

    str r0, [r1]

    pop {r0, r1}    
    bx lr

@ sets Update interrupt enable bit in TIM2_DIER register
@ function does not take, nor recieve parameters
timer2_enable:
    push {r0, r1}

    ldr r1, =TIM2_DIER
    ldr r0, [r1]
    orr r0, r0, 0x01
    str r0, [r1]

    pop {r0, r1}
    bx lr

@ initialize CPU for using
@ function does not take, nor recieve parameters
cpu_init:
    push {r0, r1}

    @ set RCC_CFGR register to system clock
    ldr r1, =RCC_CFGR       @ load address of RCC_CFGR registers
    ldr r0, =0x5000000 @ high speed (clock) internal selected (HSI)
    str r0, [r1]            @ store value from r0 to address in r1

    pop {r0, r1}
    bx lr

@ initialize sleep mode behaviours
sleep_mode_init:
    push {r0, r1}
    @ set SLEEPONEXIT bit in System Control register (if the SLEEPONEXIT bit is set, the MCU enters Sleep mode as soon as it exits the lowest priority ISR)

    @ read SCR register value (system control register)
    ldr r1, =SCR
    ldr r0, [r1]

    @ set SLEEPONEXIT bit (first bit)
    orr r0, r0, 0x02

    @ store r0 value to SCR register
    str r0, [r1]

    pop {r0, r1}
    bx lr

timer2_interupt:

    @ check values in stack
    mov r1, 0x18
    ldr r0, [sp, r1]

    bx lr

nmi_fault:
    bkpt
    bx lr

hard_fault:
    bkpt
    bx lr

memory_fault:
    bkpt
    bx lr

bus_fault:
    bkpt
    bx lr

usage_fault:
    bkpt
    bx lr

.end

0 个答案:

没有答案