Jumping from boot loader mode to application mode

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

Jumping from boot loader mode to application mode

Jump to solution
5,387 Views
kirtiraje
Contributor III

Hi,

I have written a boot loader and application code using KDS 3.2 for K64FN controller.
My boot loader starts at 0x00000000 and application starts at address 0x0000A000.

My boot loader is able to flash application (S19 file) in application area. After
firmware flashing, I am using below function to jump to application start -

APP_FLASH_VECTOR_START - 0x0000A000
UByte checkForUserApp(void)
{
uint32_t startup; /* assuming 32bit function pointers */
startup = ((uint32_t*)APP_FLASH_VECTOR_START); /* this is the reset vector (__startup function) */

if ((startup!=-1))
{
/* we do have a valid application vector? -1/0xfffffff would mean flash erased */
((void(*)(void))startup)(); /* Jump to application startup code */

}
}
I have also tried below code to jump to application but it is not able to jump to
0xA000 address.

UByte checkForUserApp(void)
{
__asm(" ldr r0, = 0xA000");

__asm(" ldr r1,[r0]"); // get the stack pointer value from the program's reset vector

__asm(" mov sp,r1"); // copy the value to the stack pointer

__asm(" ldr r0, = 0xA004"); // get the program counter value from the program's reset vector

__asm(" ldr r1,[r0]");

__asm(" blx r1"); // jump to the start address

}

The value at startup is 0xAB5D which is Program counter's value.

My issue is that, boot loader is not able to jump to application and is jumping to
thumb startup function.

did some one come across this scenario. Any help is appreciated.

Thanks,

Kirti

Labels (1)
0 Kudos
Reply
1 Solution
4,325 Views
mjbcswitzerland
Specialist V

Hi Kirti

The following code jumps to the application correctly (M4 processor).

// Allow the jump to a foreign application as if it were a reset (load SP and PC)
//
extern void start_application(unsigned long app_link_location)
{
    asm(" ldr r1, [r0,#0]");    // get the stack pointer value from the program's reset vector
    asm(" mov sp, r1");         // copy the value to the stack pointer
    asm(" ldr r0, [r0,#4]");    // get the program counter value from the program's reset vector
    asm(" blx r0");             // jump to the start address
}

Call with:

start_application(0xa000);

Note that the uTasker project includes serial loaders for the K64 (and most other Kinetis parts) which do one or multiple methods as follows:
- UART SREC, iHEX, KBOOT, AN2295 Developer's serial loader compatible
- USB-CDC (SREC, iHex)
- USB-HID AN4764 compatible
- USB-MSD binary, iHex, SREC
- USB memory stick
- SD card
- Modbus UART RTU/ASCII
- Modbus/TCP
- I2C
- Ethernet web server

These have been industrially verified in hundreds of different products over 6 years of Kinetis use and so ensure reliable performance without need to redevelop.
Builds with: CW10.x, KDS, MCUXpresso, IAR, Keil, Greenhills, Crossworks, CooCox, Atollic, S32 Design Studio, GNU Make and Visual Studio

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html
Kinetis K64:
- http://www.utasker.com/kinetis/FRDM-K64F.html
- http://www.utasker.com/kinetis/TWR-K64F120M.html
- http://www.utasker.com/kinetis/TEENSY_3.5.html
- http://www.utasker.com/kinetis/Hexiwear-K64F.html
Serial Loader: http://www.utasker.com/docs/uTasker/uTaskerSerialLoader.pdf


Free Open Source solution: https://github.com/uTasker/uTasker-Kinetis
Working project in 15 minutes video: https://youtu.be/K8ScSgpgQ6M

Professional Kinetis support, one-on-one training and complete fast-track project solutions: http://www.utasker.com/support.html

View solution in original post

15 Replies
4,325 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Kirti raje,

    You also can refer to our KBOOT2.0 for K64, this is the jump to application function:

static void jump_to_application(uint32_t applicationAddress, uint32_t stackPointer)
{
#if BL_FEATURE_OTFAD_MODULE
    quadspi_cache_clear();
    oftfad_resume_as_needed();
#endif

    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;

    // 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);
}

Wish it helps you!


Have a great day,
Kerry

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

