cancel
Showing results for 
Search instead for 
Did you mean: 

Systick Interrupt using GNU Assembler

agung
Associate II
Posted on September 13, 2015 at 16:48

Hi guys,

I have a problem to test systick using GNU assembler on my STM32VLDiscovery

My assembly code is:

.thumb

.syntax unified

.cpu cortex-m3 @ STM32VLDiscovery Board

.equ STACKINIT ,   0x20005000

.equ GPIOC_BASE ,   0x40011000  

.equ GPIOC_CRL     ,   GPIOC_BASE + 0x00

.equ GPIOC_CRH     ,   GPIOC_BASE + 0x04

.equ GPIOC_IDR   ,   GPIOC_BASE + 0x08

.equ GPIOC_ODR     ,   GPIOC_BASE + 0x0C

.equ GPIOC_BSRR     ,   GPIOC_BASE + 0x10

.equ GPIOC_BRR      ,   GPIOC_BASE + 0x14

.equ GPIOC_LCKR     ,   GPIOC_BASE + 0x18

.equ RCC_APB2ENR, 0x40021018

.equ SYSTICK ,  0xE000E010

.equ _CTRL ,  0x00

.equ _LOAD ,  0x04

.equ _CALIB ,  0x0C

.equ _CURRENT ,  0x08

.equ LEDDELAY , 100000

.equ LEDDELAY2 , 800000

.align

.global _start

.global SysTick_handler

.section .text

.org 0

vectors: @ Vectors

        .word STACKINIT

        .word _start + 1

        .word _nmi_handler + 1

        .word _hard_fault + 1

        .word _memory_fault + 1

        .word _bus_fault + 1

        .word _usage_fault + 1

        .org 0x0000003C

        .word SysTick_handler + 1      

_start:

        ldr r6, = RCC_APB2ENR

        mov r0, #0x10 @ Port C Eneable

        str r0, [r6]

        ldr r6, =GPIOC_CRH

        ldr r0, = 0x444433 @ Port C8 dan C9 output 50Hz

        str r0, [r6]

Systick_Init:

cpsid i

LDR R0, =SYSTICK @ SYSTICK control and status register

MOV R1, #0

STR R1, [R0] @ Stop counter to prevent interrupt triggered accidentally

LDR R1, =8000000

STR R1, [R0,_LOAD] @ Write reload value to reload register address

STR R1, [R0,_CURRENT] @ Write any value to current value

@ register to clear current value to 0 and clear COUNTFLAG

MOV R1, #0x7 @ Clock source = core clock, Enable Interrupt, Enable Counter

STR R1, [R0] @ Start counter

cpsie i

loop:   

ldr r6, =GPIOC_BSRR    

ldr r5, =LEDDELAY

delay1:

subs r5, 1

bne delay1

mov r2, #0x200         @ turn on port C8    

str r2, [r6]     

ldr r5, = LEDDELAY

delay2:

subs r5, 1 

bne delay2    

mov r2, #0x2000000     @ turn off port C8          

str r2, [r6]  

b loop

_dummy: @ if any int gets triggered, just loop

_nmi_handler:

_hard_fault:

_memory_fault:

_bus_fault:

_usage_fault:

ldr r6, =GPIOC_BSRR    

ldr r5, =LEDDELAY2

delay3:

subs r5, 1

bne delay3

mov r2, #0x300         @ turn on port C8 and C9      

str r2, [r6]     

ldr r5, = LEDDELAY2

delay4:

subs r5, 1

bne delay4    

mov r2, #0x3000000     @ turn off portC8 and C9            

str r2, [r6]  

b _dummy

SysTick_handler: @ isr routine

ldr r6, =GPIOC_BSRR    

mov r2, #0x300   @ turn on port C9 

str r2, [r6] 

bx lr

My goal just blink the led in pin C8 in the loop section

and when the systick interrupt is triggered, the pin C9 in set

if there is error, the pin C8 and C9 are blink together.

In the first 1 second everything is running well,  means C8 blink successfully

when the systick interrupt is triggered, it should be turning on C9 only

But i always got error (hard fault) , means C8 and C9 blink together ( _dummy loop)

I tried to add this code:

LDR     R1, =0xE000ED22     @ Set the PendSV exception priority (lowest)

LDR     R2, =0xFF

STRB    R2, [R1]

LDR     R1, =0xE000ED23      @ Set the SysTick exception priority (lowest)

LDR     R2, =0xFF

STRB    R2, [R1]

but nothing change.

Does anyone can help me !

Thanks.

7 REPLIES 7
Posted on September 13, 2015 at 17:22

I'm not wading through the code, perhaps using a debugger and stepping through it will help you?

Pretty sure if the assembler knows it's in a code segment, you don't have to +1 subroutine/location addresses. Look at what's in the vector table if you DON'T do this, the addresses should be ODD. If they are not, then look at some startup_stm32fxx.s files to see the desired structure, organization, and section/segment definitions.

