Hello Everybody,
I'm using KBoot 1.2.0 sample project for the FRDM-K64F on my FRDM-K64F.
I am working on editing kboot to launch between two applications at 2 different addresses.
I can boot to the default location, but not the 2nd. I'm missing something here, but I am not sure what.
Currently,
vector_table_info.h:
//! @brief Pointer to the bootloader vector table, which is always at address 0.
APP_VECTOR_TABLE = ((uint32_t *)kDefaultVectorTableAddress)
This works for the default app location of 0xA000.
When sw2 is active, I change my application address from 0x0000A000 to 0x0002A000, the location of my second app.
Both App1 and App2 are in flash memory and are not interfering with each other in flash.
My Problem, I think, happens here when trying to boot to the other application
bootloader.c:
// Set the VTOR to the application vector table address.
SCB->VTOR = (uint32_t)APP_VECTOR_TABLE;
// Set stack pointers to the application stack pointer.
__set_MSP(s_stackPointer);
__set_PSP(s_stackPointer);
I have a feeling APP_VECTOR_TABLE needs to reflect my application's vector table.
Also, BL_TARGET_FLASH is defined in the preprocessor but I don't see the #if statements responding correctly.
Thank you,
Jason Philippi
Hi Jason,
I'd like to suggest an approach to jump two different application code possible.
In the freedom_bootloader demo for FRDM-K64F, in the bootloader.c, you can add second application code address in the get_user_application_entry(uint32_t *appEntry, uint32_t *appStack) function.
In this function, the default application code is 0xa000, definitely you can add another one for more options.
After down that, it can make it.
//! For flash-resident and rom-resident target, gets the user application address
//! and stack pointer from the APP_VECTOR_TABLE.
//! Ram-resident version does not support jumping to application address.
static void get_user_application_entry(uint32_t *appEntry, uint32_t *appStack)
{
assert(appEntry);
assert(appStack);
#if BL_TARGET_RAM
*appEntry = NULL;
*appStack = NULL;
#else
*appEntry = APP_VECTOR_TABLE[kInitialPC];
*appStack = APP_VECTOR_TABLE[kInitialSP];
#endif
}
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello,
For some reason, I can't get APP_VECTOR_TABLE to equal BL_APP_VECTOR_TABLE_ADDRESS instead of kDefaultVectorTableAddress in vector_table_info.h
I tried your suggested change, but I'm just testing the location of the second app without any switching logic.
Hopefully this is what you meant.
static void get_user_application_entry(uint32_t *appEntry, uint32_t *appStack)
{
assert(appEntry);
assert(appStack);
#if BL_TARGET_RAM
*appEntry = NULL;
*appStack = NULL;
#else
// *appEntry = APP_VECTOR_TABLE[kInitialPC];
// *appStack = APP_VECTOR_TABLE[kInitialSP];
*appEntry = ((uint32_t *)0x0002a000)[kInitialPC];
*appStack = ((uint32_t *)0x0002a000)[kInitialSP];
#endif
}
When debugging, I noticed something funny.
appEntry = 0xa4c9 (k64f thumb)
stackPointer = 0x2003_0000
I expected
appEntry = 0x0002_a4c9 (k64f thumb)
stackPointer = 0x2003_0000
It booted to my first application @ 0xa000
So I changed the line about the VTOR that reflects my problem with APP_VECTOR_TABLE, and still booted to the first application.
static void jump_to_application(uint32_t applicationAddress, uint32_t stackPointer)
{
shutdown_cleanup(kShutdownType_Shutdown);
// Create the function call to the user application.
// Static variables are needed since changed the stack pointer out from under the compiler
// we need to ensure the values we are using are not stored on the previous stack
static uint32_t s_stackPointer = 0;
s_stackPointer = stackPointer;
static void (*farewellBootloader)(void) = 0;
farewellBootloader = (void (*)(void))applicationAddress;
// Set the VTOR to the application vector table address.
// SCB->VTOR = (uint32_t)APP_VECTOR_TABLE;
// SCB->VTOR = (uint32_t)BL_APP2_VECTOR_TABLE_ADDRESS;
SCB->VTOR = (uint32_t)((uint32_t *)0x0002a000);
// Set stack pointers to the application stack pointer.
__set_MSP(s_stackPointer);
__set_PSP(s_stackPointer);
// Jump to the application.
farewellBootloader();
// Dummy fcuntion call, should never go to this fcuntion call
shutdown_cleanup(kShutdownType_Shutdown);
}
My thought is, both binaries were compiled for the same fixed address.
Thus, the address it is getting from that location is original address 0xa000 + whatever.
Can I change my linker to handle relative placement?
Thank you,
Jason
--EDIT--
I changed the start address in APP2 binary in the linker, and it jumped to the right application.
Now I would need to make sure both apps are relative, since my applications will be flashed ether at 0x0002_A000 or 0x0000_0000.
Hi Jason,
Let's me make it more clearly.
First of all, you can find the BL_TARGET_FLASH is defined as the Fig 1 shows.
For jump the jump the second application, at first, you should add another application address in the bootloader_config.h, meanwhile add another application vector table in the vector_table_info.h too as below.
Next, in the get_user_application_entry() and jump_to_application() functions, you should add if-else to select which application to jump as below.
The linker file also need to be modified for the jumping successful and I've attached an application note, in this application note, you can learn the way of modifying linker file.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Fig 1
// The bootloader will check this address for the application vector table upon startup.
#if !defined(BL_APP_VECTOR_TABLE_ADDRESS)
#define BL_APP_VECTOR_TABLE_ADDRESS 0xa000
#define BL_Second_APP_VECTOR_TABLE_ADDRESS 0x2a000
#endif
#if (BL_TARGET_FLASH)
//! @brief Pointer to the application vector table, which is always at the
//! end of the bootloader region in flash.
#define APP_VECTOR_TABLE ((uint32_t *)BL_APP_VECTOR_TABLE_ADDRESS)
#define Second_APP_VECTOR_TABLE ((uint32_t *)BL_Second_APP_VECTOR_TABLE_ADDRESS)
#else
//! @brief Pointer to the bootloader vector table, which is always at address 0.
#define APP_VECTOR_TABLE ((uint32_t *)kDefaultVectorTableAddress)
#endif
static void get_user_application_entry(uint32_t *appEntry, uint32_t *appStack)
{
assert(appEntry);
assert(appStack);
#if BL_TARGET_RAM
*appEntry = NULL;
*appStack = NULL;
#else
if(SW is active)
*appEntry = APP_VECTOR_TABLE[kInitialPC];
*appStack = APP_VECTOR_TABLE[kInitialSP];
else
*appEntry = Second_APP_VECTOR_TABLE[kInitialPC];
*appStack = Second_APP_VECTOR_TABLE[kInitialSP];
#endif
}
static void jump_to_application(uint32_t applicationAddress, uint32_t stackPointer)
{
shutdown_cleanup(kShutdownType_Shutdown);
// Create the function call to the user application.
// Static variables are needed since changed the stack pointer out from under the compiler
// we need to ensure the values we are using are not stored on the previous stack
static uint32_t s_stackPointer = 0;
s_stackPointer = stackPointer;
static void (*farewellBootloader)(void) = 0;
farewellBootloader = (void (*)(void))applicationAddress;
// Set the VTOR to the application vector table address.
SCB->VTOR = (uint32_t)APP_VECTOR_TABLE;
if(SW is active)
SCB->VTOR = (uint32_t)APP_VECTOR_TABLE;
else
SCB->VTOR = (uint32_t)Second_APP_VECTOR_TABLE;
// Set stack pointers to the application stack pointer.
__set_MSP(s_stackPointer);
__set_PSP(s_stackPointer);
// Jump to the application.
farewellBootloader();
// Dummy fcuntion call, should never go to this fcuntion call
shutdown_cleanup(kShutdownType_Shutdown);
}
That's about what I have but with some names changed.
For some reason, BL_TARGET_FLASH is still not taking in KDS 3.0.0
Note below APP_VECTOR_TABLE and APP2_VECTOR_TABLE are grayed out.
Because I wanted to place the code in either slot, I had to make it Position independent.
Project -> Properties -> C/C++ Build -> Settings -> Tool Settings -> Optimization -> Position independent code.
Now since the binary was position independent, I had to add my offset to the bootloader.
PIC appEntry + sector offset = actual appEntry
0x0000_A4C9 + 0x0002_0000 = 0x0002_A4C9
bootloader_config.h
// Size of each application sector
#if !defined(BL_APP_SECTOR_SIZE)
#define BL_APP_SECTOR_SIZE 0x00020000
#endif
// The bootloader will check this address for the application vector table upon startup.
#if !defined(BL_APP_VECTOR_TABLE_ADDRESS)
#define BL_APP_VECTOR_TABLE_ADDRESS 0xa000
#define BL_APP2_VECTOR_TABLE_ADDRESS (BL_APP_VECTOR_TABLE_ADDRESS + BL_APP_SECTOR_SIZE)
#endif
bootloader.c
static void get_user_application_entry(uint32_t *appEntry, uint32_t *appStack)
{
assert(appEntry);
assert(appStack);
#if BL_TARGET_RAM
*appEntry = NULL;
*appStack = NULL;
#else
// *appEntry = APP_VECTOR_TABLE[kInitialPC];
// *appStack = APP_VECTOR_TABLE[kInitialSP];
if(activeApplication == 0x00)
{
*appEntry = ((uint32_t *)0x0000a000)[kInitialPC];
*appStack = ((uint32_t *)0x0000a000)[kInitialSP];
}
else
{
//BL_APP_SECTOR_SIZE 0x00020000 from bootloader_config.h
*appEntry = ((uint32_t *)0x0002a000)[kInitialPC] + BL_APP_SECTOR_SIZE;
*appStack = ((uint32_t *)0x0002a000)[kInitialSP];
}
//I will change this over when BL_TARGET_FLASH behaves
// if(activeApplication == 0x00)
// {
// *appEntry = APP_VECTOR_TABLE[kInitialPC];
// *appStack = APP_VECTOR_TABLE[kInitialSP];
// }
// else
// {
// *appEntry = APP2_VECTOR_TABLE{kInitialPC] + BL_APP_SECTOR_SIZE;
// *appStack = APP2_VECTOR_TABLE[kInitialSP];
// }
#endif
}
This all works great in debug.
The only issue is I can't let go of the switch fast enough before the bootloader thinks SW2 is a peripheral. But I can figure that out. SW2 is just being used to prove the first stage of my edit.