Hello,
I need to use a secondary bootloader on my system and so I started to look at the example provided from NXP like the AN10866.
This one allow to emulate a USB device and copy form the host PC the new bin file in...
On my board I would need to use a USB stick for this purpose and I tried to had alook at the AN11628 (written around the LPC1788).
Let me say first that I'm quite new to the Cortex-M3 architecture.
After some try to port it to my device (with no success) I decided to write one from scratch.
My secondary bootloader load a bin file from USB stick and store it into the LPC1768 Flash memory starting address 0x10000 using IAP calls.
The writing and compare process ends correctly but when I jump to the final application I get an Hard Fault handler.
My bootloader use RTX and the same does the user application.
I almost read any thread of any forum around boot loader and LPC Cortex-M3 devices, but no one of the solution provided works for me.
I would really appreciate if someone can give any advice on that.
Solved! Go to Solution.
Hello Gabriele,
Here is a quick list of things you could check.
Was the user firmware image linked for address 0x10000? Not sure which toolchain you're using, but this needs to be changed accordingly when building the application. Typically its defined in the memory map settings. I can provide more details for a specific toolchain/IDE if needed.
The interrupt vectors need to be remapped for the user application before interrupts are enabled within the user application. For example, write 0x10000 to the vector table offset register (VTOR) to assign the new vector table location, then you can allow interrupts within the user application.
Not sure how you're jumping to the user application, but I use the following function.
#ifdef __CC_ARM
__asm void BOOT_ExecuteApp(UINT32 address)
{
LDR SP, [R0, #0]
ISB
LDR PC, [R0, #4]
}
#else
void BOOT_ExecuteApp(UINT32 address)
{
__asm volatile("LDR SP, [%0, #0]" :: "r" (address));
__asm volatile("ISB");
__asm volatile("LDR PC, [%0, #4]" :: "r" (address));
}
#endif
Regards,
Tyler Drazich
Hello Gabriele,
Here is a quick list of things you could check.
Was the user firmware image linked for address 0x10000? Not sure which toolchain you're using, but this needs to be changed accordingly when building the application. Typically its defined in the memory map settings. I can provide more details for a specific toolchain/IDE if needed.
The interrupt vectors need to be remapped for the user application before interrupts are enabled within the user application. For example, write 0x10000 to the vector table offset register (VTOR) to assign the new vector table location, then you can allow interrupts within the user application.
Not sure how you're jumping to the user application, but I use the following function.
#ifdef __CC_ARM
__asm void BOOT_ExecuteApp(UINT32 address)
{
LDR SP, [R0, #0]
ISB
LDR PC, [R0, #4]
}
#else
void BOOT_ExecuteApp(UINT32 address)
{
__asm volatile("LDR SP, [%0, #0]" :: "r" (address));
__asm volatile("ISB");
__asm volatile("LDR PC, [%0, #4]" :: "r" (address));
}
#endif
Regards,
Tyler Drazich
Hi Tyler,
I'm back on this topic after few months.
I tested your code and I get better results but still Hard Fault.
I'm using Keil and I mapped the application to the 0x10000 base address:
Can you clarify what you mean with the below sentence:
"The interrupt vectors need to be remapped for the user application before interrupts are enabled within the user application. For example, write 0x10000 to the vector table offset register (VTOR) to assign the new vector table location, then you can allow interrupts within the user application."
thanks in advance
Gabriele
Hi Gabriele,
Each application (bootloader and user) has its own set of interrupt vectors. From what I gather, the bootloader vectors at placed at 0x0 (the default) and the user app vectors are at 0x10000. When an interrupt occurs, the MCU uses the vectors that are located at the address specified by the VTOR register. When switching applications, the VTOR register must be updated accordingly.
Basically, I was saying be careful with interrupts during the switch, as immediately after execution jumps to 0x10000, if an interrupt occurs, it will execute the bootloader interrupt handler function (instead of the user interrupt handlers) until the VTOR register is written with 0x10000. This could be bad if it is occurring after execution has switched to the user app. This may not be your issue, but it is something to make sure is right.
In my apps, I disable interrupts, then jump, then update VTOR, then enable interrupts. Actually for the LPC176x, I do an MCU reset when switching applications so that all peripherals are in their default state prior to launching the app. I have included a link below to an archive of a version of my own firmware that includes a secondary USB bootloader. Look at the project USB-Boot and USB-Runtime within the 'Keil/LPC1769-LPCX' directory for reference.
https://dzxdesigns.com/files/DZX-Keil-v16.3.2.zip
Best Regards,
Tyler Drazich
Thanks a lot Tyler.
I'll have a look on your code.
I really appreciate your feedback.
Best Regards
Gabriele