How to relocate interrupt vector table in MCUXpresso

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to relocate interrupt vector table in MCUXpresso

Jump to solution
17,936 Views
MAPC
Senior Contributor I

Hello,

Could anybody explain me how to relocate vector table in MCUXpresso? In MCU Settings, there is not a place where we can reconfigure interrupts area allocation. In KDS, it was possible to do this, by editing m_interrupts section in linker file directly. My MCU is a MK64FN1M0.

Thanks and best regards,

Marco Coelho

DFAE - Siletec Eletronica

1 Solution
11,975 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Marco,

I tested vector relocation on my side today. with my solution it also works. I was aware you already solved your problem with our expert LPCX support. So I am just for sharing my way. :-)

I currently don't have k64 bootloader. so I test your problem with KL25 bootloader I developed two years ago. I use this code for test because I am familiar with this bootloader code/

Kinetis Bootloader to Update Multiple Devices in a Network - for Cortex-M0+ 

then I use MCUXpresso to develop application code. here is my steps:

1. under MCUXpresso, create a new demo based on sdk sample, make sure you disable semihost and avoid any printf code in your app code.

2. relocate app code. for example in my demo I relocate it to 0x1000

pastedImage_2.png

3.  make sure VTOR is well set

SCB->VTOR = 0x1000;

4. Make sure the relocated application code start address is well aligned to the relocation flash sector start address. For example, this is my case. I relocate app code start address from 0x1000.

2017-06-23_17-48-59.jpg

after above change, the app code with vector relocation works perfect on my side.

I have verified it on my FRDM-KL25 board. But I think the method is the same for K64.


Have a great day,
Jennie Zhang

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

18 Replies
11,975 Views
ypkdani
Contributor III

Hello,

i have a problem to set the application using the bootloader. 

I have change the memory allocation to copy the interrupt to the ram

pastedImage_1.png

add the line

// Insert call to copy vector table to RAM
data_init(0x0, 0x2000fc00, 0x400);

 

to ResetISR()

and re-set the handler 

Install_RAM_Handler(UART4_RX_TX_IRQn, (uint32_t)UART4_RX_TX_IRQHandler);
Install_RAM_Handler(UART0_RX_TX_IRQn, (uint32_t)UART0_RX_TX_IRQHandler);
Install_RAM_Handler(PORTC_IRQn, (uint32_t)PORTC_IRQHandler);
Install_RAM_Handler(PORTD_IRQn, (uint32_t)PORTD_IRQHandler);
Install_RAM_Handler(LPTMR0_IRQn, (uint32_t)LPTMR0_IRQHandler);
Install_RAM_Handler(LLWU_IRQn, (uint32_t)LLWU_IRQHandler);

insted in the function 

/*
* DC2
* 19/01/18
* Chiamata per riallocare gli interrupt in RAM
*/
void Install_RAM_Handler (IRQn_Type irq, uint32_t irqHandler) {
extern uint32_t __RAM_VECTOR[]; // taken from linker script
__disable_irq();
__RAM_VECTOR [irq+16] = irqHandler;
SCB->VTOR = (uint32_t)&__RAM_VECTOR;
__enable_irq();
}

