Compiling your own CMSIS Code for the mbed
How-to Compile with plain CMSIS v2.00, with libc (newlib)
1. Download and extract the Lite Edition of Code Sourcery’s ARM EABI toolchain. This is a precompiled gcc toolchain targeted for ARM EABI, which can produce binaries for the LPC1768 on the mbed or any other Cortex-M3 microcontroller. It comes with the newlib implementation of libc.
2. Browse or download the ready-to-compile example project here: http://github.com/vsergeev/mbed-cmsis or mbed-cmsis master zip
3. Add the toolchain binary folder to your path, and run make in the sample project.
$ export PATH=$PATH:/path/to/arm-2010.09/bin
$ make
4. If everything went well, you should have produced mbed_test.bin. Upload this to your mbed and run the program, LED1 should flash on and off indefinitely. A quick side note: I’m pretty sure that the LED isn’t flashing at 100ms like the code specifies, this probably means that the configuration in system_LPC17xx.c isn’t tuned exactly for the hardware setup of the mbed.
Or, to assemble the project yourself:
1. Download and extract the LPC17xx flavor of CMSIS v2.00 from NXP. This includes CMSIS v2.00: the header files characterizing the system and peripheral register addresses for the LPC1768 that’s on-board the mbed, as well initialization helper functions, the startup assembly bootstrap, etc—essentially the low-level code for initializing Cortex-M3’s at runtime. NXP also included a wide variety of drivers for the peripherals of the LPC17xx that offer easy / high-level interfaces for their functionality.
2. Prepare a project folder with the relevant source and header files.
There’ll be a handful that you’ll need out of CMSIS archive:
- LPC1700CMSIS/Core/CM3/CoreSupport/core_cm3.c
- LPC1700CMSIS/Core/CM3/CoreSupport/core_cm3.h
- LPC1700CMSIS/Core/CM3/CoreSupport/core_cmFunc.h
- LPC1700CMSIS/Core/CM3/CoreSupport/core_cmInstr.h
- LPC1700CMSIS/Core/CM3/DeviceSupport/NXP/LPC17xx/system_LPC17xx.c
- LPC1700CMSIS/Core/CM3/DeviceSupport/NXP/LPC17xx/system_LPC17xx.h
- LPC1700CMSIS/Core/CM3/DeviceSupport/NXP/LPC17xx/LPC17xx.h
- LPC1700CMSIS/Core/CM3/DeviceSupport/NXP/LPC17xx/startup/gcc/startup_LPC17xx.s
- LPC1700CMSIS/makesection/makerule/example/ldscript_rom_gnu.ld
- main_LPC17xx.c
- Makefile
The first seven files comprise what is typically the single LPC21xx or similar ARM7TDMI microcontroller’s header file. The following file is the startup assembly bootstrap. The next two files come out of an example project employing CMSIS, which we’ll adapt for our purposes and future projects. The first of these two is the linker script, the second is a short LED flashing program. The very last file is a Makefile to compile these kinds of projects.
3. Make a few modifications to these files.
- Delete the “GROUP(-lgcc -lc -lcs3 -lcs3unhosted -lcs3micro)” line (line 21) from LPC17xx.ld linker script. I don’t believe we have the luxury of linking to some of these cs3 libraries with the free CodeSourcery toolchain (they’re probably for the full commercial versions?), but we don’t need to either.
- Change “_start” to “main” on line 147 in startup_LPC17xx.s.
4. Add the toolchain binary folder to your path, and run make.
$ export PATH=$PATH:/path/to/arm-2009q3/bin
$ make
5. If everything went well, you should have produced mbed_test.bin. Upload this to your mbed and run the program, LED1 should flash on and off indefinitely. A quick side note: I’m pretty sure that the LED isn’t flashing at 100ms like the code specifies, this probably means that the configuration in system_LPC17xx.c isn’t tuned exactly for the hardware setup of the mbed.
If you’re interested in avoiding as much of CMSIS as you can, check out my barebones bootstrap assembly, linker script, and initialization template here: http://github.com/vsergeev/mbed-cmsis/tree/master/mbed-barebones (or extract the mbed-barebones folder from the archive here mbed-cmsis master zip). It’s not perfect, but you can easily tweak it to your needs. As a warning, I wrote it out of the LPC21xx/ARM7TDMI style, so it might not be fully up to date with some of the Cortex-M3 practices out there (like the interrupt vector table declared directly in C, see http://www.embedded.com/design/testissue/220900313).
How-to Compile C++ Code with the mbed library
See Adam Green’s great work on this here: https://github.com/adamgreen/gcc4mbed !
In addition to: http://mbed.org/forum/mbed/topic/2701/ and http://mbed.org/forum/mbed/topic/2336/
Some thoughts
The mbed is a pretty neat development platform based on the LPC1768, part of NXP’s new Cortex-M3 series. I suppose it’s a kind of marketing project to promote the LPC1768, similar to other such “community-oriented” projects: STM32 Primer2, or TI MSP430 Launchpad.
However, a somewhat common complaint of the mbed is the online compiler, a “modern cloud solution” to the problem of distributing (and maintaining) a free toolchain, IDE, and other extras to accompany the fairly inexpensive mbed hardware platform. The mbed project hasn’t seemed to be particularly open about the details of what the online compiler is actually doing, though there is a svn repository that gives some clue of the underlying firmware glue.
To be honest, the thing I like about these arduino and arduino-“inspired” movements is the nifty development boards that come out of them, not so much the rapid development Wiring-esque language that accompany these platforms. Also, I felt like the mbed hardware at least deserved to be completely “unleashed” to C code I could optimize by hand and larger projects that are easier to manage on my computer rather than the online compiler. So I was interested in actually figuring out how to compile code directly for my mbed without the help of the “cloud”.
The LPC1768 folder of the svn repository trunk reveals several object files that belong to another more general project called CMSIS, or Cortex Microcontroller Software Interface Standard. CMSIS is an interesting project that I’m really having a hard time making up my mind on. I believe it’s ARM’s attempt at a kind of standardization or at least distribution of the startup code, linker script, and low-level initialization details which you were pretty much “on-your-own” with, on ARM7TDMI microcontrollers (not necessarily a bad thing though, right?).