0 Kudos
Reply
4,326 Views
mjbcswitzerland
Specialist V

Hi Kirti

The following code jumps to the application correctly (M4 processor).

// Allow the jump to a foreign application as if it were a reset (load SP and PC)
//
extern void start_application(unsigned long app_link_location)
{
    asm(" ldr r1, [r0,#0]");    // get the stack pointer value from the program's reset vector
    asm(" mov sp, r1");         // copy the value to the stack pointer
    asm(" ldr r0, [r0,#4]");    // get the program counter value from the program's reset vector
    asm(" blx r0");             // jump to the start address
}

Call with:

start_application(0xa000);

Note that the uTasker project includes serial loaders for the K64 (and most other Kinetis parts) which do one or multiple methods as follows:
- UART SREC, iHEX, KBOOT, AN2295 Developer's serial loader compatible
- USB-CDC (SREC, iHex)
- USB-HID AN4764 compatible
- USB-MSD binary, iHex, SREC
- USB memory stick
- SD card
- Modbus UART RTU/ASCII
- Modbus/TCP
- I2C
- Ethernet web server

These have been industrially verified in hundreds of different products over 6 years of Kinetis use and so ensure reliable performance without need to redevelop.
Builds with: CW10.x, KDS, MCUXpresso, IAR, Keil, Greenhills, Crossworks, CooCox, Atollic, S32 Design Studio, GNU Make and Visual Studio

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html
Kinetis K64:
- http://www.utasker.com/kinetis/FRDM-K64F.html
- http://www.utasker.com/kinetis/TWR-K64F120M.html
- http://www.utasker.com/kinetis/TEENSY_3.5.html
- http://www.utasker.com/kinetis/Hexiwear-K64F.html
Serial Loader: http://www.utasker.com/docs/uTasker/uTaskerSerialLoader.pdf


Free Open Source solution: https://github.com/uTasker/uTasker-Kinetis
Working project in 15 minutes video: https://youtu.be/K8ScSgpgQ6M

Professional Kinetis support, one-on-one training and complete fast-track project solutions: http://www.utasker.com/support.html

4,325 Views
kirtiraje
Contributor III

Hi Mark,

I have implemented extern void start_application(unsigned long app_link_location) function,still it is jumping to _thumb_startup()  in startup.c file. Please have a look at attached screenshot.

BL_to_app_jump_issue.png

0 Kudos
Reply
4,325 Views
kirtiraje
Contributor III

Hi Mark,

I did debug in single step in disassemble mode and my SP is getting loaded with 0x20000000 and PC with 0xab5d. It is jumping into application but after execution of instruction at address 0xA28c it is switching from application to thumb_start() function of boot loader startup.c. Below are the screenshots showing 0x20000000 loaded in SP in image1,  it is jumping to application in image2, and again switched to boot loader thumb_startup().1.jpg2.jpg3.jpg

I am using KDS 3.2 and openSDA to debug the boot loader. 

Can you help me to find out what could be wrong at  address 0xA28c, so that it get redirected again to boot loader. 

 

0 Kudos
Reply
4,325 Views
kirtiraje
Contributor III

Hi Mark ,

I did debug the application code. At address 0xA28c in application code is the watchdog reset instruction in init_hardware(), you can see that in the below screenshot.4.jpg

When I debug application, It is properly running the application. As I said while running boot loader mode, it is jumping to application and then at address 0xA28c it is again switching to boot loader thumb start function. Can any one help me in finding the solution.

0 Kudos
Reply
4,325 Views
mjbcswitzerland
Specialist V

Kirti

It looks like the watchdog unlock code is too slow.


When unlocking the watchdog for modification the keys needs to be written quickly otherwise the watchdog will reset (to protect the system against watchdog manipulation). I have seen similar issue in Teensy watchdog code which works after a reset but not later (when the clock is running at full speed).

Since you have disabled the watchdog in the loader code (if the same as the code you show) you could just remove the same code from the application so that it doesn't disturb.

Otherwise, build the code with full optimisation to make it faster. Or replace the code with assembler to ensure to avoid the inefficient accesses that are presently being performed (load the two key values to two registers and then write the two registers to the watchdog registers immediately after each other).


