cancel
Showing results for 
Search instead for 
Did you mean: 

Jump to custom bootloader SysTick doesn't work

Clonimus74
Senior II
Posted on November 04, 2015 at 14:02

Hi all,

Let me tell you of the configuration hat works: I have a custom bootloader (via USB or USART). The system boots from the bootloader (0x8000000), sees there is a valid application (there's an application signature) and jumps to the application (0x800A000). In the application, if a command is received from a PC to erase the signature, the signature is erased and the system turns off (reset will kill the port holding the power, so reset is not an option). turning on the system again, the bootloader loads and wait for new firmware upload. I tried to jump from the application to the bootloader instead of turning off the system (bootloader jump to application works). here's what I do:

static
void
RunToBootloader(
void
)
{
typedef
void
(*pFunction)(
void
);
FLASH_Lock();
pFunction Jump_To_Application;
uint32_t JumpAddress;
__disable_interrupt();
DisableAllPeripherals();
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (BOOTLOADER_START_ADDR + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) BOOTLOADER_START_ADDR);
Jump_To_Application();
}

In the bootloader the SysTick interrupt is not set (I don't get into the ISR), if I reset it works (interrupts are enabled at the beginning of the bootloader code). Since jump from bootloader to application works I assume vector table re-assigning is correct. what can be the problem?
10 REPLIES 10
Posted on November 04, 2015 at 18:38

Do the interrupts ever get enabled again? It won't happen magically.

The disable_interrupt is a bit of a cop-out, you should tear-down and turn off the peripherals you're not using, and turn off all their interrupt generating settings. The clean hand-over will solve a lot of problems. If you want to keep things enabled, define and implement that in both the loader/app so you have a clear contract about what happens. ie if the loader starts the HSE and PLL, perhaps you don't want the app to do that again, and if you call back into the loader it should be smart enough to know if the HSE/PLL are already running and selected.

If you jump into the boot-loader with non-reset conditions, all the code needs to be aware of that, and not make assumptions, things like the clocks sources, PLL settings, flash wait states and vector table setting being prime ones to consider.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Clonimus74
Senior II
Posted on November 05, 2015 at 15:20

Clive,

After all init in the bootloader are done, the interrupts are enabled. I can also see it in debug (I run debug from the bootloader, let it jump to the application [code now only at disassembly], send the command from PC, the code breaks at the begining of the bootloader and I can see it re-enable the interrupts, well just as if it was booting from bootloader).

Do you think the fact that I go through SystemInit() again it ruins something? I go through

SystemInit() so the interrupt vector will be relocated again, I don't see why reinit of the clocks will do something.

Also, I turn off the peripherals and their interrupts before jumping, that is what DisableAllPeripherals() does.

In any case I can detect if I came back to bootloader from the application or from power on, but what should I do different? the only thing I do different is that I don't allow the IO that keeps the power on to be reset.

Posted on November 05, 2015 at 19:25

I'm saying that the path through SystemInit() can be expedited if it doesn't tear-down the running state if it's already in the one you want.

You're going to have to debug your code, and the hand-over, to understand why it's failing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Clonimus74
Senior II
Posted on November 08, 2015 at 13:31

I understand I must debug it, but I couldn't find anything wrong so I turned to this forum to see if anyone has an idea.

I get it that the hand over from the bootloader to the application is ok, but not from the application to the bootloader.

BTW, I read in the forum that the interrupt vector should be mirrored to address 0x000000, is that tru also in the case the interrupt vector is in the flash (0x8000000 [for bootloader] and later 0x800A000 [for application])? I can see that the content of 0x8000000 is mirrored to 0x0000000 but after the jump to application (which works) 0x800A000 is not mirrored to 0x0000000

Posted on November 08, 2015 at 17:06

The mapping at zero is important for Cortex-M0 parts where the Vector Table can't be relocated, but I don't know what you're using as the thread provides little detail.

Most code built/linked with the expectation of being at 0x08008000 or wherever, won't need or expect the mapping at zero.

I don't know what issues there are with you system, there is far too little presented here to replicated the issue.

I think you're going to need to simplify the problem, and output diagnostic information so you understand what's actually happening at a hardware/register level. If you are transferring control in a user/system state, or jumping between the images in an interrupt, etc.

I've generally recommended resetting to transfer control to the loader.

I've suggested you need to do the debugging, because you hold all the cards here. 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Clonimus74
Senior II
Posted on November 09, 2015 at 10:06

Thank you clive.

I'm using STM32L151 (M3).

Obviously I cannot share my entire code here, but I shared the hand over, I have no idea what other info one needs to think of some reason that happens.

Other than disabling interrupts, and de-init all peripherals, what else should have I done?

Might there be missing something in the bootloader, assuming it runs perfectly after reset?

Interrupt vector at all instances mapped to the right place.

Posted on November 09, 2015 at 13:55

but I shared the hand over

I suspect that's not where the issue is. It's more likely to be the context in which it occurred.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dhiry2k1
Associate II
Posted on November 12, 2015 at 19:50

Hi Clon,

Check if in your bootloader  , SysTick_Config function is called? and what you mean by disabling all the peripherals ?

Try commenting that line. are you sure you are configuring the systick in application?

Clonimus74
Senior II
Posted on November 15, 2015 at 12:26

Thank you all for your help.

I found the problem, well 2 problems:

1. the load bootloader function was called from an interrupt, not a good idea (originally it wasn't there but moved due to real time issues in the app).

2. I found an interrupt that was enabled aftr I disabled it in another function call

Now my problem is infinite interrupts in the bootloader USB after it loads, I need to find how to de-init the USB rather than just turning it off and disabling the interrupts. maybe just clear the interrupt flags, don't know, but that's it, seems to be fine.