Tutorial: Using the ARM CMSIS Library


One of the great advantage of using an ARM core as on my FRDM-KL25Z board is that I can leverage a lot of things from the community. And one big thing around ARM is CMSIS (Cortex Microcontroller Software Interface Standard). It is an industry wide software library for the ARM Cortex microcontroller. Using the CMSIS libraries and interfaces will make it easier to port applications within the ARM Cortex family.

CMSIS Version 3 Block Diagram (Source: Arm.com)

CMSIS Version 3 Block Diagram (Source: Arm.com)

CMSIS has evolved over time, and even has added an RTOS API (CMSIS-RTOS API). What is the most interesting for me now is the CMS-DSP part of it: a set of over 60 functions for fixed point and floating point library routines. So how to use it in my project for the ARM Cortex-M0+ on the Freedom board?

For this Tutorial I’m using the Eclipse based CodeWarrior for MCU10.3, the CMSIS version V3.01 and the ARM GNU build tools with the Freedom FRDM-KL25Z board. As steps are pretty generic, that should work for other combinations too.

Downloading CMSIS

CMSIS is provided free of charge by ARM from their Silver Portal. On that Self-Service Portal there is a ‘Downloads’ link, but downloads are only available after I’m registered.

CMSIS Download Page

CMSIS Download Page

The current release is V3.01 and downloaded in a zip file of about 44 MByte in size.

Installing CMSIS

To simplify things, I have the CMSIS zip file unpacked inside my workspace. It creates the folders ‘Device’, ‘CMSIS’ and a file with the version number:

Installed CMSIS

Installed CMSIS

Creating a Project

Inside the workspace, I create a project for my board using the File > New > Barboard Project wizard to create a GNU gcc project. This creates a default project for me:

CMSIS CodeWarrior Project

CMSIS CodeWarrior Project

Instead of writing my own example, I’m using one which is part of the CMSIS installation:

sin cos example

sin cos example

:idea: ARM provides many such examples. They are a great way to verify that they work properly in my application. One consideration with using the libraries is their stack consumption. If they work as the simple example, but not within my application, then typically I have not reserved enough stack space. At least worth a try.

An easy way to add this file to my project is to drag&drop it into my project Sources folder. As the example comes with a main(), I can remove the original main.c from my project:

Added Sin Cos Example

Added Sin Cos Example

Creating a Build Variable

We need to reference the CMSIS installation path in the next steps several times. To make things easier and more portable, I’m going to add a Build variable. For this I press ‘Add’ in the project properties > C/C++ Build > Build Variables:

Adding a Build Variable

Adding a Build Variable

In the following dialog I define my variable and press OK:

CMSIS_LOC Variable

CMSIS_LOC Variable

:!: Of course you should use a path pointing to to where you have CMSIS installed. For me, it is is “c:\tmp\wsp_cmsis\CMSIS” in this tutorial, so you need to use the path which you have on your system.

With this, I can always use

${CMSIS_LOC}

instead of a hard-coded path.

Defined Build Variable

Defined Build Variable

Using CMSIS

The above project will not compile and link. I need to tell the compiler where to are the CMSIS header files, and what library to link.

Header File Include

The CMSIS header files are in CMSIS\Include, so I add this to my compiler include paths:

Compiler Directories Setting

Compiler Directories Setting

:idea: I’m using here the CMSIS library inside my workspace. Change the path if you have the CMSIS installed somewhere else.

Architecture Define

The other important thing is: I need to set a define which tells the CMSIS library which ARM Cortex core I’m using. For the ARM Cortex-M0+ this is ARM_MATH_CM0. I add this define to the project properties of the ARM gcc preprocessor settings.

Added ARM_MATH_CM0 to the Preprocessor Defined Symbols

Added ARM_MATH_CM0 to the Preprocessor Defined Symbols

:idea: If using an ARM Cortex-M4 (like for the Kinetis K family), then the define would be ARM_MATH_CM4

Library

CMSIS already comes with pre-built libraries. So all what I need to do for gcc is to link the correct libraries with my application. The libraries are inside CMSIS\Lib\GCC:

GCC CMSIS libraries

GCC CMSIS libraries

:idea: The M denotes the ARM core, while the ‘l’ means ‘little endian’. The ‘f’ means an ARM core with Harware Floating Point Unit (e.g. Cortex-M4F).

With this information, I add the library name and the library search path to my linker settings:

Linker Library Settings

Linker Library Settings

:!: Important: the library name is *without* the ‘lib’ prefix and *without* the ‘.a’ suffix! See Creating and using Libraries with ARM gcc and Eclipse.

Build and Debug

With this, everything should be in place to compile, link and download without errors. But if I step into the CMSIS functions, I get a message from the debugger that it cannot find the source file:

Can't find a source file

Can’t find a source file

The reason is that I’m using the precompiled libraries from ARM, and obviously that person was using a different path to the CMSIS library.

To help the debugger to find the source, I’m going to add a path mapping. I press the ‘Edit Source Lookup Path’ button:

Edit Source Lookup Path

Edit Source Lookup Path

Then I select Path Mapping:

Add a container to the source lookup path

Add a container to the source lookup path

Then I specify that ‘c:\working\CMSIS_Setup\CMSIS shall be replace with the path on my machine:

Specified Path Mapping

Specified Path Mapping

:?: I would love to use my ${CMSIS_LOC} variable in that dialog, but this is not supported in this Eclipse version? That would be a great feature extension.

Now it shows the source properly:

Showing CMSIS Source

Showing CMSIS Source

Summary

Using the CMSIS from ARM is a great add-on to my applications: I can take advantage of DSP and other functionality without writing them myself. All what it needs is to set configure my project to use one of the precompiled libraries.

My current CMSIS library and application project are on GitHub.

Happy CMSISing :-)

About these ads

8 thoughts on “Tutorial: Using the ARM CMSIS Library

  1. That is very helpful… especially how to overcome the path problems. It would be helpful to know your suggestions on some of the specific functions that you would recommend. I don’t do floating point calculations because of the excessive amount of code generated (at least under the 9sx12 series when I last used them). For the calculations that need decimal point accuracy I do these in Q16 and Q32 format, then use the pc app to do the resulting arithmetic to get to decimal precision. Although I know there are probably times floats have to be done on the embedded side…..

    That is when you have time…. :)

    • Yes, I avoid floating point operations wherever I can if my micro does not have a hardware floating point unit. The thing with CMSIS and Cortex is that some have DSP like functions, and with CMSIS they can be easily used.

  2. Hi.
    I am already worked with CMSIS library with Kinetis MCUs (K60, K40, K20, K10 series). It was hard to get started because of misconfiguration CMSIS into the project. But Freescale support helped me.
    This tutorial is very helpful – all information in one place.
    Thanks.

    • Yes, it took me a while too to sort out things. I was running into a GNU linker problem (number of object files linked). The good news is: according to the ticket, this should be resolved soon in MCU10.4 :-)

  3. Pingback: Review of CodeWarrior for MCU10.4 | MCU on Eclipse

  4. Pingback: Low-Level Coding with PDD (Physical Device Driver) | MCU on Eclipse

    • The CMSIS library is more about library functions (like DSP functionality), but not much about the core. There are the CMSIS-CORE header files which are for the different cores produced by the different vendors (TI, STM, NXP, Freescale). On the other side: CMSIS is for ARM cores, and the ARM Inc. licensing terms say if I remember right they only should be used for ARM cores. Given the fact (if the industry continues with the current pace), there are probably not many non-ARM cores in the future any more, or only niche non-ARM cores. Just how I see things evolving at least over the last few years.

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s