cancel
Showing results for 
Search instead for 
Did you mean: 

Interrupts Vector Table

sirpak
Associate II
Posted on April 03, 2017 at 19:00

Hi,

I am using STMF103R8. I developed a bootloader, which jump to main application. Everything works fine.

Because I made two programs: one for the bootloader and one for the application, I see that the flash is programmed with an Interrupt Vector Table which starts at 0x08000000 for the bootloader and another one which starts at 0x08002000 for the main application. These vector tables take big amount of memory, even if I use only:

  • for the bootloader

SysTick_Handler,

USB_LP_CAN_RX0_IRQHandler,

  • for the main application

SysTick_Handler,

EXTI9_5_IRQHandler,

EXTI1_IRQHandler,

EXTI4_IRQHandler,

ADC1_2_IRQHandler,

TIM2_IRQHandler,

USB_LP_CAN_RX0_IRQHandler.

Unfortunately I am running out of flash memory and I would like to save space taking out what is unnecessary. 

Would it be possible to have two tables with only the entries I need and taking out all the others entries?

Thanks,

Marco

#nvic #stm32 #interrupts #stm32f103 #vector-table
6 REPLIES 6
Posted on April 03, 2017 at 19:30

You can shrink the tables to the last used vector, but they are in a specific order, you can't rearrange the table randomly.

You could make a more condensed table and unpack it into the base of SRAM, and then sent SCB->VTOR to that.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sirpak
Associate II
Posted on April 04, 2017 at 18:08

Hi Clive,

thanks, I managed to have the bootloader working with the vector table in RAM.

The main application, instead, still has the vector table in FLASH, but it does not work anymore.

Is it possible to have the mixed solution: bootloader with the vector table in RAM and main application with the vector table in flash?

can I use address for the main application vector table as 0x08002400? or shall it be 

0x08001000, 0x08002000, 0x08003000 ....?

Thanks,

MS

Posted on April 04, 2017 at 18:45

You'd need to make sure the app doesn't trash the RAM based vector table prior to setting SCB->VTOR, the code to initialize the statics may tread on it if you haven't excluded that area from the linker's use. You must pay attention to detail, but yes mixed solutions are possible.

Yes I think setting SCB->VTOR to 0x08002400 should be fine from an alignment standpoint, a quick check would be to read the content back, I would expect the core to zero the low order bits to enforce its own alignment requirements.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 05, 2017 at 11:34

Maybe if I show you the code you better understand where I made the mistake. Thanks a lot!

I made both Bootloader 

and Application

 with interrupt table in RAM.

on Bootloader and Application stm32f10x_vector.s I left only

__Vectors   DCD __initial_sp                         ; Top of Stack

                   DCD Reset_Handler

and I commented all the following handlers.

Bootloader:

♯ define VECTOR_TABLE_LEN 17 + USB_LP_CAN_RX0_IRQChannel

♯ define VECTOR_TABLE_ADD ((u32)0x20000400)

volatile u32 int_vector_table[VECTOR_TABLE_LEN] __attribute__((at(VECTOR_TABLE_ADD)));

void init_interrupt_controller(void)

{

   u8 int_number;

   for(int_number = 0; int_number < VECTOR_TABLE_LEN; int_number++)

      int_vector_table[int_number] = 0;

   int_vector_table[3] = (u32)&HardFaultException;

   int_vector_table[4] = (u32)&MemManageException;

   int_vector_table[15] = (u32)&SysTick_Handler;

   int_vector_table[16 + USB_LP_CAN_RX0_IRQChannel] = (u32)&USB_LP_CAN_RX0_IRQHandler;

}

int main(void)

{

   ...

   NVIC_DeInit();

   init_interrupt_controller();

   SCB->VTOR = VECTOR_TABLE_ADD;

   SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup_4;

   ...

   while(1)

   {

      ...

      // Non c'è il codice, faccio il jump al main program se c'è il main program

      if(Program_Code_flag == 0)

      {

         // Test if user code is programmed starting from address 'ApplicationAddress'

         if(((*(vu32*)START_FLASH_APP_ADDRESS) & 0x2FFE0000 ) == 0x20000000)

         {

            // Jump to user application

            JumpAddress = *(vu32*) (START_FLASH_APP_ADDRESS + 4);

            Jump_To_Application = (pFunction) JumpAddress;

            // Initialize user application's Stack Pointer

            __set_MSP(*(vu32*) START_FLASH_APP_ADDRESS);

            Jump_To_Application();

         }

      }

   }

}

Application:

♯ define VECTOR_TABLE_LEN 17 + TIM2_IRQChannel

♯ define VECTOR_TABLE_ADD ((u32)0x20000400)

 

volatile u32 int_vector_table[VECTOR_TABLE_LEN] __attribute__((at(VECTOR_TABLE_ADD)));

void init_interrupt_controller(void)

