1

I am trying to implement a very simple program to call a function from systick interrupt on stm32f103rb board. The program runs fine but it never calls the interrupt function. I have gone through many fourms and experimented with different register values but I am not sure what I am missing here. My startup program and test program are below:

startup.s ::

         .data 
arr:    .4byte 0x20001000        @ Read-only array of bytes
        .4byte start+1     
        .4byte reset1
        .4byte reset2
        .4byte reset3
        .4byte reset4
        .4byte reset5
        .4byte reset6
        .4byte reset7
        .4byte reset8
        .4byte reset9
        .4byte reset10
        .4byte reset11
        .4byte reset12
        .4byte reset13
        .4byte reset14
        .4byte reset15
        .4byte reset16
eoa: 
        .text
reset1: b reset1
reset2: b reset2
reset3: b reset3
reset4: b reset4
reset5: b reset5
reset6: b reset6
reset7: b reset7
reset8: b reset8
reset9: b reset9
reset10: b reset10
reset11: b sysTickFunc
reset12: b sysTickFunc
reset13: b sysTickFunc
reset14: b sysTickFunc
reset15: b sysTickFunc
reset16: b sysTickFunc
start:                           @ Label, not really required
        mov   r4, #4             @ Load register r0 with the value 5
        mov   r5, #5             @ Load register r1 with the value 4
        add   r6, r4, r5         @ Add r0 and r1 and store in r2
        ldr   r4, =0x40021000
        str   r1, [r4]
        cpsie i
        b test_func
stop:   b stop                   @ Infinite loop to stop execution

Test.c - test function and systick function implementation::

#define SYSTICK_CTRL     (volatile unsigned int *)( 0xE000E010 )
#define SYSTICK_LOAD     (volatile unsigned int *)( 0xE000E014 )
#define SYSTICK_VAL      (volatile unsigned int *)( 0xE000E018 )

#define PORT_C_CRL   (volatile unsigned int *)( 0x40011000 )
#define PORT_C_CRH   (volatile unsigned int *)( 0x40011004 )
#define PORT_C_ODR   (volatile unsigned int *)( 0x4001100C )
#define APB2         (volatile unsigned int *)( 0x40021018 )
#define AHB          (volatile unsigned int *)( 0x40021014 )

void sysTickFunc(void);
void test_func(void)
{
    volatile unsigned int * p;
    unsigned int x;
    p = SYSTICK_CTRL;
    *p = 7;   /*CLKSRC to processor clock, TICK INT is 1, COUNTER ENABLE is 1  */
    p = SYSTICK_LOAD;
    *p = 20;
    p = (volatile unsigned int *)( 0xE000E01C );
    *p = 0x00002328;
    x = 0;
    /* loop in while and check if systick function is called */
    while(1)
    {
       
       x++;
    }       
}


void sysTickFunc(void)
{
    while(1)
    {
        asm("mov r0,0xCCCCCCCC;");
        asm("mov r1,0xDDDDDDDD;");
        asm("mov r2,0xBBBBBBBB;");
        asm("mov r3,0x11111111;");
        asm("mov r4,0x22222222;");
        asm("mov r5,0x33333333;");
        asm("mov r6,0x44444444;");
    }
}

Linker file:

SECTIONS {
   . = 0x08000000;
   .data : { * (.data)}
   . = 0x08003000;
   .text : {* (.text)} 
}

build script:

arm-none-eabi-gcc -nostdlib -mcpu=cortex-m3 -mthumb -g -o add.elf -T stm.ld test.c startup.s
arm-none-eabi-objcopy -O binary add.elf add.bin
dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=add.bin of=flash.bin bs=4096 conv=notrunc

Can someone help me what is wrong in my code? When I run it with arm gdb on ubuntu, I never get my systick function called. ( I know I have put systick function in many places in the vector table. It was an attempt to check the possibility of sysTickFunction not being at right location in the vector table.)

artless noise
  • 21,212
  • 6
  • 68
  • 105
Ravi
  • 251
  • 2
  • 3
  • 11

1 Answers1

0

Issue #1

How are you checking if the systick got called? Looking at code, you're just setting a few registers, so I assume you're checking those.

This will not work as you might think, as exception entry will store r0-r3 (and some other registers) on stack. You might want to read Cortex-M3 Technical Reference Manual (chapter on Exceptions) for details.

Issue #2

Your linker file lists .text at an offset. That won't work, since reset vectors need to be at beginning. You want to place reset vectors in a separate section that goes at beginning of FLASH, then put .text and .data. Don't forget to also put .data and .bss into RAM.

Issue #3

For start you store the pointer+1 (thumb code), but for any other vectors you don't.

Issue #4

You might also need to enable appropriate clocks before using systick registers, and enable interrupts globally and through NVIC to actually receive interrupts.


I'd also suggest you write clearer code - it makes things easier for you, and for us, trying to read it.

domen
  • 1,819
  • 12
  • 19
  • The code runs perfectly except the part of systick getting ticked. Your point of vector+1 seems the right direction to go. For other things here is my explanation: Issue 1: Startup code works. it jumps to the startup function in C correctly. I am checking this with help of gdb. Issue 2:: My linker lists an offset but my vector table is saved at 0x08000000. That is the address where STM32F103rb (cortex-m3) expects it to be. Issue 3:: That is the problem I think. I will give it a try. Issue 4:: I will look into this after I try the issue 3 solution. – Ravi Nov 15 '16 at 11:20
  • 1. How do you check if your systick function is called? It's important to know, because checking could be the issue. 2. Ah, true, your vectors are in `.data`, so it might work. 6. Why not print systick registers in gdb, and see if it's at least running? – domen Nov 15 '16 at 12:47
  • Adding +1 to vector addresses worked. Just to add, in the example there is no need to copy the data section to the RAM as there are no global variables which are getting updated in the example. But yes if there are any global variables added to the example then there would be need to put vector table in a different section and data section to be copied somewhere in RAM. Also the linker file need to be updated accordingly in that case. – Ravi Nov 15 '16 at 22:04
  • `.data` is normally RW. `.text` and `.rodata` are RO. Vector table should be in its own section, so it can reliably be placed at start of FLASH. Otherwise expect problems in future :) – domen Nov 15 '16 at 23:05
  • Btw, written in C, you don't need to add +1, as compiler (gcc in my case) will recognize function pointers correctly. For example: https://github.com/domenpk/cbaos/blob/master/arch/arm-cortex-m3/mach-stm32/crt.c – domen Nov 15 '16 at 23:12
  • 1
    Yes. Thats correct. But this was just a crude and quick attempt to see the startup behaviour of stm32f103rb. But certainly the proper way is to have different sections for vector table, constants(.rodata), global data(.data) and code(.text). Main purpose of this excercise was to understand startup and systick without using ST libraries. I think I understood the concept correctly except the part where I did the stupid mistake of not have +1 in all vector addresses. – Ravi Nov 15 '16 at 23:19