cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f4discovery Program and interrupt-vector in RAM not working. Testing with systick.

Sara1
Associate II

I'm trying to recreate a project we did in school on my stm32f4discovery-board. For some reason the teacher decided to load the program and the interrupt-vector into RAM. The interrupt-vector should start at address 0x2001C000. I managed to load and run the program in RAM but I'm having trouble with the interrupt-vector when trying to use systick-interrupts. How do I correctly place and use the interrupt-vector in ram? The code is not the whole school-project, just some pieces of it. I have added the function relocate_irq_vectors().

How the teacher relocated the vector, I don't know. I have tried the systick-setup in another program with a normally placed interrupt-vector, so I don't think that is the problem. The program should blink a led when the systick reach 1000.

Code:

#include "stm32f4xx.h"

#include "stm32f4xx_usart.h"

#include "stm32f4xx_rcc.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_tim.h"

#include "misc.h"

void led_init();

void bss_init(void);

void relocate_irq_vectors(void);

void systick_init(uint16_t frequency);

extern void SysTick_Handler(void);

void delay(__IO uint32_t c);

void startup(void) __attribute__((naked)) __attribute__((section (".start_section")) );

void startup(void) {

asm volatile(

" NOP\n"

" LDR SP,=0x2001C000\n" // Set stack

" BL relocate_irq_vectors\n"

" BL bss_init\n"

" BL main\n"

".L1: B .L1\n"

);

}

void relocate_irq_vectors() {

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x1c000);

}

void bss_init() {

asm volatile(

" ldr r2, =_sbss\n"

" b LoopFillZerobss\n"

"FillZerobss:\n"

" movs r3, #0\n"

" str r3, [r2], #4\n"

"LoopFillZerobss:\n"

" ldr r3, = _ebss\n"

" cmp r2, r3\n"

" bcc FillZerobss\n"

) ;

}

#define SYSTICK_VECTOR (0x2001C000+0x3C)

int main() {

led_init();

systick_init(1000);

while (1) {

GPIO_ToggleBits(GPIOD, GPIO_Pin_15);

delay(1048575);

}

return 0;

}

void systick_init(uint16_t frequency) {

RCC_ClocksTypeDef RCC_Clocks;

RCC_GetClocksFreq(&RCC_Clocks);

(void) SysTick_Config(RCC_Clocks.HCLK_Frequency / frequency);

*((void (**)(void) ) SYSTICK_VECTOR ) = SysTick_Handler;

}

volatile uint32_t ticks;

extern void SysTick_Handler(void) {

ticks++;

}

void delay(__IO uint32_t c) {

ticks = 0;

while(ticks < 1000);

// while(c--);

}

void led_init() {

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

GPIO_InitTypeDef GPIO_InitDef;

GPIO_InitDef.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;

GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;

GPIO_InitDef.GPIO_OType = GPIO_OType_PP;

GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitDef.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOD, &GPIO_InitDef);

}

}

6 REPLIES 6
berendi
Principal

Copy it with memcpy()

turboscrew
Senior III

I'm not sure, but I think NVIC_SetVectorTable() only sets VTOR. It doesn't copy the table.

I think that routine has disappeared from the libraries long ago.

There's probably nothing to be copied - note that startup code is part of what is presented here, presumably a single .c file of the project, with the startup relying maybe on the debugger ("managed to load and run the program in RAM")?

> *((void (**)(void) ) SYSTICK_VECTOR ) = SysTick_Handler;

And as long as there's only one interrupt, writing it's vector directly is more-less OK (except that the fault handlers are not set, so if fault kicks in, it's quite likely to execute some garbage and then end up in the lockup). I mean, while unusual, this may be an illustrative setup, if the teacher explains all the ins and outs.

OTOH, there's this reliance on SPL, which is IMO weird.

At the end of the day, I don't see any obvious problem here, but I'd recommend to disassemble and see how the startup is solved; or as an alternative, single-step it from the very beginning.

JW

Thanks for the reply. Will try to step as you suggested. Yes I use gdb to load the program to ram. What do you mean by "reliance on SPL"?

> What do you mean by "reliance on SPL"?

NVIC_SetVectorTable() and GPIO_Init(); are SPL (Standard Peripheral Library) functions.

Not only is SPL deprecated by ST for quite a couple of years (and not available for newer STM32 families), I find it also strange that somebody who teaches using direct addresses

> #define SYSTICK_VECTOR (0x2001C000+0x3C)

and inline ASM, would also use SPL functions which often only rename direct register acesses.

JW

Ok thanks. Good to know.