Using CMSIS-DSP hardware accelerated math libraries

Does somebody knows how to include and compile and use CMSIS-DSP libraries which are hardware accelerated (and also feature non square matrices which are not covered by AP_Math)?

CMSIS 4 http://www.keil.com/cmsis/dsp
CMSIS 5 http://arm-software.github.io/CMSIS_5/DSP/html/index.html

Usage

The library installer contains prebuilt versions of the libraries in the Lib folder.

  • arm_cortexM4lf_math.lib (Cortex-M4, Little endian, Floating Point Unit)
  • arm_cortexM4bf_math.lib (Cortex-M4, Big endian, Floating Point Unit)
  • arm_cortexM4l_math.lib (Cortex-M4, Little endian)
  • arm_cortexM4b_math.lib (Cortex-M4, Big endian)
    … others for M0, M3, M and Armv8 …

The library functions are declared in the public file arm_math.h which is placed in the Include folder. Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single public header file arm_math.h for Cortex-M cores with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. Define the appropriate preprocessor macro ARM_MATH_CM7 or ARM_MATH_CM4 or ARM_MATH_CM3 or ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application.

So I have added the CMSIS repository as a submodule in the libraries folder inside a TestLib folder.
I’m building for a PixRacer on Chibios.

Then in a test file:

#define ARM_MATH_CM4
#include "CMSIS/CMSIS/DSP/Include/arm_math.h"

#define N 3

I’ve declared a matrix like this:

static float TestMatrixData [N][N];
static arm_matrix_instance_f32 TestMatrix = {N, N, (float *) TestMatrixData};

// fill matrix with test data
for(int i=0; i<N; i++) {
	for(int j=0; j<N; j++) {
		TestMatrixData[i][j] = i*N + j;
	}
}

// matrix to hold transpose result
static float TestMatrixTData [N][N];
static arm_matrix_instance_f32 TestMatrixT = {N, N, (float *) TestMatrixTData};

// transpose function
arm_mat_trans_f32(&TestMatrix, &TestMatrixT);

I’m using waf. For a fast test I’ve simply added the following line

    '-L%s,-l%s' % (cfg.srcnode.make_node('libraries/TestLib/CMSIS/CMSIS/Lib/GCC/').abspath(), 'libarm_cortexM4lf_math'), #libarm_cortexM4lf_math.a

to env.LINKFLAGS in the class chibios(Board) in the file Tools/ardupilotwaf/boards.py.
Are there better places to add it?
I think the path is OK because if I change to a non-existent file it complains.

The TestLib files are compiled without errors, but when it arrives to linking:

Linking build/fmuv4/bin/arducopter
lib/libArduCopter_libs.a(TestLib.cpp.0.o): In function 'TestLib::TestLib()':
TestLib.cpp: undefined reference to 'arm_mat_trans_f32'

Have you any hints to resolve this? Maybe @tridge?
Probably I’m missing something stupid.

I can also try to compile CMSIS from source.

By the way using this library can lead to improvements in all the math calculations, i.e. a faster EKF. Can more experienced Ardupilot developers see reasons to not use it?

1 Like

hello,

Add the library to env.LIB and path to env.LIBPATH
on env.LINKFLAGS only add -L part
on env.CXXFLAGS and env.CFLAGS add -l part
And it should work.

I can think about plenty reason about why we don’t use it :

  • as you said : it can lead to improvement, but we need proof !
  • we don’t write it, so it something is wrong it will be hard to find it out
  • switching on it will need good knowledge on the lib and evalutation time, and I don’t think we got much people able to do that

Thanks @khancyr, I’ve done the following changes:

in boards.py > chibios(Board) > configure_env():

  • CMSIS_path = cfg.srcnode.make_node('libraries/TestLib/CMSIS/CMSIS/Lib/GCC/').abspath()
    
  • added library path to env.LINKFLAGS like '-L%s' % CMSIS_path,
  • added '-llibarm_cortexM4l_math', to env.CFLAGS and env.CXXFLAGS
  • added env.LIBPATH += [CMSIS_path]
  • added 'libarm_cortexM4l_math'to env.LIB

in chibios.py > build():

  • added 'libraries/TestLib/CMSIS/CMSIS/Lib/GCC/' to bld.env.LIBPATH

The error now is

... arm-none-eabi/bin/ld: cannot find -llibarm_cortexM4l_math

I can think about plenty reason about why we don’t use it :

  • as you said : it can lead to improvement, but we need proof !
  • we don’t write it, so it something is wrong it will be hard to find it out
  • switching on it will need good knowledge on the lib and evalutation time, and I don’t think we got much people able to do that

Do you have in mind some specific proof? I can do some tests if needed…

Ok, found it.

The steps are:

in boards.py > chibios(Board) > configure_env():

  • add library path to env.LINKFLAGS like '-L%s' % cfg.srcnode.make_node('libraries/TestLib/CMSIS/CMSIS/Lib/GCC/').abspath(),
  • add '-llibarm_cortexM4l_math', to env.CFLAGS and env.CXXFLAGS

in chibios.py > build():

  • add 'arm_cortexM4l_math' (WITHOUT ‘lib’ PREFIX!!!) to bld.env.LIB
  • add ‘libraries/TestLib/CMSIS/CMSIS/Lib/GCC/’` to bld.env.LIBPATH

Nice, good job !

About the test … I don’t know how to make a simple and effective test to see if it is worth it or not

Updated instructions to compile ArduPilot with CMSIS:

  • add submodule https://github.com/ARM-software/CMSIS_5
  • include CMSIS/DSP/Include/arm_math.h
  • add '-llibarm_cortexM4lf_math', '-DARM_MATH_CM4' to env.CXXFLAGS in class chibios of boards.py
  • add the following to chibios.py
bld.env.LIB += ['ch', 'arm_cortexM4lf_math']
bld.env.LIBPATH += ['modules/ChibiOS/', '<path to CMSIS module>/CMSIS/DSP/Lib/GCC/']

this for an M4, CMSIS supports also M0, M3, and M7, but we need some configuration rule to make it portable to the other ARM supported.

Unfortunately this also means that you can’t use this library in SITL… maybe HITL?