7
\$\begingroup\$

I am looking at making an embedded design featuring an ARM Cortex M3 MCU and bluetooth. I would like to be able to update its firmware over Bluetooth periodically.

Is this possible with the following chip? From ST:

http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1031

I am used to connecting the bluetooth to the MCU via UART. Does the bootloader need to be modified when I want to program "over the air"? How does one load their own bootloader on the device? What does bootloader code look like?

I'm also open to other suggestions based on my objective.

\$\endgroup\$
  • \$\begingroup\$ If your bootloader accepts programs from the uart that should work just fine. You might need to tweak it to initialize your BT module of course, but that's about it. \$\endgroup\$ – Vladimir Cravero Jun 20 '14 at 20:40
  • \$\begingroup\$ A crucial problem with bootloaders is how to force the target chip into bootload mode. (Note that you can't rely on the application program!) How are you going to do that? \$\endgroup\$ – Wouter van Ooijen Jun 20 '14 at 21:44
  • 2
    \$\begingroup\$ @WoutervanOoijen Why can't you rely on the application to dump you into a "bootloader" mode? How else would you do a remote firmware update? \$\endgroup\$ – dext0rb Jun 20 '14 at 23:06
  • \$\begingroup\$ At least for AVR controllers the bootloader code is executed first, if it exists. Then there is a jump instruction to the main program address in flash. \$\endgroup\$ – sherrellbc Jun 21 '14 at 2:03
  • 1
    \$\begingroup\$ The application can be un-cooperative, for instance due to a programming error (power failure) or a bug. For remote bootloading, the only reliable way to force the target into bootload mode is to have a separate (non-updatable) intelligence that can do this (e.g. a small microcontroller, or something that is built into the communication module). \$\endgroup\$ – Wouter van Ooijen Jun 21 '14 at 6:42
7
\$\begingroup\$

Yes, you can do remote firmware updates with the STM32.

Now you have two choices:

  • using the STM32's factory-programmed bootloader
  • writing your own bootloader

Using the factory-programmed bootloader requires booting the chip with pin BOOT1 pulled low and BOOT0 pulled high, and the Bluetooth module needs to be connected to a specific USART peripheral (there are other interfaces, depending on the specific STM32 model, but I assume the USART makes the most sense here). Also, you need to write an app to interface with the bootloader, following the bootloader's command protocol which is documented here. To avoid writing code to interface to the bootloader, you could use the STM32 Flash Loader demonstrator application; of course this requires that the other end of the Bluetooth connection be plugged into a PC, so it doesn't make sense in every scenario.

The other possibility is writing your own bootloader, which gives you more control. You can, for instance, trigger the bootloader using a software-only sequence, so that you don't need to set certain pins as required by the factory-programmed bootloader. Of course, writing such a bootloader involves a lot more effort than using one that is already written, tested and shipped with the MCU.

Some brief comments about writing your own bootloader. A bootloader is a piece of firmware code like any other. It's loaded into the MCU during the production (or debugging) process together with the main code.

Despite being code like any other, since the bootloader is used to reprogram the MCU's firmware, it merits a few special considerations. First of all, for simplicity, you may want to make your bootloader a fully separate piece of code from your main code. Edit the bootloader's and the main code's linker scripts, so that each uses a completely distinct segment of flash memory. That way, you can update the main code without touching the bootloader. When the bootloader is part of the main code, if the updating process encounters any kind of problem, then your device is bricked. Bootloader code needs to be very reliable, since a bug in a bootloader may be the difference between the user being able to service the device by himself after a botched update, versus being forced to take it to a service center. Personally, I'd make the bootloader as small and simple as possible, even going so far as to avoid using interrupts, since in a way they make code less predictable. Usually I'm all for interrupts, but this is the one case where I'm against using them.

Briefly, a bootloader is loaded when the device boots, and usually just hands control over to the main code. However, when performing a firmware update, then the bootloader runs its own code after boot instead. This code must include some kind of communication (in your case) or storage driver, so it can receive/read the binary for the updated code, via Bluetooth, Ethernet, an SD card, flash drive or whatever. It then erases the old code and reprograms the flash memory with the new code.

One of the tricks that must be done when reprogramming the flash memory is relocating (copying) part of the bootloader code to the RAM, since you can't run code from flash while it is programmed (even if the address being read is different from the address being programmed). Also, the updated binary code that is going to be written to flash must be in RAM as well. Usually there won't be enough RAM to store the full code for the update, so it's not unusual to receive/read a partial block of code, write it, receive/read another partial block of code, write it, and so on.

Programming flash memory is not a simple matter of writing data to the desired addresses. There's a flash programming manual for each member of the STM32 series (for instance, here is the manual for the STM32F10x series). In brief, due to low-level details of how flash memory is implemented, before reprogramming a given block, you'll need to issue an erase command to it. Also, you can't make any reads from flash while it is being programmed, so forget about interrupts, DMA, etc. unless there's just no chance that they'll try to read from flash while it is being written.

\$\endgroup\$
  • \$\begingroup\$ Thank you! Exactly what I'm looking for - I had heard that STM32 allows for this. Two questions: how does one load their own bootloader on the device? What does bootloader code look like? \$\endgroup\$ – JDS Jun 24 '14 at 1:40
  • 1
    \$\begingroup\$ I've added answers to the questions in your comment to my post above. Please move these questions to the body of the main question above by editing it, so that any users who stumble into this question later don't feel that the answer is disconnected from the question. \$\endgroup\$ – swineone Jun 24 '14 at 4:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.