Also R6 isn't in the register set that the processor automatically pushes in interrupt context, so review that, and use a register that is pushed, or preserve it yourself.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
agung
Associate II
Posted on September 13, 2015 at 17:33

Thanks, for your fast reply

I will follow your advise, and try to fix again

I will post the result later 

agung
Associate II
Posted on September 13, 2015 at 18:44

Actually i don't know how to debug the assembly code using GNU assembler

I just use ST-Link Utility - LiveUpdate facility, and ''Target --> MCU Core'' to debug and to know Micro controller state

The +1 in my vector table is manually adjust to odd for thumb code

i have tried to remove all the +1 in the vector table and the result is no interrupt called, 

by removing the +1 , the problem is not solved and  my ''dummy loop'' as my indicator also never been called. when the reset button is pressed it should be return my pointer to the _start label, if i remove the +1 the _start label is never been called after the reset button is called.

So i think the +1 in vector table is correct.

i also tried to change r6 to r1 register but nothing change.

moreover, i want to  know the process without any interrupt handler,

so i try to remove all the vector table except stackinit and reset, i just leave my vector table to this:

vectors:

        .word STACKINIT

        .word _start + 1 

and the result is same, the blink of c8 (main loop) is running 1 second, ( 1 second is my systick_load value is 8M) and after that all led is off.

so i guess the problem is in systick interrupt event.

here is my reason:

The main loop is running well for 1 sec and then start error, means the error is happened exactly when systick countdown is reached 0.

i just want to know, why there is an error when the system tick interrupt is triggered.

sorry i am a newbie in microcontroller programming, so i need a lot of helps.

Posted on September 14, 2015 at 02:53

.thumb
.syntax unified
.cpu cortex-m3 @ STM32VLDiscovery Board
.equ STACKINIT , 0x20005000
.equ GPIOC_BASE , 0x40011000
.equ GPIOC_CRL , GPIOC_BASE + 0x00
.equ GPIOC_CRH , GPIOC_BASE + 0x04
.equ GPIOC_IDR , GPIOC_BASE + 0x08
.equ GPIOC_ODR , GPIOC_BASE + 0x0C
.equ GPIOC_BSRR , GPIOC_BASE + 0x10
.equ GPIOC_BRR , GPIOC_BASE + 0x14
.equ GPIOC_LCKR , GPIOC_BASE + 0x18
.equ RCC_APB2ENR, 0x40021018
.equ SYSTICK , 0xE000E010
.equ _CTRL , 0x00
.equ _LOAD , 0x04
.equ _CURRENT , 0x08
.equ _CALIB , 0x0C
.equ LEDDELAY , 100000
.equ LEDDELAY2 , 800000
.align
.global _start
.global SysTick_handler
.global vectors
.section .text
.org 0
vectors: @ Vectors
.word STACKINIT
.word _start + 1
.word _nmi_handler + 1
.word _hard_fault + 1
.word _memory_fault + 1
.word _bus_fault + 1
.word _usage_fault + 1
.org 0x0000003C
.word SysTick_handler + 1
@if .type _start, function you wouldn't need the +1
_start:
ldr r6, =RCC_APB2ENR
mov r0, #0x10 @ Port C Enable
str r0, [r6]
ldr r6, =GPIOC_CRH
ldr r0, = 0x444433 @ Port C8 and C9 output 50Hz
str r0, [r6]
Systick_Init:
LDR R0, =SYSTICK @ SYSTICK control and status register
MOV R1, #0
STR R1, [R0] @ Stop counter to prevent interrupt triggered accidentally
LDR R1, =8000000
STR R1, [R0,_LOAD] @ Write reload value to reload register address
STR R1, [R0,_CURRENT] @ Write any value to current value
@ register to clear current value to 0 and clear COUNTFLAG
MOV R1, #0x7 @ Clock source = core clock, Enable Interrupt, Enable Counter
STR R1, [R0] @ Start counter
loop:
ldr r6, =GPIOC_BSRR
ldr r5, =LEDDELAY
delay1:
subs r5, 1
bne delay1
mov r2, #0x100 @ turn on port C8
str r2, [r6]
ldr r5, = LEDDELAY
delay2:
subs r5, 1
bne delay2
mov r2, #0x1000000 @ turn off port C8
str r2, [r6]
b loop
_dummy: @ if any int gets triggered, just loop
_nmi_handler:
_hard_fault:
_memory_fault:
_bus_fault:
_usage_fault:
ldr r6, =GPIOC_BSRR
ldr r5, =LEDDELAY2
delay3:
subs r5, 1
bne delay3
mov r2, #0x300 @ turn on port C8 and C9
str r2, [r6]
ldr r5, = LEDDELAY2
delay4:
subs r5, 1
bne delay4
mov r2, #0x3000000 @ turn off port C8 and C9
str r2, [r6]
b _dummy
SysTick_handler: @ isr routine
ldr r1, =GPIOC_ODR
ldr r2, [r1]
mov r0, #0x200 @ turn toggle port C9
eor r2, r0
str r2, [r1]
bx lr

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
agung
Associate II
Posted on September 14, 2015 at 10:48

