2014-05-13 07:53 AM
Hi, I'm quite new with the ARM and STM32 world.
I'm developing an application wich has to load a bootloader and, at a certain point, jump to the main application. I'm using the STM32F4-Disco. The bootload is quite complex, using FreeRTOS and STemWin, comunicating to an external device with USART periph. Using a USB OTG drive which han an image.bin file on it (which is the main app code), I load it to a flash memory sector that for me is APPLICATION_ADDRESS (uint32_t)0x08080000 and then press a button on the touch-LCD for jumping to the loaded code. The jumping function is: cmd_Jump_To_Application(APPLICATION_ADDRESS) void cmd_Jump_To_Application(uint32_t start_Address) { USART_DeInit(USART2); USART_DeInit(USART1); RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE); RCC_DeInit(); __disable_irq(); uint32_t addressToJump = *(__IO uint32_t*) (start_Address + 4); pFunction Jump_To_Application = (pFunction) addressToJump; /* Initialize application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) start_Address); /* Call Reset Handler */ Jump_To_Application(); } Assuming that the downloading part to flash memory is right (I ported from the FW_Upgrade example, and debugging I can see what I expect in the application sector), there is something wrong. When I press the jump button I get a white screen and everything freezing and I can't start the main application. I'm missing something for sure, maybe about stack or some other vector adress\init, but I can't understand what. Some suggestions? Thanks!2014-05-13 08:22 AM
Use a debugger and step into it.
Implement a functional Hard Fault Handler so you can observe if/why something fails. Make sure you have built the app for the higher address, and that the code in SystemInit() sets the appropriate address into SCB->VTOR For FreeRTOS, you'd probably want to switch to System mode to perform the transfer of control (SVC?).2014-05-14 02:29 AM
I'm not able to debug anymore once the jump is executed. I can still run and stop the code but I don't get the line where the code is at. Maybe that means that it does do the jump and the problem is somewhere else.
I added the line SCB->VTOR = (__IO uint32_t)start_Address; just befor the jump to app, but didn't help. I also did a version of my bootloader removing FreeRTOS use, but I get the same thing. I think that means that the problem is beyond it, but maybe I'm wrong. I think my app code is ok since is a bin file already provided from ST and it works ok when loaded with the ''Firmware upgrade'' example loader.2014-05-14 02:40 AM
''I added the line
SCB->VTOR = (__IO uint32_t)start_Address; just befor the jump to app, but didn't help.'' This needs to be in your application, very early on. I think it is in SystemInit() (part of the cmsys code) in my FreeRTOS project. It needs to be set BEFORE ANY interrupts are enabled.2014-05-14 06:36 AM
I thought that jumping to another app code, meant to somehow clear and reset everythig that was executed until that point..is that right? I'm not so sure anymore..
In which way can the bootloader code influence the app code once the micro jumps to the first instruction of the new app?2014-05-14 06:45 AM
I thought that jumping to another app code, meant to somehow clear and reset everything that was executed until that point..is that right? I'm not so sure anymore..
In which way can the bootloader code influence the app code once the micro jumps to the first instruction of the new app?
Well how's it going to do that, you enter with non-reset conditions, probably running from the PLL, with a bunch of peripherals initialized, NVIC and interrupts configured. With an RTOS you're biggest problem will likely be that you are running in User/Process mode, and not System mode. You should be able to step into code of the app, follow the code disassembly. For source level, Keil would allow you to debug the app, having you run through the loader, and then break pointing the Reset_Handler. You are trying to identify why/where it fails, which can be done without source. A properly implemented Hard Fault handler would also provide insight into what's happening.
2014-05-14 06:59 AM
So isn't there a way to do the necessary resets just before the jump?
I'm sorry for the dumb questions, but as I said I'm a newbie, a university student. My RTOS is runnging in user mode, but I don't understand how to have it running in System mode. The problem is that I have no knowledge about dissasembly, so unfortunately that wouldn't really help. I tried doing the jump as the very first instruction in the main, before any initializazion, but it doesn't work anyway. Does that mean that the problem is somewhere in the startup or sysinit?2014-05-14 07:49 AM
Hi
''So isn't there a way to do the necessary resets just before the jump?'' Yes but you should do it in the application as part of the start up sequence. That way you guarantee the application start is correct not matter how it is started. Look at the clock control registers - there are 2/3 registers which control peripheral reset. If you set all the bits to 1 - all peripherals get reset. ''I'm sorry for the dumb questions, but as I said I'm a newbie, a university student.'' Not at all we are here to try and help BUT please listen to what we tell you (others just seem to waste our time). ''My RTOS is runnging in user mode, but I don't understand how to have it running in System mode.'' I have done exactly what you are trying to do - a bootloader which loads and run another application code. I did not have the bootloader running FreeRTOS - it adds extra complication, not to mention uses up valuable FLASH/binary space! The application code I load does run in FreeRTOS. ''I tried doing the jump as the very first instruction in the main, before any initializazion, but it doesn't work anyway. Does that mean that the problem is somewhere in the startup or sysinit?'' What you had at the start is pretty close to what it should be. When you transition from bootloader to application, the booloader does not know exactly where the application code starts. It does know where the vector table is. At the start of vector table is 1)stack location of RAM for application 2)start address of entry point into application. It is described as 'start address of entry point into application.' because it is not main or sys_init - it is up to what every the programmer, compiler, linker decide. In STM32 case - it is usually a small piece of assembler code.2014-05-14 08:03 AM
I tried doing the jump as the very first instruction in the main, before any initialization, but it doesn't work anyway. Does that mean that the problem is somewhere in the startup or sysinit?
Or that your app code wasn't linked at the right address. Check your Target settings, scatter file or linker script.2014-05-14 08:12 AM
First of all thank you for the time you are dedicating to me!
Yes but you should do it in the application as part of the start up sequence. That way you guarantee the application start is correct not matter how it is started.
Look at the clock control registers - there are 2/3 registers which control peripheral reset.If you set all the bits to 1 - all peripherals get reset.
Even supposing I was able to reset setting thins register's bits, If I have my bootloader going to HardFault, I would I know that my bootloader is jumping and that this reset operation will happen?Not at all we are here to try and help BUT please listen to what we tell you (others just seem to waste our time). I'm trying to do my best, which is really bad :)
I have done exactly what you are trying to do - a bootloader which loads and run another application code.
I did not have the bootloader running FreeRTOS - it adds extra complication, not to mention uses up valuable FLASH/binary space!
The application code I load does run in FreeRTOS. I don't get it. Are you sharing with me some kind of exaple code? If it's like that, I'm not able to see it!
What you had at the start is pretty close to what it should be.
When you transition from bootloader to application, the booloader does not know exactly where the application code starts. It does know where the vector table is. At the start of vector table is 1)stack location of RAM for application 2)start address of entry point into application.
It is described as 'start address of entry point into application.' because it is not main or sys_init - it is up to what every the programmer, compiler, linker decide. In STM32 case - it is usually a small piece of assembler code. Here comes the problem. I'm not able to write a singol assembler code line. I thought I was remapping the vector addresses with line __set_MSP(*(__IO uint32_t*) start_Address) Is that right? And, most of all, is it possible to have my project working without knowing assembler language? I'm not so sure about it anymore.. Thanks again!