cancel
Showing results for 
Search instead for 
Did you mean: 

How do I install a newer version of CMSIS in the STMCubeIDE work environment to include PKHBT and VMAXNM/VMINNM?

Hansel
Senior

I noticed that STMCubeIDE version 1.9.0 refers to a fairly old version of CMSIS V5.2.0 from May 2019 while ARM has published 5.8.0 in the meantime. Is there a way to install a newer version of CMSIS in an existing project?

I have to two types of code in a timing critical interrupt routine:

mergedVal = ((uint16_t) maxVal << 16) | (uint16_t) minVal;

 and

if(x < minVal) {
    minVal = x;
 } else if(x > maxVal) {
    maxVal = x;
 }

There are three perfectly fitting assembler instructions PKHBT, VMAXNM.F32 and VMINM.F32 that fulfill exactly that purpose. However, in the cmsis_gcc.h file of version 5.2.0, __PKHBT is poorly implemented, actually not taking advantage of the availability of this assembly instruction. So I implemented it via the macro

#define PKHBT(ARG1, ARG2, ARG3) \
({ \
 uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
 __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
 __RES; \
})

which is actually commented out in cmsis_gcc.h.

VMAX and VMIN don't even show up in this file. I don't know if CMSIS version 5.8.0 have them actually as __builtin_pkhbt, __builtin_vmaxnm and __buitin_vminnm in the meantime so I need to find out.

When I tried to implement the commands for VMAXNM and VMINNM as follows

#define VMAXNM(ARG1, ARG2) \
({ \
 float __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
 __ASM ("vmaxnm.f32 %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
 __RES; \
})

I get the following compiler error:

Error: VFP single, double or Neon quad precision register expected -- `vmaxnm.f32 r3,r3,r2'

In summary:

  1. My preference would be to install the latest version of CMSIS in the hopes these assembly instructions are taken advantage of.
  2. If the above isn't the case, I would go with my own macro but would appreciate some insight what's wrong with the way I am setting up this macro.
1 ACCEPTED SOLUTION

Accepted Solutions
Hansel
Senior

OK, in the meantime I found the solution for #2:

#define VMAXNM(ARG1, ARG2) \
({ \
   float __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
   __ASM ("vmaxnm.f32 %0, %1, %2" : "=w" (__RES) : "w" (__ARG1), "w" (__ARG2) ); \
   __RES; \
})

And performance-wise it is indeed significantly faster to use

minVal = VMINNM(x, minVal);
maxVal = VMAXNM(x, maxVal);

than the if-then-else construct shown above.

View solution in original post

3 REPLIES 3
Hansel
Senior

OK, in the meantime I found the solution for #2:

#define VMAXNM(ARG1, ARG2) \
({ \
   float __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
   __ASM ("vmaxnm.f32 %0, %1, %2" : "=w" (__RES) : "w" (__ARG1), "w" (__ARG2) ); \
   __RES; \
})

And performance-wise it is indeed significantly faster to use

minVal = VMINNM(x, minVal);
maxVal = VMAXNM(x, maxVal);

than the if-then-else construct shown above.

Hansel
Senior

I just managed to find the cmsis_gcc.h file and it appears the latest version as of today is 5.4.1. When sifting through the file, I didn't see VMINNM or VMAXNM implemented. It's a shame in my eyes if useful functions like these are not made available because the µC cannot be used at its full potential so easily.