.thumb
.syntax unified
.cpu cortex-m3 @ STM32VLDiscovery Board
.equ STACKINIT , 0x20005000
.equ GPIOC_BASE , 0x40011000
.equ GPIOC_CRL , GPIOC_BASE + 0x00
.equ GPIOC_CRH , GPIOC_BASE + 0x04
.equ GPIOC_IDR , GPIOC_BASE + 0x08
.equ GPIOC_ODR , GPIOC_BASE + 0x0C
.equ GPIOC_BSRR , GPIOC_BASE + 0x10
.equ GPIOC_BRR , GPIOC_BASE + 0x14
.equ GPIOC_LCKR , GPIOC_BASE + 0x18
.equ RCC_APB2ENR, 0x40021018
.equ SYSTICK , 0xE000E010
.equ _CTRL , 0x00
.equ _LOAD , 0x04
.equ _CURRENT , 0x08
.equ _CALIB , 0x0C
.equ LEDDELAY , 100000
.equ LEDDELAY2 , 800000
.align
.global vectors
.section .text
.org 0
.type _start, function
.type _nmi_handler, function
.type _hard_fault, function
.type _memory_fault, function
.type _bus_fault, function
.type _usage_fault, function
.type SysTick_handler, function
vectors: @ Vectors
.word STACKINIT
.word _start 
.word _nmi_handler
.word _hard_fault 
.word _memory_fault 
.word _bus_fault 
.word _usage_fault 
.org 0x0000003C
.word SysTick_handler
@if .type _start, function you wouldn't need the +1
_start:
ldr r6, =RCC_APB2ENR
mov r0, #0x10 @ Port C Enable
str r0, [r6]
ldr r6, =GPIOC_CRH
ldr r0, = 0x444433 @ Port C8 and C9 output 50Hz
str r0, [r6]
Systick_Init:
LDR R0, =SYSTICK @ SYSTICK control and status register
MOV R1, #0
STR R1, [R0] @ Stop counter to prevent interrupt triggered accidentally
LDR R1, =8000000
STR R1, [R0,_LOAD] @ Write reload value to reload register address
STR R1, [R0,_CURRENT] @ Write any value to current value
@ register to clear current value to 0 and clear COUNTFLAG
MOV R1, #0x7 @ Clock source = core clock, Enable Interrupt, Enable Counter
STR R1, [R0] @ Start counter
loop:
ldr r6, =GPIOC_BSRR
ldr r5, =LEDDELAY
delay1:
subs r5, 1
bne delay1
mov r2, #0x100 @ turn on port C8
str r2, [r6]
ldr r5, = LEDDELAY
delay2:
subs r5, 1
bne delay2
mov r2, #0x1000000 @ turn off port C8
str r2, [r6]
b loop
_dummy: @ if any int gets triggered, just loop
_nmi_handler:
_hard_fault:
_memory_fault:
_bus_fault:
_usage_fault:
ldr r6, =GPIOC_BSRR
ldr r5, =LEDDELAY2
delay3:
subs r5, 1
bne delay3
mov r2, #0x300 @ turn on port C8 and C9
str r2, [r6]
ldr r5, = LEDDELAY2
delay4:
subs r5, 1
bne delay4
mov r2, #0x3000000 @ turn off port C8 and C9
str r2, [r6]
b _dummy
SysTick_handler: @ isr routine
ldr r1, =GPIOC_ODR
ldr r2, [r1]
mov r0, #0x200 @ turn toggle port C9
eor r2, r0
str r2, [r1]
bx lr

Hi Clieve, thanks for your help

but i change my code same as your suggestion, Apply the type and use the R1 on Interrupt handler (I attach my complete code and also the assembler program in zip file)

but the problem is not yet solved

I have the video result

https://www.youtube.com/watch?v=y2WVFK60tDo&feature=youtu.be

The first 1 second everything running well, as you can see, the c8 blinks well

but when the systick countdown reach zero (1 second) it should be call the Systick handler and the c9 start blink, but i got hard fault so the dummy loop is running (c8 + c9 blink together)

Any other suggestion?

Thanks

________________

Attachments :

Systick_Test.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzQw&d=%2Fa%2F0X0000000bO7%2F4sWWmagnx63cbhs.PhLQRuXdTSPt7mxL5tg3c6Ebx88&asPdf=false
Posted on September 15, 2015 at 04:04

The part you are using only has 8KB of RAM, not 20KB

    .equ STACKINIT      ,   0x20002000

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
agung
Associate II
Posted on September 15, 2015 at 05:15

Wow .. 

Its work perfectly

I did not realize this very basic problem, but you know it

You are very genius

Thank you very much Clive