Bootloaders are a fine thing: With this I can load any applications I like. Power comes with some complexity, and a bootloader alone is a complex thing already. But this applies to the application part too: I need to link the application to a certain offset in the memory space so it can be loaded by the bootloader, plus the application typically needs to add some extra information to be used by the bootloader. This article describes how to build a bootloader application with Eclipse (MCUXpresso IDE) using the MCUXpresso SDK.
I’m using the Eclipse based MCUXpresso IDE V11.0.1. Instead ‘hacking’ the linker file, I’m using the built in managed linker script way to automatically relocate the application to an address. In Tutorial: Porting BLE+NRF Kinetis Design Studio Project to MCUXpresso IDE I already used the FreeMarker mechanism, but here I show how it can be used on higher level.
The needed files are available on GitHub so you can copy the files from there: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/tinyK22/tinyK22_Blinky
The idea is to switch between ‘no bootloader’ and ‘bootloader application at address’ using Eclipse Build Configuartions. Create a new build configuration. Name it like “BL_<application offset>”, e.g. “BL_0xA000”:
💡 The naming is important, because I’m going to recognize in a script if it is a bootloader application (starting with “BL_”) and at which address the application shall get linked too (Hexadecimal number).
The Bootloader needs a configuration data. I have put it into a ‘bootloader_config.c‘ and ‘bootloader_config.h‘. Add them to the project:
The bootloader configuration is only used in bootloader applications, so just turn it on with the following define in the project settings:
The IDE is using FreeMarker scripts which is a powerful way to generate linker script files. We are going now to extend and overwrite some of the default files. Create a folder named ‘linkscripts’ (Naming is important!) inside the project and create three files (you can copy them from GitHub:
- user.ldt: this contains user variables used in the other scripts
- crp.ldt: this contains placement of the bootloader configuration data
- memory.ldt: this defines the linker memory ranges
The user.ldt uses the build configuration name to generate linker variables for the application offset and the configuration offset:
This is how it looks in the generated linker file:
The crp.ldt is used to place the bootloader configuration data at the expected offset (0x340) inside the application memory after the vector table.
Inspecting the template files in <MCUXpresso IDE Installation Path>\ide\Wizards\linker, I see I could ‘misuse’ the ‘crp.ldt’ to place my bootloader descriptor after the vectors. Ideally the IDE would provide a dedicated template or hook. Instead I’m just making a copy of the existing crp.ldt and have it extended.
Below the result in the linker file:
Correct placement can be verified e.g. with EHEP:
Finally, the memory.ldt is building the memory map in the linker file with the application offset:
So based on the Build Configuration name it automatically links the application to the correct memory area :-).
Using FreeMarker custom scripts and Eclipse Build Configurations I can automatically build and link an application to be used with a bootloader. And I can use a ‘normal’ debug configuration to build and debug the application without the need for a bootloader.
Happy FreeMarking 🙂
- FreeMarker home page: https://freemarker.apache.org/
- FreeMarker Tutorial: https://www.vogella.com/tutorials/FreeMarker/article.html
- Tutorial: Porting BLE+NRF Kinetis Design Studio Project to MCUXpresso IDE
- Bootloader with KL03Z: Getting Started: ROM Bootloader on the NXP FRDM-KL03Z Board
I am back working on my bootloader again and you make this timely post today…
Anyway, I figured I would just start with your code and make it work for me.
I downloaded your tinyK22_Bootloader, and have it compiled and working in MCUXpresso 11.0.1.
Now I switch over to my target hardware which is the K22FX512 (instead of the K22FN512) and am line by line making it work. I fixed up the problems caused by the FTFA /FTFE flash module differences, and the code gets past that.
Now I get hung up at the clock_mode_switch() function. It is trying to change to the FEE mode and is waiting forever for the external reference clock to be ready.
Your board probably has a 8 Mhz or 4 Mhz crystal. My board has a 16 Mhz crystal.
I know my board will run at 120Mhz with the USB at 48Mhz if I use PEE mode.
What do you think the easiest way to get the clocks happy on my board are? I tried going into the clock cfg tool but it looks like it had nothing set, which implies your code did not use the clock tool.
I think the MCG module is the same between the FN and FX.
my robots use the K22FX512, but I have not ported/run the bootloader on it (yet). The robots do have a 8 MHz crystal too.
I did not check the details, but to my understanding (and experience) the FN and the FX are completely different parts, so I think the MCG is different too.
I did not use the clock tool for the bootloader (It seems the SDK engineers providing the example did not use it neither): one way would be indeed to use the clocking tool and to copy that code somehow.
I now have my K22FX bootloader working. I can send you the details of what I did if your interested.
The trick was starting with the K64F120 MCUXpresso SDK 2.6 bootloader demo,
as that processor has the same FTFE flash module as the K22FX512.
The other trick is getting the clocks right, as the bootloader demo insists on trying to use the self-clocking feature of the USB, which doesn’t exist on the FX.
I used the MCUXpresso clock tool to set the clocks right, but then there is a vital function to set the usb clocks that the code generated by the clock tool did not bother to call. I could only use the USB HID version of the bootloader, as those are the only wires available [actually I do have CANbus also]
I’m definitely interested in that bootloader details for the FX part. I won’t be able to roll this out on our robots for this semester, but ther is a new semester coming soon :-).
I’m struggling with the clocks tool too: I like the graphical view, but now the tool exposes the settings pretty much the same way as the reference manual (which is hard to understand), so it is very difficult for me to get a clock configuration right using the clocks tool. This was much easier back with Processor Expert.
I also like the visual part of the clock tool, but what I’ve learned about it from the problems I’ve had to solve are at least these two things:
1) after setting up the all the clocks visually with the clock tool, I assumed calling
BOARD_InitBootClocks() which calls BOARD_BootClockRUN() (in the Board\clock_config.c file, which was generated by the clock tool) would set the clocks to to what I chose with the clock tool.
BUT! it turns out that the USB clock is NOT initialized.
I added this line just before the end of BOARD_BootClockRUN()
That line enables the USB clocks with the code the clock_tool generated but never called. the 0x50000 is the correct bits to enable it for me, I didn’t figure out exactly what the right macro to do the same is.
2) It is not enough to set the clock mode that you want. To get to the PEE mode I wanted with my 16Mhz external crystal, a different clockmode is passed through on the way there (I think it was PBE). The clocktool did not know enough to set up the internal 4Mhz correctly so that as the current clock mode stepped from the boot default to the desired PEE mode, it would not get hung up in between.
So, I think the clock tool needs to be debugged – it should either just work for whatever I set up, or it should tell me what else needs to be done for my desired mode to work right. If I set up a USB clock, the generated code should call the initializer for that. If it passes through some intermediate mode(s) on the way to my desired final mode, it should either set up all those needed intermediate modes, or tell me that I need to set them up, and why.
Pingback: Debugging Bootloader and Application with one Debug Session | MCU on Eclipse