{

   u8 int_number;

   for(int_number = 0; int_number < VECTOR_TABLE_LEN; int_number++)

      int_vector_table[int_number] = 0;

   int_vector_table[3] = (u32)&HardFaultException;

   int_vector_table[4] = (u32)&MemManageException;

   int_vector_table[15] = (u32)&SysTick_Handler;

   int_vector_table[16 + USB_LP_CAN_RX0_IRQChannel] = (u32)&USB_LP_CAN_RX0_IRQHandler;

   int_vector_table[16 + TIM2_IRQChannel] = (u32)&TIM2_IRQHandler;

   int_vector_table[16 + ADC1_2_IRQChannel] = (u32)&ADC1_2_IRQHandler;

   int_vector_table[16 + EXTI9_5_IRQChannel] = (u32)&EXTI9_5_IRQHandler;

   int_vector_table[16 + EXTI1_IRQChannel] = (u32)&EXTI1_IRQHandler;

   int_vector_table[16 + EXTI4_IRQChannel] = (u32)&EXTI4_IRQHandler;

}

int main(void)

{

   ...

   NVIC_DeInit();

   init_interrupt_controller();

   // Set the Vector Table base location at

   SCB->VTOR = VECTOR_TABLE_ADD;

   // Configure the NVIC Preemption Priority Bits

   SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup_4;

}

Many thanks for your support

Posted on April 05, 2017 at 17:51

Ok, and what debugging have you done to refine 'doesn't work' ? Does it end up in the Hard Fault handler, or somewhere else. When you break execution where is the processor stuck?

The code doesn't look objectionable. I don't think I'd use at() to acheive this. Have you confirmed via the .MAP file that the linker successfully places the table address as expected?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 07, 2017 at 10:35

Hi Clive,

I managed. I didn't use the __attribute__(at()) and I allocated properly the table. I share with you the code:

Bootloader

&sharpdefine VECTOR_TABLE_LEN 64

__align(0x100) volatile u32 int_vector_table[VECTOR_TABLE_LEN];

void init_interrupt_controller(void)

{

   u8 int_number;

   for(int_number = 0; int_number < VECTOR_TABLE_LEN; int_number++)

   int_vector_table[int_number] = 0;

   int_vector_table[3] = (u32)&HardFaultException;

   int_vector_table[4] = (u32)&MemManageException;

   int_vector_table[15] = (u32)&SysTick_Handler;

   int_vector_table[16 + USB_LP_CAN_RX0_IRQChannel] = (u32)&USB_LP_CAN_RX0_IRQHandler;

}

int main(void)

{

...

// NVIC configuration

NVIC_DeInit();

init_interrupt_controller();

// Set the Vector Table base location at

SCB->VTOR = (u32)int_vector_table;//VECTOR_TABLE_ADD;

// Configure the NVIC Preemption Priority Bits

SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup_4;

...

if(Program_Code_flag == 0)

{

   // Test if user code is programmed starting from address 'ApplicationAddress'

   if(((*(vu32*)START_FLASH_APP_ADDRESS) & 0x2FFE0000 ) == 0x20000000)

   {

      SysTick->CTRL &= 0xFFFFFFFE;

      NVIC->ISER[0] = 0;

      // Jump to user application

      JumpAddress = *(vu32*) (START_FLASH_APP_ADDRESS + 4);

      Jump_To_Application = (pFunction) JumpAddress;

      // Initialize user application's Stack Pointer

      __set_MSP(*(vu32*) START_FLASH_APP_ADDRESS);

      Jump_To_Application();

   }

}

Application

&sharpdefine VECTOR_TABLE_LEN 64

__align(0x100) volatile u32 int_vector_table[VECTOR_TABLE_LEN];

void init_interrupt_controller(void)

{

   u8 int_number;

   for(int_number = 0; int_number < VECTOR_TABLE_LEN; int_number++)

   int_vector_table[int_number] = 0;

   int_vector_table[2] = (u32)&NMIException;

   int_vector_table[3] = (u32)&HardFaultException;

   int_vector_table[11] = (u32)&SVCHandler;

   int_vector_table[14] = (u32)&PendSVC;

   int_vector_table[15] = (u32)&SysTick_Handler;

   int_vector_table[16 + USB_LP_CAN_RX0_IRQChannel] = (u32)&USB_LP_CAN_RX0_IRQHandler;

   int_vector_table[16 + TIM2_IRQChannel] = (u32)&TIM2_IRQHandler;

   int_vector_table[16 + ADC1_2_IRQChannel] = (u32)&ADC1_2_IRQHandler;

   int_vector_table[16 + EXTI9_5_IRQChannel] = (u32)&EXTI9_5_IRQHandler;

   int_vector_table[16 + EXTI1_IRQChannel] = (u32)&EXTI1_IRQHandler;

   int_vector_table[16 + EXTI4_IRQChannel] = (u32)&EXTI4_IRQHandler;

}

int main(void)

{

   ...

   // NVIC configuration

   NVIC_DeInit();

   init_interrupt_controller();

   // Set the Vector Table base location at

   SCB->VTOR = (u32)int_vector_table;

   // Configure the NVIC Preemption Priority Bits

   SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup_4;

   ...

}

Thanks,

MS