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
Solved! Go to Solution.
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
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.
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.
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.
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:
Also a hard fault is reported.
Looking in the disassembly window:
When resetting BEFORE entering the bootloader (so resetting when the breakpoint has triggered), it works?
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
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:
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
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
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
hello Diego,
I've tried the MCU secure provision tool:
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().
Thanks!
Marcel
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
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
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