Finally, ensure that interrupts are disabled at this point to avoid the unlock sequence from potentially being interrupted.

Regards

Mark

0 Kudos
Reply
4,325 Views
kirtiraje
Contributor III

Hi Mark,

I have commented the watchdog disable code which is there in cpu_init.c file of application code 

The code I have commented is -

// #if STARTUP_WDOG
// WDOG_UNLOCK = (uint16_t)STARTUP_WDOG_KEY_1; /* Key 1 */
// WDOG_UNLOCK = (uint16_t)STARTUP_WDOG_KEY_2; /* Key 2 */
// WDOG_STCTRLH = (uint16_t)STARTUP_WDOG_STCTRLH_VALUE; /* Disable WDOG */
// #endif /* STARTUP_WDOG */

I did disable the interrupts.

Then I did debug the application, but It did not run the application (LED blink)  (not from boot loader code).

If I uncomment the above code then the application runs fine (not from boot loader code).

Please let me know your comments on this.

Thanks,

Kirti

0 Kudos
Reply
4,325 Views
mjbcswitzerland
Specialist V


Kirti

If it is not the watchdog code I don't have any other ideas at the moment (there are many reasons why application code is not compatible with a boot loader but not all are evident from a screen shot).

If you need a fast solution you could just use the uTasker open source project which has a mature SREC loader included in it which may solve your issues.

In case you need to use other solutions I can fix it for you in your code but you will need to make a service request at http://www.utasker.com/support.html

Regards

Mark

0 Kudos
Reply
4,325 Views
kirtiraje
Contributor III

Hi Mark,

Thank you for your help. It was not the watchdog reset issue.( I was debugging the WDOG_UNLOCK keys switching and it got reset)

Now, I am able to jump to application mode successfully and the LED is switched ON (as my application is to blink LED in 1 sec interrupt). But it is not toggling. I have disabled all interrupts, timers in boot loader code before switching to application mode.  

Can you help me in this.

Thank you,

Kirti

0 Kudos
Reply
4,325 Views
mjbcswitzerland
Specialist V

Kirti

Is sounds as though your interrupt are not yet operating in the application.

Go through the check list in the appendix of the uTasker serial loader document to verify application compatibility with boot loaders.

Regards

Mark

0 Kudos
Reply
4,325 Views
kirtiraje
Contributor III

Hi Mark,

As I told you , I am able to jump to application mode from boot loader. I have added the LED blinking code in main function without using interrupts. It is running fine but could not enable the timer interrupt. I did disable all the interrupts in boot loader mode before switching to application and enabled in application code. I am still looking into it. If you find any clue please let me know.

I have one doubt about the flash configuration memory. Do I need to allocate memory for flash configuration (10 bytes) in application too. As I have already allocated that memory in boot loader.

Thanks,

Kirti

0 Kudos
Reply
4,325 Views
mjbcswitzerland
Specialist V

Kirti

Flash configuration in the application is redundant - only the boot loader can determine the values in Flash at 0x400..0x40f.

Regards

Mark

4,325 Views
kirtiraje
Contributor III

Hi Mark,

After a long try, finally my boot loader worked fine and it is flashing the application image properly and running the application. Now all the interrupts are also enabled in application. 

As my application was running without interrupt but interrupts was not getting enabled. The problem was , I did disable the cpu interruputs by calling Cpu_DisableInt() function in boot loader code but did not enable that Cpu interrupts in application code. After adding the Cpu_EnableInt() function in my application code my interrupts enabled. 

Thanks a lot for helping me to solve this issue..Your comments helped me to get in right direction to solve the issue.

I really appreciate  your help.

Thank you,

Kirti

0 Kudos
Reply
4,325 Views
kirtiraje
Contributor III

Okay.. Thank you Mark..

0 Kudos
Reply
4,325 Views
mjbcswitzerland
Specialist V

Kirti

I see that you have 0xab5d at 0xa004 and so I expect it to jump to here.
You need to single step the jmp code and check that 0x20000000 is really in the SP before the jump takes place.
Single step in disassemble mode since the debugger may otherwise become confused when it tries to follow using source level debugging.

Regards

Mark

0 Kudos
Reply