1

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? 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.

#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);
   }
}
datamoose
  • 181
  • 7
  • Interrupt vector is fancy word for "array of function pointers". So basically you must have an array of function pointers at the RAM address 0x2001C000 and the entry corresponding to the SysTick_IRQn (which iirc should be array index 15) must point to SysTick_Handler. – Vinci Jan 07 '20 at 09:31
  • 1
    Thank you. Do I have to implement the entire intterupt-vector or is it sufficient with the function-pointers that I intend to use? In the example above I have only one function-pointer and it points to SystTick_Handler as you mentioned. – datamoose Jan 14 '20 at 18:35
  • 1
    Well that kinda depends on your definition of sufficient. If the systick is the only interrupt (/exception) that will ever get triggered than leaving all other entries empty would work. A pretty common pattern is to fill all the entries which are not used with a pointer to some default handler which contains an infinite loop. That at least allows the application to be paused by a debugger in case of an error. – Vinci Jan 14 '20 at 20:06
  • At the moment I'm just trying to move the interrupt-vector and use systick to test it. – datamoose Jan 15 '20 at 17:44
  • If you are using a cross-compiler that supports creating a map file I would suggest you generate the *.map file and to double check to make sure that your interrupt vector table is at the correct location you want it. Make sure it lines up as well to what you want in the linker file as well. – Moeiz Riaz Feb 15 '20 at 22:28

0 Answers0