Flash Resident USB-HID Bootloader With the NXP Kinetis K22 Microcontroller

DZone 's Guide to

Flash Resident USB-HID Bootloader With the NXP Kinetis K22 Microcontroller

See how you can bring a flash resident bootloader to your projects and how it works with Eclipse-based IDEs to offer you greater visibility into your projects.

· IoT Zone ·
Free Resource

The tinyK22 board (see tinyK22 Boards arrived) has been rolled out at the Lucerne University of Applied Sciences and Arts, so I thought I would write up an article on how to use that board with a flash resident bootloader.

tinyK22 with USB HID Bootloader

tinyK22 with USB-HID Bootloader

I tried to keep this article as generic as possible, so you can use any other Eclipse-based IDE (DIY, Kinetis Design Studio, or the NXP MCUXpresso IDE). For the example project and sources used, see the link to GitHub at the end of this article.

If you are interested in another very good open source bootloader, check out the μTasker project page (http://www.utasker.com/kinetis/tinyK22.html). That bootloader offers MSD loading and much more — and is much smaller too.

As hardware, the NXP Kinetis K22FN512 is used. This ARM Cortex-M4F microcontroller is present on the tinyK22 board as well on the NXP FRDM-K22F board.

Blinky on a FRDM-K22F with SDK V2.0 and Processor Expert

tinyK22 with USB HID Bootloader

tinyK22 with USB HID Bootloader

USB HID Bootloader

A bootloader based on USB HID is a cool way to load applications on a microcontroller. For USB HID no special drivers are needed for a Windows/Mac/Linux host as USB HID drivers are part of the host operating system. The downside is that USB is a rather complex protocol, thus requires USB hardware and a USB  stack on the target device.

I ported the presented project from the NXP KBOOT and am using the utilities that come with that package. The implemented bootloader is a flash resident bootloader. This means, initially, I program the microcontroller with the bootloader and it remains in flash, then is used to load any application I want. With optimization -O1 set, I have a USB HID bootloader, which uses around 26 KBytes of FLASH.

Project Structure

The screenshot below shows the bootloader project structure.

bootloader project

bootloader project

  • link: contains the linker file. The bootloader vector table and address is mapped to 0x0000’0000, which is the default vector table for ARM Cortex-M
  • MK22F51212: contains the hardware-specific port to the Kinetis K22 microcontroller. The bootloader_config.h file in this folder is used to configure the bootloader.
  • src: contains all the bootloader sources, which are pretty much generic

Bootloader Project Defines

The project uses a few global defines to configure the bootloader:

Bootloader Defines

Bootloader Defines

The above defines disable extra debug messages, set the USB stack to be bare-metal (no RTOS used), and configure the device (MK22 and ARM Cortex-M4). The last define configures the bootloader to be FLASH resident.

Bootloader Configuration

The header file MK22F51212\bootloader_config.h is used to configure the bootloader, for example, which communication protocols are supported. In the setting below, I’m configuring it to use USH HID only:

#if !defined(BL_CONFIG_SCUART)
#define BL_CONFIG_SCUART (0)
#if !defined(BL_CONFIG_I2C)
#define BL_CONFIG_I2C (0)
#if !defined(BL_CONFIG_DSPI)
#define BL_CONFIG_DSPI (0)
#if !defined(BL_CONFIG_USB_HID)
#define BL_CONFIG_USB_HID (1)
#if !defined(BL_CONFIG_USB_MSC)
#define BL_CONFIG_USB_MSC (0)
#if !defined(BL_TARGET_FLASH)
#define BL_TARGET_FLASH (1)

The more numerous or the more complex communication protocols are used, the more FLASH memory is occupied by the bootloader. With the USB HID enabled, the size is around 26 KByte of FLASH, it fits into the memory area below 0xb000 (see text, data, and bss: Code and Data Size Explained)  how to read the output below.

arm-none-eabi-size --format=berkeley "tinyK22_KBOOT_bootloader.elf"
  text data bss dec hex filename
 26204 1856 14000 42060 a44c tinyK22_KBOOT_bootloader.elf

For example, if I would communicate to the bootloader with UART, it would only need 21 KB of FLASH memory.

The bootloader can use a GPIO pin to enter bootloader mode after a reset (e.g. POR, Power-On-Reset). Which pin is used is configured in MK22F51212\hardware_init_K22F512:

#define BOOT_PIN_NUMBER 17

tinyK22 Pinout

tinyK22 Pinout

With the above code, I’m using the GPIO Pin PTB17. The function is_boot_pin_asserted() is used to check that pin. Typically this pin is pulled HIGH by a pull-up and pulling it to LOW during startup I will enter bootloader mode.

If not using any bootloader pin, I can configure the bootloader timeout specified in bootloader_config.h:


With the above setting, after reset, it will wait for 5 seconds for any communication from the host until the bootloader proceeds. If such a timeout is not desirable, then I recommend configuring a dedicated bootloader pin.

Another setting in the bootloader_config.h is where the vector table of the application resides. Basically, this defines where my application FLASH memory space starts. Below I have set it to 0xC000 which means that the bootloader can use 0x0000 up to 0xBFFF.

// The bootloader will check this address for the application vector table upon startup.

Programming the Bootloader

The bootloader needs to be programmed with an SWD/JTAG debug probe (e.g. Segger J-Link, P&E Multilink, or CMSIS-DAP) to the microcontroller.

Stopping the bootloader with the debugger shows that it waits for incoming USB packets:

USB HID Bootloader waiting for USB packets

USB HID Bootloader waiting for USB packets

Building an Application to Be Loaded With the Bootloader

An application to be loaded with the bootloader needs to be linked at the correct address, where the bootloader expects it. As discussed above, I have my application start address (actually its vector table address) at 0x0000’C000.

Linker File Mapping Application at 0xC000

Linker File Mapping Application at 0xC000

With that linker file, I create the S19 and/or the binary file of the application that I want to load with the bootloader. See Binary (and S19) Files for the mbed Bootloader with Eclipse and GNU ARM Eclipse Plugins and MCUXpresso IDE: S-Record, Intel Hex, and Binary Files for more on how to create S19 or binary files with GNU tools.

Connecting to the Bootloader

KBOOT (see links at the end of this article) includes two utilities to communicate with the bootloader:

  • blhost: command line utility
  • KinetisFlashTool: same as above, but with a GUI

Connect to the USB HID Bootloader using the 0x15A2 for VID and 0x0073 as the PID:

Connect to USB HID Bootloader

Connect to the USB HID Bootloader

 Note that the bootloader needs to be active for the connect process!

If that succeeds, it will show me the bootloader information:

connected with USB HID Bootloader

Connected with USB HID Bootloader

The same way the blhost utility can be used to connect to the device on the command line (the USB VID/PID is optional):

blhost --usb 0x15a2,0x0073 - get-property 1

blhost with USB HID Bootloader

blhost with USB HID Bootloader

Once connected, I can update the binary using the bootloader. As the binary file does not contain any destination address information, I have to specify this in the dialog (0x0000c000, as this is where my application starts with its vector table):

Update with new binary

Update with new binary

The same thing can be accomplished using the blhost command line:

To load a binary file to address 0xc000:

blhost.exe --usb 0x15A2,0x0073 write-memory 0xC000 tinyK22_KBOOT_led_blinky_1Hz_0xC000.bin

loading binary file

Loading the binary file

For loading S19 files the flash-image command is used:

blhost.exe --usb 0x15A2,0x0073 flash-image tinyK22_KBOOT_led_blinky_1Hz_0xC000.srec

loading S19 file

Loading the S19 file

Reset the board, and the new application is running!


A flash resident bootloader is a bootloader that I can configure and program into the FLASH memory of the microcontroller. I can configure it for the communication protocol to be used to the outside world (USB HID in this case) and then connect either with a GUI or command line tool to the device and update the application. This is especially useful if I have devices in the field and I have to update them with a new firmware without the need for a debugger.

Happy Bootloading!


eclipse ide, flash resident bootloader, iot, microcontrollers, tutorial

Published at DZone with permission of Erich Styger , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}