cancel
Showing results for 
Search instead for 
Did you mean: 

Ensuring that goto from one function to another function always works properly?

arnold_w
Senior

I am working with the STM32F446 microcontroller and compiling with Eclipse/GCC. 

Short version: I have two functions, main1(int argc, char* argv[]) and main2(int argc, char* argv[]) and I want to be able to goto back and forth between the two many times. What do I need to do to ensure that this will always work properly? In particular, I'm concerned about the stack and the Core General Purpose Registers R0...R12. Will these be "confused" if they all of a sudden find themselves executing inside a different function or will it be just fine since I always goto the BEGINNING of the respective functions?

Long version: I need to make my own USB-bootloader (no, the built-in bootloader doesn't fit my needs) and I have two Eclipse projects, bootloader project at sectors 0-3 and application project at sectors 4-7. I need to somehow be able to switch between bootloader mode and application mode (and vice versa) without dropping the USB-connection (hence, I can't reset the microcontroller). If I switch between the two projects using function CALLS, then I'm afraid I will run of out stack in case someone switches back and forth many times, that's why I want to switch between the two using goto instead. 

12 REPLIES 12
MFran.4
Senior

Is it possible to readjust the stack pointer (copying the stack in the starting position also) to start always at the beginning of the stack?

Danish1
Lead II

How about a "controlling" main that alternately calls main1 and main2?

To switch between, all you need do is return from your current mainx

How strongly do you need to not drop the USB connection? My guess is that firmware upgrades don't happen all that often so they're allowed to be sufficiently slow to re-establish USB.

KnarfB
Principal III

Not sure if it fits your use case: setjmp + longjmp came to my mind.

hth

KnarfB

You tell me. Is that all that's necessary to do?

Interesting idea, I think that should work. If the USB-connection is dropped, the re-connects are flaky and computer dependent (look at the Device Manager when you add/remove a USB-device, sometimes the tree gets updated 3-4 times) making the product appear to be of low quality.

Wow, that is way above my level, I have no idea what that means.

TDK
Guru

Alternatively, jumping from a bootloader to the main application won't reset the USB. It will be in the same state as when the jump happened. You will need to ensure interrupts stay enabled through the transition and that the vector table entry for USB is valid, but these are solvable problems. Set flags to indicate where the code is at and act accordingly in the interrupt.

If you feel a post has answered your question, please click "Accept as Solution".

Yes, I will specify SCB->VTOR first thing in main, in both bootloader and application. I was planning to hardcode a shared location in RAM for static and global variables. However, you brought up a good point about code in flash, I'm not sure how to solve that. I want the bootloader to be able to work even if the application area (sectors 4-7) is erased and I want to be able to run the application without the bootloader (common case when debugging from Eclipse). Could you please elaborate on how to use flags to indicate where the code is?

Put flags in a fixed location in memory which is not touched by the startup code. Check and change the values of those variables based on where your program state is. Maybe set to 0 during startup, change to 1 when USB initialized, change to 2 when second application call is imminent, set to 3 after second app loads, etc. Use the value in the callback to determine how to handle.
Code in flash stays in flash after the jump. The variables may not, but the code is there. You just need to ensure the variables that it does access are valid. Hence, the shared flag.
If you feel a post has answered your question, please click "Accept as Solution".