Jump to ROM bootloader from application in i.MX RT1010

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

Jump to ROM bootloader from application in i.MX RT1010

Jump to solution
2,795 Views
MKlem
Contributor III

Hello all,

In the reference manual of the MIMXRT1011CAE4A, chapter 9.10 ROM APIs there is an example on how to jump back to the bootloader with an argument. 

My application is running FreeRTOS.

I'm looking to update the firmware in the flash through the USB cable. With the USB cable attached, my application code emulates a VCP. Then when I'm sending the jumpToBootloader command, it executes this:

typedef struct 
{ 
 const uint32_t version; //!< Bootloader version number 
 const char *copyright; //!< Bootloader Copyright 
 void (*runBootloader)(void *arg); //!< Function to start the bootloader executing 
 const uint32_t *reserved0; //!< Reserved 
 const uint32_t *reserved1; //!< Reserved 
} bootloader_api_entry_t; 
#define g_bootloaderTree (*(bootloader_api_entry_t**)(0x0020001c)) 

void runBootloader(void* arg) 
{ 
  g_bootloaderTree-> runBootloader(arg); 
} 

void jumpToBootloader(void){
  uint32_t arg = 0xeb100000; 
  runBootloader (&arg); 
}

 

All that happens is the "Windows disconnect sound", the LCD goes blank (device resets?) and then it's stuck. No new hardware is found. Once, I got the "Device Descriptor Request failed" error, but most of the time nothing. 

 

Should this code be in a critical entry? 

 

Thanks for any help!

 

Marcel

0 Kudos
Reply
1 Solution
2,511 Views
MKlem
Contributor III

Hello Diego,

Thanks for your reply. I've made a workaround because of time limits.

Now, when the jumpToBootloader function is called, it writes a flag into the external EEPROM. 

The user is now requested to restart the device (a reset might work now, too!). 

On boot the EEPROM is read before starting the scheduler. If the flag is set, the bootloader is called and everything works as expected. 

Thanks anyway for your help. I hope someone else might find this usefull.

 

Marcel

View solution in original post

0 Kudos
Reply
10 Replies
2,781 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hi @MKlem 

I hope you are doing well! 

I do not know which pins are you using for USB. Or if you manually set the MCU into serial downloader mode you are able to see enumeration of USB port. Please detail this.

I suggest you to  do a ping using LPUART1 pins instead after calling the runBootloader API. By ping I refer to send this command ( sdphost -p COMxx,115200 -j -- error-status ) using SDPHOST. 

 

 diego_charles_0-1689019580590.png

 

UART or USB connection with the MCU during serial downloader mode can be done with the MCUxpresso Secure Provisioning Tool with ease. So you do not need to write down  UART or USB SDPHOST commands.

diego_charles_1-1689020085696.png

 

The other way arround to check if there is any issue with the Jump to the bootloader is by halting the MCU and reading processor registers via SWD, if possible.

I am not sure , if the code should be in a critical entry, but it may be convenient to disable any interrupts before calling the API. 

All the best, 

Diego.

0 Kudos
Reply
2,696 Views
MKlem
Contributor III

Hello Diego,

I have put a breakpoint on the jump "g_bootloaderTree-> runBootloader(arg);". 

With the debugger, I jumped in. The stack trace now shows this:

MKlem_0-1689247534723.png

Also a hard fault is reported.

Looking in the disassembly window:

MKlem_1-1689247940229.png

When resetting BEFORE entering the bootloader (so resetting when the breakpoint has triggered), it works?

MKlem_4-1689248797048.png

Is it because the value of the arg might be loaded, and resetting causes this to trigger it? 

 

I'll try some more things and let you know when I am getting somewhere.

 

Thanks,

 

Marcel

 

0 Kudos
Reply
2,690 Views
MKlem
Contributor III

Stepping through the assembly code, i've found it does a compare on the 0xEB value of the argument, which passes. Then look is the "serial downloader" bit is set, if so, it jumps to 0x0020037C. 

This is the last call where it jumps to CPSID:

MKlem_0-1689258934055.png

 

