Post navigation

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 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

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

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

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

sin cos example

💡 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

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

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

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

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

💡 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

💡 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

💡 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:

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

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

Then I select Path Mapping:

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

❓ 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

On a side note: the debugger launch configuration has as well a panel to configure where the debugger is looking for source files:

Debugger Source File Mapping

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.

About Erich Styger

58 thoughts on “Tutorial: Using the ARM CMSIS Library”

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…..

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.

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 🙂

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.

Hi, Erich!
I’ve been reading your web site for weeks and you’ve been of great help! Thank you and congratulations for all the contents you’re making available for everyone out there, like me.
I’ve used this particular tutorial a couple of weeks ago when I started using CMSIS. A couple of days ago, I changed the computer at work. I had to install CodeWarrior and the CMSIS library all over again. Every thing seemed to be ok, until I tried to build the project (The same project I was using in the old computer).
I got an error from the linker saying the m_text was overflowed. Looking at the .map, I found the problem but cannot seem to find a solution. What is happening, and did not happen before, is that the linker includes all the variables from arm_common_tables.o!
Do you know how i could change the settings so as to solve this problem?
If you need, I could upload both .map, before and after the computer change.

Hi Juan,
thanks 🙂
if m_text overflowed, this means your code is larger than your FLASH. Could it be that you link/compile more stuff?
Maybe your compiler optimizations are not the same?
What you could try is to increase the FLASH memory size in your linker file (just be able to link), so you can inspect the .map file what is taking so much space?

Hi Erich!
Thanks for the reply.
I already did what you said.
Actually, that’s how I found that there was a difference between the CMSIS versions.
I managed to solve the problem by using and old version of it (3.20) instead of the newer on (4.00). I can’t tell why, but I suppose they build there library in a static manner , and not dynamically.
So, that’s it.

Hi Erich,
I do see CMSIS folder under my project’s ../SDK/Platform/CMSIS
My thought is that it should be getting built, and the problem happens during linking. Here is the Console log at the trailing end:

Hi
I am trying to implement FFT transform in FRDM KL25Z which is cortex M0+ using codewarrior 10.6. I have downloaded the CMSIS 4.2 library and tried the procedures mentioned in above. But i am not able to implement them successfully, I am getting some errors even when i tried to implement some example codes. Can any one help me with this issue.

Hi Charan,
I pretty much moved away from CodeWarrior and using either Kinetis Design Studio or Eclipse Kepler with gcc/gdb. So not sure if your problem is related to CodeWarrior, but as there are no further details you have provided, it is hard to tell.
Erich

Hi Erich,
I am new to CodeWarrior,Can you please tell me what are the details that need to be provided …?
I am trying to impliment Your CMSIS_kl25z_app example with CMSIS_Library for FRDM KL25Z. But while debugging i am getting error at “in = x * 0.159154943092f + 0.25f;” in arm_cos_f32.c as No source available for “__aeabi_fmul (0x00000E80)() ” .

Hi Erich
In this post is the only place I could find at least some mention about “path mapping” or “source file lookup” problems. I already know the dialog which is displayed, if source code you want to step into when debugging, is not available. One of my questions is: is there another place, where you can edit existing mappings? Like in the Project Properties (haven’t found it yet)? I have a weird situation where my project, which I want to debug, jumps to the same file in a copy of the project in another location.
I am using Code Warrior 10.3 on Windows so far, but maybe soon moving to 10.6, because I need a license anyway (Code Size exceeded).
Any suggestions are appreciated.
Cheers, Adrian

Hi Adrian,
yes, there is a panel in the debug configuration settings, a tab labeled ‘Source’. I have added that information/screenshot at the end of this article. This one should be present as well in your CodeWarrior version.

Hi Erich, i had tried to port this to the KDS 3.0.0,CMSIS 4.3, i got no errors but when i step through the code the cosOutput and senOutput variables never change, i know it’s hard to know but what can be the problem?.