i have a problem with the definition of __RAM_VECTOR[]. The compilare say undefined reference to `__RAM_VECTOR'. 

Thanks

PS:

i have to change the setting

pastedImage_4.png

too?

11,975 Views
MAPC
Senior Contributor I

Hello LPCX support and Jennie Zhang

I just found out what was causing the interrupt demo codes not to work with my bootloader. According to ARM Cortex M4 manual avialable at http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/DUI0553A_cortex_m4_dgug.pdf , SCB->VTOR is defined as the following:

pastedImage_2.png

So, in my code I loaded SCB->VTOR register with my application Flash start address shifted by 7 bits to the left, but that caused the MCU to reset and I didn't know why. So, after seeing the Jennie's message, I suspected that I should load that register with the value itself, and not shifted by 7 bits to the left. After doing that, everything is up and running!

But I'm still intrigued why MCUXpresso doesn't change SCB->VTOR register value automatically according to Program Flash address entered in Memory Configuration Editor. That sounds strange to me. In KDS demos, I didn't need to change SCB->VTOR register value in the code, what leads me to suspect, not to affirm because I haven't checked it yet, that Kinetis Design Studio already changes SCB->VTOR register according to linker file configuration in startup code and that is why we don't need to change SCB->VTOR value in code.

Your answer was decisive and enlightening, Jennie! Thank you very much!

I'd like to thank LPCX support for the first approach that copies the vector table to RAM. It is very interesting and could be useful in some cases.

Best regards!

Marco Coelho

DFAE - Siletec Eletronica 

11,975 Views
lpcxpresso_supp
NXP Employee
NXP Employee

So your original post made no mention of a bootloader =>I assumed that you were just wanting to move the vector table from Flash to RAM.

If all you are wanting to do is build at image at a non-zero address, then move the FLASH region in the memory configuration up to the required address (and reduce its size to offset that).

You should be careful about what address you use for the new start of the FLASH region though .. make sure it is aligned with the start of a flash sector (to prevent issues with erasing/programming the flash).

Regards,

MCUXpresso IDE Support

11,975 Views
MAPC
Senior Contributor I

Hello, LPCX support

I had already done that. My application's Flash start address is 0x18000. I have set Flash start and size in Memory Configuration Editor accordingly. The printf messages simply don't display in the Terminal. In the case, I tested MCUXpresso SDK frdmk64f_driver_examples_adc16_interrupt and frdmk64f_driver_examples_gpio_input_interrupt. With demo codes without interrupt like MCUXpresso SDK frdmk64f_driver_examples_gpio_led_output and frdmk64f_driver_examples_adc16_polling, printf messages are displayed normally in the Terminal and I can see the applications running fine.

Can you tell me how I can configure MCUXpresso to debug my bootloader and application codes together? In KDS, there is a tutorial posted in this Community: Debugging Bootloader and Application using Kinetis Design Studio. I tried to do this with .axf file, but it didn't work (there may be differences). Therefore, I could run everything line by line and try to find out where it is failing.

It is weird because with the approach to copy vector table to RAM, everything runs perfectly, demos with or without interrupts, including "printf" messages that are displayed in Terminal.

Regards,

Marco Coelho

DFAE - Siletec Eletronica

11,975 Views
lpcxpresso_supp
NXP Employee
NXP Employee

This is pretty straight forward to do - as follows ....

First of all use the memory configuration editor (detailed in the MCUXpresso IDE User Guide, chapter 12, "Memory Configuration and Linker Scripts") to split one of the RAM banks into two, one of which we will use to store the RAM copy of the vector table in. The start address of this RAM bank needs to be carefully aligned though, as the NVIC's VTOR register will need to be set to point to it (as described in ARM's documentation - for instance for Cortex-M4 at ARM Information Center  ).

So in the case of my FRDM-K64 project, I take the standard memory configuration:

DefaultMem.png

and split SRAM_UPPER to produce a second bank called RAM_VECTORS of the appropriate size, and moved this to the end of the list:

MemRAMVectors.png

Note that the size of this bank is 0x400, and that is the maximum size possible for Cortex-M4 of the vector table (though generally not all 0x400 bytes are actually needed in most MCUs).

Now modify the startup file to add an extra call in ResetISR() to the data_init() function thus:

// Copy the data sections from flash to SRAM.
 while (SectionTableAddr < &__data_section_table_end) {
 LoadAddr = *SectionTableAddr++;
 ExeAddr = *SectionTableAddr++;
 SectionLen = *SectionTableAddr++;
 data_init(LoadAddr, ExeAddr, SectionLen);
 }

// At this point, SectionTableAddr = &__bss_section_table;
 // Zero fill the bss segment
 while (SectionTableAddr < &__bss_section_table_end) {
 ExeAddr = *SectionTableAddr++;
 SectionLen = *SectionTableAddr++;
 bss_init(ExeAddr, SectionLen);
 }

// Insert call to copy vector table to RAM
data_init(0x0, 0x2002fc00, 0x400);

Now add a function to your code to modify one of the interrupt handlers in the RAM copy of the vector table, and update the VTOR register to point to the RAM block:

void Install_RAM_Handler (IRQn_Type irq, uint32_t irqHandler) {
  extern uint32_t __base_RAM_VECTORS[]; // taken from linker script
  __disable_irq();
  __base_RAM_VECTORS [irq+16] = irqHandler;
  SCB->VTOR = (uint32_t)&__base_RAM_VECTORS;
  __enable_irq();
}

And then add a call to your main code to install the required handler into the correct entry of the vector table

Install_RAM_Handler(I2C0_IRQn, (uint32_t)My_I2C0_IRQHandler);

More details of the vector table layout can be found in the ARM docs at - ARM Information Center 

Regards,

MCUXpresso IDE Support

11,975 Views
MAPC
Senior Contributor I

Hello, LPCX support

I'm glad to inform you that your tips worked perfectly. Now I can load MCUXpresso application codes with interrupt through my bootloader as well. Thank you very much! I would never do it without your help!

But, I need to persist with two questions:

1) Why do KDS application codes work without this approach?

2) Do I really need to waste 1KB of RAM memory to allocate the vector table? Isn't it possible to allocate it directly in the start of application's Program Flash area?

Best regards,

Marco Coelho

DFAE - Siletec Eletronica

11,975 Views
MAPC
Senior Contributor I

Hi, LPCX support

Thanks for attention.

That makes me confused. When I use KDS SDK 2.0 application codes which have interrupts, I don't need to copy vector table to RAM and set SCB->VTOR. My bootloader just jumps to application and runs perfectly. Can you explain me that? I only have issues with MCUXpresso SDK 2.2 demo codes that have interrupts.

And why do I have to allocate vector table in RAM? Isn't it possible to relocate the vector table to the application's Program Flash instead of RAM?

Just to notice that my bootloader was built in MCUXpresso.

Thanks! 

11,975 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Marco,

We can edit MCUXpresso project linker file with "Memory configuration editor".

The Memory Editor is accessed via the MCU settings dialog, which can be found at
Project Properties -> C/C++ Build -> MCU settings

the detailed information is already well described in document MCUXpresso_IDE_User_Guide.pdf, Chapter 12. we can customized our own linker file with it.

There is an option to disable "manage linker script", but it is not recommended.

pastedImage_2.png


Have a great day,
Jennie Zhang

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

11,975 Views
MAPC
Senior Contributor I

Hello, Dear ZhangJennie

I have already modified the start address of my application Program Flash in Memory Configuration Editor and disabled automatic placement of Flash Configuration Field in image (since it is already defined in my bootloader Flash portion), but it didn't work. When I load my application Flash with my application code, it runs the application,  but it looks like it doesn't recognize interrupts somehow.

I have tested my (customized) bootloader with SDK demo codes "frdmk64f_driver_examples_adc16_interrupt" and "frdmk64f_driver_examples_gpio_input_interrupt". Both are successfully written into application Flash memory, but they don't run properly.

The "frdmk64f_driver_examples_adc16_interrupt" while loop is:

while (1)
{
GETCHAR();
g_Adc16ConversionDoneFlag = false;

ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
while (!g_Adc16ConversionDoneFlag)
{
}
PRINTF("ADC Value: %d\r\n", g_Adc16ConversionValue);
PRINTF("ADC Interrupt Count: %d\r\n", g_Adc16InterruptCounter);
}

One of the tests I have done was removing the lines relating "ADC16_SetChannelConfig" function call and "while(!g_Adc16ConversionDoneFlag){}". After that, when I press any key from PC, the two messages are displayed in the Terminal. On the other hand, if I leave the code as it is, the introduction messages are displayed, but the other messages printed in while loop, are not, no matter the key pressed in PC.

The "frdmk64f_driver_examples_gpio_input_interrupt" doesn't work as well. But, if my bootloader loads demo codes without any interrupts like "frdmk64f_driver_examples_adc16_polling" or "frdmk64f_driver_examples_gpio_led_output", they run perfectly without issues and perfectly loads and runs application codes that were built in KDS (with or without interrupts), what leads me to suspect that the interrupts, somehow, were not correctly relocated to the new Program Flash address in application codes in MCUXpresso.

I don't know how the vector table is allocated by MCUXpresso. In KDS, as I said previously, we have a "m_interrupts" section in the linker, where we can modify its starting address. In MCUXpresso, we just have Program Flash. I believe that it is because it already considers the start of vector table area as the start of Program Flash.

I tried to expose my issue as clearly as possible, but if I was not clear enough, please let me know! Can you give me a helping hand on this please?

Thanks and best regards,

Marco Coelho

DFAE - Siletec Eletronica

11,975 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Siletec.

Please check if you set vector table offset register.

 SCB->VTOR = <vector redirection address>;

If you already set but still can not work, pls let me know. I will test it with a board when I arrive office tomorrow.

Have a great day,
Jennie Zhang

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

11,975 Views
MAPC
Senior Contributor I

ZhangJennie,

Just to add to my previous comment, for interrupt application codes compiled in KDS, it works without setting SCB->VTOR, but not for interrupt application codes compiled in MCUXpresso. And, my bootloader was built in MCUXpresso. 

11,976 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Marco,

I tested vector relocation on my side today. with my solution it also works. I was aware you already solved your problem with our expert LPCX support. So I am just for sharing my way. :-)

I currently don't have k64 bootloader. so I test your problem with KL25 bootloader I developed two years ago. I use this code for test because I am familiar with this bootloader code/

Kinetis Bootloader to Update Multiple Devices in a Network - for Cortex-M0+ 

then I use MCUXpresso to develop application code. here is my steps:

1. under MCUXpresso, create a new demo based on sdk sample, make sure you disable semihost and avoid any printf code in your app code.

2. relocate app code. for example in my demo I relocate it to 0x1000

pastedImage_2.png

3.  make sure VTOR is well set

SCB->VTOR = 0x1000;

4. Make sure the relocated application code start address is well aligned to the relocation flash sector start address. For example, this is my case. I relocate app code start address from 0x1000.

2017-06-23_17-48-59.jpg

after above change, the app code with vector relocation works perfect on my side.

I have verified it on my FRDM-KL25 board. But I think the method is the same for K64.


Have a great day,
Jennie Zhang

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

11,975 Views
rans
Senior Contributor I

Hello Jennie ,

How can we verify that interrupt relocation is OK ?

Thank you,

ranran

11,975 Views
jeremyanderson
Contributor III

I've read this subject thread because we are using MCUXpresso and the SDK with the FRDM_K66 board and would like to install a custom bootloader at address 0x0 in Program Flash.  To do this we have to move program flash and that means we have to deal with the application vector table being in a new location.  I have the same question as the originator of the thread concerning why the vector table is not found by default in relation to the base of Program Flash.  But more important for us right now is that we are unable to get the debugger to execute our application.

We have done the following:

1. Change program flash to start at 0x1000 and changed length to 0x1ff000

2. Add a statement at beginning of main() function SCB->VTOR = 0x1000;

The compile works fine, but execution ends with 'No source available for "__sys_appexit() at 0x69e0"'

Have we attempted something obviously wrong here or is more information needed?

11,975 Views
geoff_s
Contributor III

I am attempting similar things to Marco and also having some problems with interrupts.  Should the modification of the vector table offset register (SCB->VTOR = 0x1000;) be performed as the last step in the bootloader before jumping to the main user application, or as part of the startup code for the user application?

11,975 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Geoff,

Sure. It's  OK.

Best Regards,

Jennie Zhang

11,975 Views
MAPC
Senior Contributor I

Hi, ZhangJennie

I had tried to do like you did and it didn't work. Please see the details in my last answer to LPCX support.

Thanks!

Marco Coelho

DFAE - Siletec Eletronica

11,975 Views
MAPC
Senior Contributor I

Yes, ZhangJennie

I have already tried this in my application code, in case I used "frdmk64f_driver_examples_adc16_interrupt" as an example and inserted an offset to Program Flash starting address in Memory Configuration Editor. What is the correct point to put this line? I tried in the beginning of main function, but it is causing a reset. I double checked SCB->VTOR is debugger and it is correct.

 

I wait for your test.

Best regards,

Marco Coelho

DFAE - Siletec Eletronica