Frank's Random Wanderings

Freescale Kinetis USB Bootloader

I’ve been doing some work with a Kinetis MKL25Z128 Cortex-M0+ processor. I love what you get for the very small amount of money this thing costs. It even contains a 16 bit A/D converter, which is very rare at this pricepoint. Along with everything else, it contains a USB port.

There are a number of Freescale application notes about how to use the USB port, implement bootloaders, etc. To be honest a lot of them are a bit of a mess, and if you frequent the Freescale forums you’ll see plenty of discussions with people asking pretty basic questions (like, why doesn’t the sample code even compile). So to find something actually working is a bit of a rarity.

Freescale has an appnote called AN4764 which describes a very small USB bootloader. The whole thing compiles down to only around 4 kB of flash which is quite impressive. They also provide a simple PC application to work with it. The source code, appnote, etc, can be found here:

AN4764 Simple HID Bootloader

The source code zip file in the link above contains prebuilt images for most processors, but for some reason the MKL25Z128 processor (also known as the “Freedom board” processor) is missing. IAR is required to build the projects. (Why Freescale used the IAR compiler instead of their own CodeWarrior compiler is another unsolved mystery.) I installed the small (32 kB code size) free version of IAR and built the MKL25Z128 project. To save others from needing to do the same, I’ve posted the entire project, including the executable and the appnote PDF, here:

Click here to download the files.

The function Check_Bootloader_Mode() in file kl25z_bootloader.c has been modified to remove most of the checks it was doing. It used to calculate & compare a checksum on the application, plus it looked to see if a couple of words of flash were erased. Now all it does is looks at GPIO bit PE31 – if that pin is low it runs the USB bootloader, and if that pin is high it runs the application. That’s it.

For a quick summary of how to use it, you program it into your processor. To cause the USB bootloader to run GPIO PE31 needs to be low after reset (ie, put a switch on PE31 and hold it low during reset or poweron). When plugged into a Windows PC it’ll be recognised as a HID device. Then run the PC application to download application code. Your application code needs to be built for a start address of 0x1000, seeing as the bootloader lives at the bottom 3.5 kB of flash. Do that by editing your linker file. Then somewhere at the beginning of your application code you need to point the processor to your new interrupt vector table (if you’re using interrupts), like so:

Once your application starts, interrupts will be disabled. In CodeWarrior you can use the following macros to enable and disable interrupts:

That’s it. This is a super-easy way to get a USB bootloader running on a Freescale Kinetis processor.

Update Oct 2014
I’ve made a minor update to the bootloader (link to the file is above) to correct a problem where sometimes, if you don’t have an external pullup resistor on Port E bit 31, the bootloader might not always jump to your code. The reason was the code didn’t always wait long enough after a power-on, when using the internal weak pull-up. I’ve increased the delay a little (just a millisecond or two) to give it a little extra time to detect PE31 as being high. Ideally you should have an external pull-up resistor on PE31, but if you want to save a penny and don’t have one, this minor change helps.

6 thoughts on “Freescale Kinetis USB Bootloader

  1. Tom

    Thanks for you advice. I tried it using your prebuilt HID bootloader and it worked fine. I then tried simply recompiling your Lite Bootloader source project for Freedom and it did not work. The board does come up as an HID but when I try to load the blinky freedom srec file, it fails as if it can’t connect. Any ideas as to what I did not set correctly? The only thing I had to set was that I was using CMSIS-DAP as my debugger. I don’t think this is a problem, because as I said, it worked fine with your pre-compiled copy. I am using IAR 7.3 kickstart.

  2. frank Post author

    Sure, you can if you want to. If your application code wants to change SCB_VTOR later, it can do that at any time, so setting it in the bootloader doesn’t hurt.

    Just to be clear, the bootloader does NOT jump to 0x1000. The bootloader loads the (application code start) address from address 0x1000, then jumps to that address.

  3. Tom

    Thanks for the reply. I will try it out. Since the jump to 0x1000 is hard coded in your bootloader, any reason I can’t put the SCB_VTOR assignment right before the call to the user application?

  4. frank Post author

    I didn’t change the starting address for the bootloader code. The bootloader code places its own vectors at 0x0 and places its code following the vectors. So the bottom part of flash is used by the bootloader. By starting your code (or your vectors) at 0x1000 you’re safely above the bootloader.

    You can place your own vectors in flash or in RAM, your choice. If you’re going to be changing them during runtime (common in the case of an RTOS) then of course place them in RAM. If you’re not going to be changing vectors during runtime then certainly you can put them in flash. Which is what I do. Regardless of where you put them, or copy them afterwards, before you enable any interrupts you need to inform the processor where your vectors are – I show how to do that in my blog post by writing to the SCB_VTOR register. The SCB_VTOR register defaults to zero (0x0) so if it’s not changed to point to your own vectors, any interrupts that happen will use the bootloader vectors, which is not very helpful when you’re trying to run your own program.

  5. Tom

    AN4764 says to copy the vector table to RAM, but you do not do this. It also looks like they are putting the code at 0x10C0 which I assume leaves room for the vectors at 0x1000. Did you change the starting address for the bootloader code?

    Tom

Leave a Reply

Your email address will not be published. Required fields are marked *