2016-11-22 08:42 AM
Folks,
I have implemented bootloaders on the STM32F103 and F107 a number of times, but am struggling with a new one I have done using USB to download the new image when it has finished downloading the new image and is jumping from the bootloader section of the code to the new section. I have set my software to be programmed by the bootloader to start at 0x08008000 by setting this in my Section Placement Macros: FLASH_START=0x08008000 This clearly sets the code to 0x08008000 and if I run this code from the debugger it runs just fine. The bootloader itself is 25.5k; if I erase all, load the bootloader, I can see there is nothing at 0x08008000. If I then run the bootloader and send the relocated code via USB, I can see the bootloader loads the relocated code at 0x08008000 and all looks good. Once the code is all loader I call this: void JumpToNormalApplication(void) { volatile unsigned long JumpAddress; SCB->VTOR = (unsigned long)APPLICATION_START_ADDRESS; JumpAddress = *(volatile unsigned long*) (APPLICATION_START_ADDRESS + 4); Jump_To_Application = (pFunction) JumpAddress; Jump_To_Application(); } APPLICATION_START_ADDRESS is set as follows in a header file:#define APPLICATION_START_ADDRESS 0x8008000
However, when I jump into the code, I get partway through the the function in the startup code here: /* Zero the bss. */ ldr r0, =__bss_start__ ldr r1, =__bss_end__ movs r2, #0 bl memory_set ldr r0, =__tbss_start__ ldr r1, =__tbss_end__ movs r2, #0 bl memory_set And it crashes. Now, if I change this so that - once the bootloader has already loaded the code and does not try to run the bootloader code, but go straight to the new, relocated image, it seems to run OK. I am, in both instances, running a FreeRTOS program. If I don't start the scheduler in the bootloader and jump to the relocated program, why would it not crash? Can anyone think of what I can do so that I can seemlessly go from the bootloader, once it has loaded a new image, into the new image located up at 0x8008000 please? What am I missing here? Thanks! Rob2016-11-22 09:09 AM
Crashes how exactly? Hard Faults?
If memset() is causing a crashing it suggests you likely have some interrupts running, or some stack(s) situated in the area you are nuking. Look at the memory the App uses in the frame of the Loader (via its .MAP or symbol table)Be careful handing over from Interrupt context, if you don't exit the IRQHandler through the normal mechanism it will break the core and NVIC nesting/preemption logic. Also be wary of System/User state.2016-11-22 09:16 AM
JumpToNormalApplication() jumps to the App in the Stack of the Loader, not the Stack expectations of the App
Suggest you explicitly load the Initial SP of the App in the App's ResetHandler, rather than expect it to enter in reset conditions. ie LDR SP,=__initial_spI'd do it there rather than in the loader, in C, as it is not coming back from the ResetHandler, and at that point the entire memory is owned by the App2016-11-22 09:56 AM
Hi Clive,
It's a hard fault exception. I am disabling all interrupts and there are no pending interrupts when I boot to the new application. What does ''in the frame of the Loader'' mean in the line below please? Look at the memory the App uses in the frame of the Loader (via its .MAP or symbol table) I must confess I have never understood this System/User state thing at all. How do I tell what state I am in as I leave the bootloader? I have Googled this: ''what is system and user control in cortex m3?'' to try and find something that explains it in simple terms, but cannot find anything. Does anyone know of a good tutorial on this please? Many thanks.2016-11-22 10:22 AM
Thanks for this reply too.
From what I can see, when it boots into the application from the bootloader, thumb_crt0.s is setting the stack pointer (r13) before it crashes. One thing that is interesting is that when I step through the cod after I have moved into the application, but [long] before I get to the main() of the C code is that I seem to get a call to xPortSysTickHandler() and to xTaskIncrementTick() which I rather think should not be happening. It *does* seem to be the code within the application rather than the bootloader though. ie the debugger is pointing to xPortSysTickHandler within tasks.c within the directory of the application not the bootloader. (I have loaded the application .elf file to the IDE so I can trace what goes on when I pass from bootloader to app.) I will investigate this systick going off. Maybe I have not disabled its interrupt, but when I looked at all the NVIC->ISER registers they are all set to 0 as I come out of the bootloader.2016-11-22 11:06 AM
Yep, disabling the timer tick interrupt just before calling the boot to main app seems to have fixed it.
That JumpToNormalApplication is what I have used loads of times when the bootloader has been a run to complete program rather than a FreeRTOS bootloader. So that would explain why this has caught me out I guess.2016-11-22 12:55 PM
What does ''in the frame of the Loader'' mean in the line below please?
Here I mean look at what memory regions you are memset()'ing to zero in the Application, and what those areas are used for in the Loader. It might help pin point where the conflict is. For instance if you nuke some FIFO buffer for the USART, and the IRQ then picks up and accesses a pointers which have become a NULL all of a sudden.I use System/User as a generic Motorola 68K type concept, where what instructions you use, and what memory you can touch is different. The Cortex-Mx doesn't really have this same level of virtualization, but there is a longer list of things you can't touch without Hard Faulting. There are some potential issues with an RTOS starting another RTOS out of an unprivileged context. You also have to watch which stack is used, and the size or consequences of using each.http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s06.html
2016-11-22 01:33 PM
Hi wood.robert,
Would you be able to post your code which fixed the issue?Thanks!