Program counter doesn't return from stack

0

I'm trying to learn arm assembler (on stm32) and had faced with a problem. I've configured timer interrupt on TIM2. ISR was executed, but on return from interrupt program counter loaded with 0. I've investigated how interrupt is calling and checked the stack for main thread registers values. In the stack program counter value is correct, but NVIC doesn't take it. Does anyone have ideas why it can be so?

.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
assembly
arm
stm32
asked on Stack Overflow Aug 6, 2017 by LLDevLab • edited Aug 6, 2017 by LLDevLab

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0