After looking into it, it writes 0xE000ED0C to register R0, 0x5FA0004 to register R1, and then stores the value of R1 into the register at address R0. Looking into the Arm Cortex-M7 Processor Technical Reference Manual (pjrc.com), this is Application Interrupt and Reset Control Register.

According the ARMv7-M Architecture Reference Manual when written with the value 0x5FA0004 will request a reset:

Writing 1 to this bit asserts a signal to the external system to request a Local reset.

Ofcourse this should be done, and my guess is that is also does this and restart, because my application stops (pins are also reset). 

Tracing the things the call to runBootloader does; I've found it does the following 

- Compare 0xEB with the high byte of the given argument and if equal

- Check if serial downloaders is requested by AND with 0x100000 and if so 

- Load the value of 0xeb100000 into register 0x400f8000+0x2C

- Call a reset

When doing this before the scheduler has started, it seems to work. This would mean there is an issue with my OS or application. 

 

I'll dive into this and report back when I know more.

 

Thanks

 

Marcel

 

 

2,747 Views
MKlem
Contributor III

Hello Diego, 

 

Thanks for your quick response. 

For USB I'm using the default USB OTG pins. When I'm pulling down the pin boot pin, it is working and I can use the NXP-MCUBootUtility-2.2.0 to update the firmware. 

That is working flawlessy. But I don't think the end customer will short TP3 and GND on the PCB hehe  

I haven't tried LPUART1 yet, as those pin are used by other functions in this application. I figured if it works using the boot mode, I should also be able to jump to ROM from my application code. 

This  MCUxpresso Secure Provisioning Tool look good, is it included in the MCUXpresso IDE? 

 

Tomorrow or Thursday I'll look back into this problem and pause it in debug, to see what is is doing. 

Thanks!

Marcel

2,738 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hi @MKlem 

Thanks for your response ! 

I  understand that you are having USB connection with the MCU working properly. 

The SPT is not included in MCUXpresso IDE, it is  just stand alone. You can download it from the official page Actually you can use the SPT can the MCU boot Utility for simply send the ping command over UART. I understand that you do not have the LPUART1 pins available.

When you get chance, could you also let me know the ROM bootloader version your RT1010 has?

All the best, 

Diego

 

 

0 Kudos
Reply
2,721 Views
MKlem
Contributor III

hello Diego, 

 

I've tried the MCU secure provision tool: 

MKlem_0-1689151180434.png

 

When using the connection method with the boot pins, it works good. 

 

But when jumping from application code, this does not work yet. Can it have something to do with my application already using the USB function, and that it should be deinitialised before jumping? 

 

Here are the values of the bootload struct, just before calling the runBootloader().

MKlem_1-1689152713904.png

 

Thanks!

 

Marcel

 

0 Kudos
Reply
2,618 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hi @MKlem 

Thanks for letting me know. I am sorry for not getting back to you sooner. 

Does it makes any difference if you call the runbootloader api with or withot the USB cable connected ?

I am checking this with our RT1010 EVK. So far I have not seen issues with your use of the API.

All the best,

Diego

0 Kudos
Reply
2,554 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hi @MKlem 

As you comment this may be related to your RTOS. 

The runBootloader API works on my side from a baremetal environment, I tested with a RT1010 EVK. After calling it I am able to enter into serial downloader mode and get USB enumeration. 

Let me know if you got further details to share. 

Thank you!

Diego

 

 

0 Kudos
Reply
2,512 Views
MKlem
Contributor III

Hello Diego,

Thanks for your reply. I've made a workaround because of time limits.

Now, when the jumpToBootloader function is called, it writes a flag into the external EEPROM. 

The user is now requested to restart the device (a reset might work now, too!). 

On boot the EEPROM is read before starting the scheduler. If the flag is set, the bootloader is called and everything works as expected. 

Thanks anyway for your help. I hope someone else might find this usefull.

 

Marcel

0 Kudos
Reply
2,454 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hi @MKlem 

Thanks a lot for sharing the outcome! 

Diego

0 Kudos
Reply