USB MSC device bootloader revision for FRDM-KL25Z (IAR)

Document created by Kai Liu on Oct 25, 2013Last modified by Adrian Puga Candelario on Jan 21, 2020
Version 13Show Document
  • View in full screen mode




This document is a supplement and revision of AN4379 Freescale USB Mass Storage Device Bootloader written by Derek Snell in 2011. The original version was programmed with CW for Flexis JM/ColdFire MCF522XX/Kinetis K60. It has not been updated for 2 years.


In 2013, I selected FSL MKL25Z as my prefer platform for USB host/OTG application, because it has on chip OTG module, instead of regular device module in its competitors have. I can develop some USB host applications. IAR is selected among commercial compilers for KL2X and other MCU development, since IAR can offer 32KB limited edition for ARM. In order to make AN4379 work on my FRDM-KL25Z, it involves porting efforts between compilers (from CW to IAR EW) and hardware platforms (from K60 to KL25).


Reused Sources

I gave up the original release since I found FSL USB stack has been improved in many ways between v4.0.3/v4.1.1 and Derek's base. The MSD application from USB stack are reused as baseline. I also merge flash and serial port driver from AN2295 Serial bootloader, as well as some helper functions for debug purpose.


The printf( ) sometimes is more helpful than debugger, since it can reveal information during full speed run time. However, don't print out too many characters, since it occupies many resources. Don't print message everywhere, use it only when necessary and remove them in your final release.


Bootloader Project & Sources


A working bootloader project should include following files and paths.


X:\Freescale USB Stack v4.0.3\Source\Device\app\msd_bootloader

X:\Freescale USB Stack v4.0.3\Source\Device\app\common

X:\Freescale USB Stack v4.0.3\Source\Device\source\driver\kinetis

X:\Freescale USB Stack v4.0.3\Source\Device\source\class\usb_msc*.*

X:\Freescale USB Stack v4.0.3\Source\Device\source\common


Since I have not touched any code in Device\source folder and it is part of USB stack. You can unzip them into a separate folder and merge them into your existing USB stack tree.


Be careful, since I have changed some code in common folder. It is up to you to merge them with compare tool. And MSD bootloader and MSD user application indeed have differences in main( ).


Open the attached project in IAR EW, rebuild it and download into debugger.


Then you can connect its user USB port to PC, the OS will prompts MSC device connecting and BOOTLOADER driver is shown later on. You can drag and drop , copy and paste or enter in command prompt to copy any user application S-record file into BOOTLOADER driver.


If your application code is designed for MSD bootloader, it will run after reset. For what is designed for MSD bootloader, please check the following chapter.

First Thing First

The bootloader must have conditional jump to user application. The condition could be push button or timeout counter. As a result, the GPIO and timer must be initialized as first step. According to Cortex-M's nature, MCG should be initialized as well in some cases. However, I find multiple calls to MCG initialization routines may cause system hangs on it. The detail logic has not been recovered so far. But I would like to recommend to initial GPIO and LPTMR only, without touching too much on MCG pll_init( ).


Default Operation


The bootloader will check if PTA2 has been grounded after reset. It will drops to bootloader anyway if it is connected to ground. Otherwise, it will check 0x8000~0x8004 for SP/PC checking. If there is a valid user application, it will transfer control to user application. If not, bootloader will enumerate an MSD driver called BOOTLOADER. There is a file called READY.TXT inside the driver.

Custom Bootloader

The bootloader can be used directly, or you can custom it. That's why I still keep the revised bootloader as open source. You can rename the driver label, download and run, more firmware format like intel hex, use another ISP push button, resize the driver, add CDC for debug purpose, add driver inf file for custom driver installation, add bi-directional communication over file system, add more features.


However, you must understand FAT16 and make modification by yourself. You have to help yourself.


Demo User Application Project


Another attachment FRDM_KL25ZDemo_freedom.srec is demo project from Kinetis L family release and its S19 file, linked with modified ICF link file.


The starting address of an user application is heavily device dependent, which basically related to its 32bit flash protection registers.


Since MKL25Z128VLK4 has 128KB flash memory, the minimal protected flash block is 128K/32=4KB. The existing MSD bootloader release is 22KB (0x597F). So 0x6000 could be the start address of an application. Considering potential integrated features and data storage in future releases, 0x8000 is recommended as application start address.

General Purpose ICF files


During my development with AN2295(Serial) / AN4370(DFU) / AN4379(MSC device) bootloaders, I prepared more linker file. The only differences are the starting addresses, aka relocated vector address, ranges from 0x4000 / 0x8000 / 0xA000. The attachment Pflash_128KB_0x8000.icf explains itself from its name


You can easily find necessary modifications for your ICF files in AN2295/AN4370/AN4379 documets.


We can put three versions of ICF file in your linker script folder for easy development.

Unnecessary Flash Protection Bytes


By inspecting the S-Record file, I found the flash protection bytes are still reserved in user applications. Furthermore, the area between 0x80C0 and 0x83FF is kept as 0xFF, blank bytes. The flash protection bytes from 0x8410 to 0x841F are unnecessary since these flash protection bytes are useless in a relocated flash address besides 0x410~0x41F. We can remove the definitions and free some flash memories for user code and EEPROM emulation.


In order to free these bytes, we must search source file and icf file who might hold them. This topic has not been covered here.


Debug Skills


You can debug both bootloader as well as user application with FRDM-KL25Z. Amazing !


It is easy for debug bootloader, since it is a regular application. How to debug a relocated user application? You can download the firmware by bootloader. After bootloader transfers control to the user application, you have to debug it in disassembly Window.


Or you can download the user firmware as a regular application in debugger. The debugger will stop at main( ) of user application. If you want to debug the code before running main. Simply add more breakpoint, press reset. The debugger will tell you if you want to stop running to main. Click "stop", you will be forwarded to the address of user PC points to.


By using these skills, I found my bootloader pll_init( ) has some side-effects on user application's pll_init( ). The debugger is very helpful in debugging both bootloader and relocated user firmware. Compare to IAR's debugger, Eclipse's debug Window is a mess. It has not reset button at all. That is why I usually use IAR for development and port to GCC later on.


More Features


FSL bootloaders only offers a basic framework. The users will need more features in future development. I am preparing following features when I am available.


License file

Including SNR and installation, activation, authentication as well as user API. By this license program, the firmware developers can monetize their IPR investment.


User files

Support emulated file with on-chip flash memories, Including drivers, html and other files. It is a handy feature since the users can access the related driver easily. And these files can be read-only and virus-proof. This files can also be used as keys for access control and other security applications.



Since bootloader can be used as part of user application, we can integrate some important ROM API, like authentication, serial communication, and any other algorithms. It is simple to implement, define a dedicated code section, and use KEEP directive avoid optimization by the compilers.




I have changed some code during this release. Like bootloader_task.c .FlashConfig should be updated to protect 32KB or 24KB. The current figure 0xFFFFFFFE only protects one block, aka 4KB.  And it is heavily device dependent. (Please correct me if I am wrong)


So maybe there are still a lot of bugs. Feel free to leave your comment.


I only tested it with S-record file, you are free to test it with CW binary and raw binary files. Even the S-record file, I have not tested those files with memory gaps in the file. Maybe you should padding the gaps with 0xFF before download.

2 people found this helpful