Hello,
At the moment, I'm working on software for a STM32F4 series micro-controller. The software consists out of a boot loader and a main application. The code itself has been working quite nicely for some time now. Recently I've altered the boot loader and released it as a newer version and it works quite nicely as well. However, when testing new versions of the application software, we've been noticing a few oddities that we cannot explain.
From my understanding, when using a properly written boot-loader, it (barely?) affects the main application. For example, the main application has the full RAM available for itself, no matter how much the boot loader uses of it. It seems that this isn't quite the case with our combination. Depending on which boot loader is used, we can allocate more space for the heap in the start up assembly file of the main application. This makes it feel as if the boot loader keeps some memory in use after it has jumped to the main application. (In this specific case, the newer boot loader allows for an additional 1000 bytes to be allocated to the initial heap size.)
Is this behaviour normal/expected, or are we possibly doing something wrong?
In case it is needed, some background info on our boot loader and the main application. The final part of the boot loader, that makes the jump to the main program, is as follows:
/* Jump to user application */ JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4); Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); Jump_To_Application(); // does not return here
In the SystemInit routine, the vector table is relocated using (the default?)
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
Where FLASH_BASE | VECT_TAB_OFFSET equals the same address as APPLICATION_ADDRESS in the boot loader.
Again, it all seems to work well, but it strikes us as odd that we need to lower the Heap_Size in the startup assembly file of the main application to make it work with the older boot loader.
Any advice is highly appreciated.
Thanks in advance.
Well the boot loader's not taking any of your memory. The heap allocation in the startup.s is all managed by the assembler/linker, and will be described in the .MAP file.
In the boot loader you need to consider where your stacks are, what interrupts and peripherals you've left hanging, etc. Be wary of any DMA operations, and multiple stacks.
You could dump out the processor/peripheral states at application entry, then compare/contrast the working and failing conditions. Consider also that the application is entering under non-reset conditions, ie clocks, plls, peripherals, make sure none of your code, or code you call/use makes other assumptions.
My bet is that it has nothing to do with heap size/allocation. It's an interesting side-effect, suggest you sanity check the memory arena as you enter main() so you catch it.
Thanks for your replies.
Tamir Michael: We haven't overridden the behaviour of the c runtime library. We've started noticing the problem when we were testing a new software release, which was working as expected in combination with the newest boot loader. At some point, we updated the main application on a machine with the old boot loader, and it failed to boot. After recreating the issue on a test board, it seemed that while executing the main() routine in the main application, a stack overflow error was detected. This happened before the actual os_sys_init call.
From experience, we knew that this is related to the memory settings in the start up assembly file. After some tinkering, we got it to work, and after some more research, we found out that when the main application was being called by the new boot loader, its initial heap size could be increased by roughly 1 kiB compared to it being called by the old boot loader.
Westonsupermare Pier: Thanks for those pointers and advice. I'm going to dig into the suggestions you gave. If/when something interesting happens, I'll of course let you know.
Do you build the boot loader as a completely separate project?
Some people try to create a merged project where application and boot loader is built in the same build step - but unless the boot loader is written 100% in assembler it's common that the boot loader and application then happens to use shared code since the C compiler often makes use of helper functions for some combinations of multiplication, division, variable assigns etc. So the original build works very well. But if the boot loader or the application is switched, then interesting things may happen when these common functions has been moved to other locations in memory.
Also remember that the boot loader should try to keep the processor as close as possible to the initial reset state when handing over to the application - the application may not like if an UART is already enabled with a ISR address somewhere in the boot loader memory - and then the interrupt vector table gets swapped so a pending interrupt will suddenly reach the applications UART ISR before the startup code initialized the buffer variables. So lots of strange things can happen when the boot loader leaves things enabled and the application assumes the code starts from a reset condition.
We've found the cause of the strange behaviour. It turned out that it was an interrupt, i.e. the SysTick timer, that wasn't disabled before the boot loader made the jump.
Disabled it before the jump, and now the memory usage isn't erratic any longer. (The weird memory part had to do with what was called by the triggered SysTick interrupt.)
Again, thanks for the help. Especially on the interrupts and the .MAP file.
Kind regards, Patrick.
PS. Per Westermark, we're using separate projects :)