2011-12-14 02:57 PM
Hi,
I'm working on a project on a STM32F4 where I want to update firmware over a GPRS modem from a webserver. In the past I've taken the approach of having a 'fixed' bootloader section that was robust and solid...at time of release! This boot section contacted the server and downloaded firmware. Later on when I wanted to make system changes the boot section couldn't be udpated and restricted what could be done. I have tons of code space, so this time I would like the main app to download the new firmware image (or a backup image of itself) and stash it into flash. A basic startup routine would validate the image with the highest version number and then jump to that image. So as each update is released the flash location that contained the operational code would toggle between two different locations. Has anyone taken this approach before with the F4? Any sample code/advice? At the moment my main 'unknowns' are firstly, is it possible to remap the interrupt vectors in the little startup routine so that each app is running its own interrupt routines? Secondly, how do I setup the build such that the app will run from an offset start address? Any help appreciated, Mike #multi-image-bootloader2011-12-14 04:38 PM
I would have thought you could probably have made a special app that could have updated the boot loader on the F1.
The F4 you can relocate the vector table in the same way as the F1. You won't be able to use the same image in two locations unless you compile it to be address agnostic, and copy vectors into RAM, as they are hard coded addresses, and you can't shadow different FLASH addresses at zero. You could make images for different locations by playing with the scatter file or linker script, or equivalent GUI settings. You could separate the compile of the app vs start code. Or if you are creative you could have some pre-main() start up code that would handle the choice between App A or B, and this could be done before you need to bring interrupts up, or the PLL, etc.2012-01-19 05:10 PM
I'm in the middle of the same thing. I'm using the Atollic toolset for the STM32F discovery board, and now using makefile based development.
It would be worth the effort to generate relocatable code if this is possible. I've been given the advice to add -fPIE to compiler, assembler, linker (in a managed build) - this still seems to generate absolute code that doesn't run. I've added -fPIC to compiler, assembler, linker in the makefile - I can't remember whether his ran or not.... Am I on the right track? Do I then need to also manually add relocation to the vector table entries?2012-01-19 06:11 PM
The vectors by their nature are a list of absolute addresses, you can't really resolve this with compiler/linker options. The rest of the code can be self-relative/agnostic.
I think the simplest approach is to build a vector table in RAM (CCM) during initialization in startup.s, or as a function of the boot loader. In this scenario you'd build the image in the normal way, at some generic address, and then in the loader code copy the N vectors from the address they are loaded at, to a fixed RAM address, dereferencing each a long the way. Off the top of my head, something like this.. unsigned long *x = (unsigned long *)0x08004000; // inferred load address unsigned long *y = (unsigned long *)0x1FFF0000; // RAM vector block unsigned long z = 0x08000000; // Assumed compile address int i; for(i=1; i<N; i++) y[i] = x[i] - z + (unsigned long)x; // Adjust to load address2012-01-19 06:36 PM
Also, if you are pulling firmware over the air, be aware that writing to the flash while executing from flash will cause hideous processor stall, and potential data over/under run conditions in peripherals serviced by interrupt.
2012-01-19 10:54 PM
Hi,
you can start by this Application note: AN3965: STM32F40x/STM32F41x in-application programming using the USART http://www.st.com/internet/mcu/product/252144.jsp2012-01-20 06:23 AM
Thanks - three questions then: 1) hideous; I thought I had looked this up and found some magic provision in the 32F4 which allowed writing whilst running? If not - hideous = about 10mS?
2) Flags for relative code -fPIE or -fPIC in assembler, compiler, linker? 3) And it sounds like it might be easier to copy the whole thing to RAM and run it there. The plan is that I'm always running an image, and that the image manages the downloading of its replacement. The disadvantage is that I don't expect THIS code to be very big, but RAM is always a smaller limit...2012-01-20 07:25 AM
The magic is that it works at all, most flash parts are unusable while write/erase operations occur, or need multiple banks/planes to work. The key take away here is that it stuffs the core with wait states, stalling the core from doing anything else, and this can be very disruptive. The ART unit will not protect you from this, according to the FAE I spoke to.
I'm not totally familiar with all of the GNU/GCC options but -fPIC seems like an appropriate option. Yes, running from RAM makes a lot of sense, use the CCM as this is single cycle for both instruction and data reads. The use of RAM depends on your code/data footprint2012-01-20 11:56 AM
Sorry - I'm trying to compile for RAM. Atollic has an option in the new project wizard to build for RAM but the linker script is the same as the build for FLASH. Anyone have an example linker script?
Thanks2012-01-20 01:51 PM
With the older version, the difference between the RAM and FLASH scripts was that the RAM one didn't direct any of the sections to FLASH. The use of a merge tool would be quite illustrative.
You should be able goose the sizes/locations of the memory areas in the MEMORY portion. For example making FLASH area actually describe the CCM RAM, here presuming you are using an STM32F4 board. Or, you could create a CCM area in MEMORY, and then adjust the SECTIONS portions to direct the code into that area.