2017-04-03 10:00 AM
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:
SysTick_Handler,
USB_LP_CAN_RX0_IRQHandler,
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-table2017-04-03 10:30 AM
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.
2017-04-04 09:08 AM
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
2017-04-04 11:45 AM
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.
2017-04-05 04:34 AM
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_Handlerand 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
2017-04-05 10:51 AM
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?
2017-04-07 03:35 AM
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