JTAG/SWD vs Bootloader

There are two ways to write a program into the microcontroller in order to execute it : either using a JTAG/SWD adapter or the library's bootloader. This page discusses the pros and cons of each method.


JTAG is a norm designed originally to perform electrical tests on components and boards going out of factories by taking control of their intput/out pins ("boundary scan"). From there, it has evolved into the generic interface used to take control of the whole microcontroller and allowing, among other things, to program its internal flash memory, control its execution flow with breakpoints, and dump its registers content in real time.

SWD is an alternative protocol specific to ARM chips, which is pin-compatible with JTAG but uses less wires. Most of the time when working with ARM microcontrollers, you'll use a microcontroller and an adapter both compatible with both JTAG and SWD, so you won't care which protocol is actually used. This is why we will refer to them collectively as JTAG/SWD.

Using JTAG/SWD requires an adapter, i.e. an external board which connects the microcontroller to the computer. It's kind of a "USB to JTAG adapter". There are many models available, but here are two that have been tested and are known to work :

You will also need a software in order to communicate with this adapter. libtungsten uses the great and open-source OpenOCD for this, most of the adapters and microcontrollers are supported right out of the box.

JTAG/SWD is the "classic" method for programming a microcontroller. It gives you the most powerful features (such as in-system debugging capabilities) and it "always works" because it is implemented at the hardware level. However, it is a bit more complexe and expensive, because you need an external adapter.


  • Unless the microcontroller is damaged, you will always be able to program it with an adapter
  • This offers you powerful features such as step-by-step debugging, real-time memory inspection, and more


  • It requires that you buy an adapter (~$30)

How to

  • make sure the BOOTLOADER option in your Makefile is either unset or set to false (and remember to issue make clean every time you change the Makefile)
  • plug the JTAG adapter to the board via the 10-pin connector on the right
  • to write your program to the microcontroller's memory, either use make autoflash or run make openocd in a background terminal and use make flash


A bootloader (in the context of an embedded system such as a microcontroller) is a small program flashed at the beginning of the microcontroller's memory with two main purposes :

  • receiving a compiled program from a communication port (such as USB or a serial port) and writing it into the microcontroller memory (while making sure not to overwrite itself, obviously)
  • executing this program, which we will call user code

libtungsten provides a customizable bootloader, which is able to receive code from USB or a serial port. This allows you to program the microcontroller without the need for an adapter, however, it will never be as powerful as a JTAG/SWD adapter (for example, you won't be able to do step-by-step debugging). The bootloader itself also needs to be flashed into the microcontroller once, using an adapter, although you can buy a board with the bootloader pre-installed. This is actually how Arduino works : there is a bootloader flashed into the microcontroller from factory, and the IDE connects to it via a serial port.

libtungsten also provides the tool needed to send the code to the bootloader, called codeuploader. This command-line tool supports both USB and Serial mode.


  • If the bootloader is installed, flashing code is plug-and-play, quick and easy
  • No need for an adapter
  • In a commercial system, the bootloader allows the user to update the device firmware


  • If the bootloader is not installed (or damaged), you won't be able to program the microcontroller without an adapter
  • You won't have access to advanced debug features, which can be extremely helpful during prototyping

How to

  • make sure the BOOTLOADER=true option is set in your Makefile (and remember to issue make clean every time you change the Makefile)
  • plug the board directly via USB
  • if the current program is able to detect a bootloader request automatically (see the autoBootloaderReset parameter of Carbide::init()), you can go to the next step directly; otherwise, you need to reboot the microcontroller into bootloader mode (for example, by resetting the board while pressing the button on a Carbide, but it depends on the bootloader configuration)
  • to write your program to the microcontroller's memory, use make upload

For more in-depth information, such as how to customize and interact with the bootloader, see the dedicated Into the bootloader page.

Bottom line

If you plan to make advanced projects and can afford a JTAG/SWD adapter, go for it. For simple projects and for final products, the bootloader might be enough and provide an interesting update feature.