Hi Victor,
it has been a while since I used that library (using my own one instead). Have you turned on optimizations? This might result in code where it seems that the variables do not change, as the compiler keeps them in registers. Have you stepped through the assembly code to see what is going on?

Hi, Erich.
I’m using the CMSIS DSP library on KDS 3.0.0, running a MKL26Z64 on a custom board. Some functions, as the cosine and sine, work. Others, like the sqrt and the FFT give me a hard fault. I tried debugging using your HardFault component and disassembling, only to find that apparently the program is trying to access a memory address it cannot read. What could it be?

Hi Gustavo,
or it could be something with the library. uVision5 is not using the same CMSIS library, right? Maybe there is a compatiblity problem between the library you use and the compiler you use. I have seen such problems in the past, and they got resolved once I have rebuilt the source file or library with the compiler I use. You will not need to build the whole library: add the files/functionality of CMSIS DSP sources to your project should be good enough.

HI Eric,
I am using the KSDK 1.2 with Kinetis Design Studio 3.0. I have been trying to use the cmsis dsp library without any success so far. When using processor expert, it seems like the library is already included automatically by PE. However, I cannot use any function of this library. I am especially interested in the digital filter part of the dsp library. Do you have any tutorial or advices how to access this library ?
thanks
Hung

You are very welcome! I was in that trap first too, not realizing that I need to use special naming convention for the linker. It is not logical, but that’s the way how the GNU linker is working with libraries.

Hi Eric
Looking at the current picture of the current CMSIS architecture diagram, Is it correct to think that KSDK would be contained in the purple square named “Device HAL (Silicon Vendor)”? It seems to me that would be the way of thinking about CMSIS and KSDK but I’m not sure.

Hi Manuel,
The Kinetis SDK v1.x includes a device HAL layer, so yes, for that SDK the Kinetis SDK HAL would be that purple box. And the rest of the Kinetis SDK v1.3 would be that CMSIS-Driver green box. But the Kinetis SDK is *not* built with the CMSIS-Driver API, it is using its own silicon vendor API.
In the Kinetis SDK there is no special HAL layer any more needed. Here again, Kinetis SDK is not CMSIS-Driver API, but doing the same/similar thing.

Erich
Thanks for the reply, nevertheless I still confused and here is why. This is my thought about how this idea of a vendor independent CMSIS and vendor HAL should work.

I have a Kinetis K64 and a STM32F4 MCUs. I’m creaitng an application that should work in both MCUs so what I’m thinking is that I can put the CMSIS framework in both MCUs and build my application in top of that, this way my application will be totally hardware independent and portable between this two micros. The only difference is at the HAL layer and since “…the software interfaces across all Cortex-M silicon vendor products [is standardized]” and “…CMSIS enables consistent and simple software interfaces to the processor for interface peripherals, real-time operating systems, and middleware.” (according to the CMSIS website), I should be able to just “switch” between kinetis HAL and STM32 HAL depending on the MCU I need to use, the same applies for the vendor-specific middleware (both purple boxes in the diagram).

I understand that for example UART could be much more complex between MCUs and there is where a “specific vendor driver API” that extends the “CMSIS-Driver API” will work, but for generic UART configuration I could use just CMSIS APIs.

Am I seeing this the wrong way? I mean, it seems that this way it could justify having a CMSIS, and a KSDK, and a STM32CubeF4, etc. Otherwise is really confusing if KSDK can be used “instead” CMSIS and if I build my application in top of KSDK it would be difficult to port it to the STM32.

Hi Manuel,
I understand that confusion. As said, the Kinetis SDK is not following CMSIS-Driver, so therefore what you describe is not possible: if only one vendor is following CMSIS-Driver, but not the other one, you cannot switch between them. To me, every vendor still wants to do their secret sauce stuff, and this makes things not compatible. It is not the fact that STM and NXP sell ARM cores (they are a commodity), but they create their value proposition with their specific and custom perpherals (and drivers). I think things will change in the future. You might have a read at https://mcuoneclipse.com/2016/02/14/are-arm-cmsis-pack-the-future-of-software-components/ and the discussion there as this goes into a similar direction.