I'm interested in writing C code to allow a firmware update to my project over the ethernet port instead of connecting the JTAG programmer every time. I've done enough embedded C programming to have a good handle on most things, but this one seems a bit tricky. I know the answer to this is very likely complex, but I'm only contemplating this right now, and there's no deadline. In my case, copying the executable "firmware update" code to RAM so I have unrestricted write access to FLASH seems like the way to go. What gets me is, how is this done in C? How do I copy a function(s) in FLASH to RAM then suddenly pick up and start executing out of RAM with no regard to any previous RAM contents? Or, is there no simple solution to this, and I have to get creative? The good thing is that at the point where I would initiate reprogramming, there would be over 80K of free RAM, so maybe I would have to copy to a specific region I know is free using a hard-coded address, then jump to that address. The stack, etc would stay intact. Any pointers? I think I could work something out but maybe I can learn something here.
I've never done this for a STM32 but for a AVR Controller. There is a small bootloader at the top of the Flash. This can be activated and controls the download of the new firmware. A block is loaded into the ram and then copied to the flash. That with all blocks necessary for the firmware. Then jump to the new firmware (address 0) or a reset or ..... I'm not sure if this is also possible with the STM32 but I think so. I guess you will find also hints on the STM website for this theme. Just my 2 cents 900ss
900ss D. wrote: > I've never done this for a STM32 but for a AVR Controller. There is a > small bootloader at the top of the Flash. This can be activated and > controls the download of the new firmware. A block is loaded into the > ram and then copied to the flash. That with all blocks necessary for the > firmware. Then jump to the new firmware (address 0) or a reset or ..... > > I'm not sure if this is also possible with the STM32 but I think so. I > guess you will find also hints on the STM website for this theme. > > Just my 2 cents > 900ss I should note that this is not for STM32, as I didn't mention the micro. It's for LM3S9bxx. I know there's a bootloader available for these, but I wasn't thinking of a bootloader so much. I wanted to be able to select to do a f/w update from a menu, although I suppose it doesn't make much difference how the user has to do it.
Jerry Milner wrote: > I should note that this is not for STM32, as I didn't mention the micro. Ah, yes :-) > It's for LM3S9bxx. I know there's a bootloader available for these, but > I wasn't thinking of a bootloader so much. How you call that piece of program is the same I think ;-) > I wanted to be able to > select to do a f/w update from a menu, although I suppose it doesn't > make much difference how the user has to do it. Yes, I think you can write such a f/w loader which is located at the end of the flash. The problem is, if the download failed then there is no valid application where the reset vector points to. May be you can set the reset vector in general and fixed to the f/w loader and there you decide to start the application or the f/w loader itself. But at the moment I don't know if such a scenario is possible with the LM3Sxxx or also the STM32. The application needs also reset vectors but I guess with the base address of the vector table you can "play". But my experience for the Cortex is not enough to give a precise hint. 900ss
As already pointed out by "900ss D." it can cause trouble if the update-code gets copied to RAM and deletes the old application during the update procedure. If update failes i.e. because of a power-failure the application code in flash and the update-code in RAM are lost and firmware has to be rewritten to flash using ohter channels (factory bootloader, JTAG...). You might check the documentation how software-protection is implemented. Some target have limitations which flash-pages can be written from application code if protection. Even if it's possible disabling the protection temporarly might not be an option since this might open a security hole for a short time. Maybe there are also non-volatile settings or external pins to set the default start-address (I can not rememeber this for Stellaris devices. But maybe there are options like this.) Possible appoaches: (1) - inital programming of the memory with the vector table at the start of flash and the update code (=bootloader) at the end of flash. - the reset-address in the vector points to the update-code's reset/startup-routine - the bootloader has its own vector-table to handle its interrupts and the first instructions of the update-code remap to this vector-table - the update code tests for an update request. Maybe by waiting for a special package received over ethernet until a timeout of by checking if a key is pressed. - if there is no update request the bootloader checks if there is a user-application in flash. This could be done by checking for a version-number or "magic-number" at a known memory address or simple by checking for empty flash - if there is an update request the update code receives the flash-image and writes it to flash but changes the reset-vector address before writing the applications vector so the update-code is always started first. The reset address of the user-application gets stored at a known memory address, maybe in one of the reserved elements of the vector table. - after update or after timout the bootloader sets the stack-pointers, remaps the vector-table to the default, reads the applications address from the known locations and finally jumps to it The advantage of this approach is that there is no special memory layout needed for the user-application and no need to take care of remapping in the user-code. Everything "special" gets handled by the bootloader. (2) - bootloader including its vector-table gets installed at the beginning of the flash-memory - bootloader always starts first, checks for update request as outlined above. - user-application starts at a known address after the end of the bootloader-code. - bootloader tests of update-request, receives new code, writes it to flash - after update or if there is no update request the bootloader reads the reset-vector of the application from the known start-address, sets the stack-pointers and calls the user-applications reset-handler. Optionally the bootloader can already remap the vector-table address but this could be also done in the reset-handler of the user application - the user-application needs to be linked to start at the known address. The address needs to be a valid postition for a vector-table (valid addresses/aligments should be listed in the documentation). For this minor modifcation are needed in the linker-script or special command-line options need to be passed to the linker I have implemented both approaches successfully with STM32 devices where firmware updates get read from a SD-Card. So the basic concepts do work. But of cause TI/LMI Cortex M3 devices are different in terms of in-application-programming and there may be differences in handling the vector-table location/offset. Hope this rather long post gives at least an idea.
Thank you Martin for your reply. I'm still investigating some of the points you make.