2
votes

I have a bootloader and a firmware where the initial jump from bootloader to firmware works like a charme but when I have the scenario jumping back from application, make some stuff and jump back to my application. There I got some curious problem which ends in a hard fault. This problem comes up if I will activate the interrupts via __enable_interrupts() from IAR.

What are the right register to clear and reset all? I have set the MSP and the PC to the beginning of the application/bootloader.

It is neccessary that I don't use NVIC_Systemreset for that purpose.

Hope anyone can help me with that question?

2
Please give us some more details like: Where do you jump to in the bootloader, how do you return, where in the application do you want to return, what problems do you get? - the busybee
Why is it necessary that you don't use NVIC_SystemReset? That is by far the simplest method. This may be an X-Y problem - you are trying to avoid NVIC_SystemReset for some unstated and your solution to that does not work. It may be that avoiding NVIC_SystemReset is necessary, but knowing your reason for that assumption may just get you a better solution. - Clifford
While Julien's answer is likely on the money it is also not clear how "jumping back" to the bootloader is being performed - if for example a JMP to the main() address is used, the bootloader will run in the in the C runtime environment (stack, heap, library state) of the application, which may also cause problems. Typically from reset, there will be hardware (PLL, external memory interface etc) initialisation, C (or C++) runtime initialisation, then main(). You need to start from the runtime initialisation at least, so long as your bootloader has no hard clock speed dependencies. - Clifford
It sounds like perhaps you do not realize you cannot use interrupts without updating the pointer to the vector table, or using the remap to change it behind the scenes; if you go back to the bootloader you have to undo that change. Likely a reset is the best way to go back to the bootloader, especially if it is one you did not write; in fact, the general recommendation is to use a reset in each direction; when going to the application you set a flag (maybe in RTC registers or in RAM you exclude from clearing), detect that early in startup and branch instead of doing any chip configuration. - Chris Stratton

2 Answers

3
votes

There is an ST application note about bootloader.

In addition to patterns described above, user can execute bootloader by performing a jump to system memory from user code. Before jumping to bootloader user must:

  • Disable all peripheral clocks
  • Disable used PLL
  • Disable interrupts
  • Clear pending interrupts

This is why when you activate interrupts the bootloader crashes.

EDIT

To address @Clifford thoughts STM32 system bootloader exits with jump to master defined address with go command. This address should be reset vector not main so that heap, stack and FW will be correctly initialized. After that you can either do system_reset to be in a known HW state or you must fully configure the peripherals you use in application because they are not set bat to reset state after bootloader used them.

Note: If you choose to execute the Go command, the peripheral registers used by the bootloader are not initialized to their default reset values before jumping to the user application. They should be reconfigured in the user application if they are used. So, if the IWDG is being used in the application, the IWDG prescaler value has to be adapted to meet the requirements of the application (since the prescaler was set to its maximum value). For some products, not all reset values are set. For more information please refer to the known limitations detailed for each product’s bootloader versions.

0
votes

sorry for late response.

After some more investigations I have found the problems. For more clarifications about what I have done, here are some points which were also mentioned by your comments.

  • Disabled all Peripherals
  • Disbaled PLL
  • Disabled all interrupts
  • Clear alle pending interrupts

What I unfortunately forgot to mention that we use embOS. And this was the problem here. There is the CORE registers http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CHDBIBGJ.html

In the CONTROL Register there was a bit set: SPSEL If this bit is set to "1" then embOS got problems with normal operation. The solution for this is simple:

__set_CONTROL(0x0);

When this is called the jumping from embOS to Bootloader and back to embOS works perfectly.