Post Image
By Matt GaidicaDecember 13, 2020In Uncategorized

Configuring CMSIS DSP Package and Performing a Real FFT

A benchmark of fast Fourier transform (FFT) speed suggests that using the internal floating-point digital signal processing (DSP) hardware in some of the ARM Cortex devices (e.g., Texas Instruments (TI) CC2652RB, Cortex M4) is the way to go—it essentially optimizes and accelerates. I’m not the first to have some issues making this work, so I’m going to discuss how I did it. The first section is specific to compiling the library (CMSIS Documentation) in Code Composer Studio (CCS), and next, testing the FFT on-chip against ground truth data in MATLAB.

Compiling CMSIS DSP in CCS

There is one E2E Support Forum post concerning CMSIS DSP for TI devices. I had some issues with those directions and found that arm_cortexM4l_math.lib provided in the CMSIS Library was somehow not properly configured: it needed to be recompiled from source.

I downloaded the CMSIS Pack from the latest CMSIS release. The ZIP file won’t include the .lib files, but since you’ll be building that, I don’t think it matters. To extract a .pack file, use the terminal command unpack200 source destination. Then you can right-click the resulting .jar file and extract it using The Unarchiver tool.

For the DSP functions, you are just packing all the files in CMSIS > DSP > Source into a library. The E2E post referenced above, and the cited application report SPMA041G suggest downloading patched CMSIS DSP files, but I don’t think that applies to all (or more recent) applications. I did not patch CMSIS (version 5.7.0) before compiling.

Another discrepancy from previous articles was that the include files were a bit all over. It took some digging to realize that was a major source of the compilation errors. Here are the important pieces of getting the library to build:

  1. Create a new CCS Project as a static library (as the SPMA041G app report suggests).

  2. You need includes from 3 places in Properties > CCS Build > ARM Compiler > Include Options > Include search path.

    1. CMSIS > DSP > Include

    2. CMSIS > DSP > Private Include

    3. CMSIS > Core > Include

  3. Right-click the project and import the CMSIS > DSP > Source folder.

  4. Build the project.

This will compile everything into a new .lib file in the Debug folder. The only warning remaining regards __COMPILER_BARRIER; I don’t know what this is, but it doesn’t seem to matter so far. To use the library in other projects:

  1. Add the same includes to the ARM Compiler (you need the header files). You can copy all of them to one place to make it easier.

  2. Add the library to the properties ARM Linker > File Search Path > Include library file.

  3. Include the proper header files:

#include "arm_math.h"
#include "arm_const_structs.h"

Performing a Real FFT using CMSIS

I used MATLAB to create a test signal that was a 5 Hz + 25 Hz cosine (Fs = 250 Hz); my main requirement was that it creates a distinct frequency response to compare with the results on the MCU.

The MATLAB code will export the signal to raw values that can be included in C code as a header file. The code below is the basic structure of how to accomplish the FFT.

Most importantly, the results match the ‘ground truth’ example from MATLAB. For this example, finding the max bin isn’t as helpful as if there were one fundamental, or dominant frequency (5 Hz and 25 Hz should have the same power).

Top: Single-sided |Y| spectrum, Bottom: phase response in radians

Top: Single-sided |Y| spectrum, Bottom: phase response in radians


  • The documentation states: “real[0] represents the DC offset, and imag[0] should be 0.” In my experience, the DC offset was present but imag[0] was non-zero. I don’t know why.

  • The DC offset could be removed from the signal beforehand (e.g., filtering or subtracting the mean), but if it’s included, take care to not include it in finding the max bin and value if that’s your goal (as demonstrated in the sample code).

  • inputSignal is written over in-place, so if this code is in a loop, make sure that variable is refreshed with new data.

svgOn Optimal Timestamps for Bio-loggers
svgImplementing a Biquad Cascade IIR Filter on an ARM Cortex M4 using CMSIS DSP