2022-04-11 07:47 AM
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:
Solved! Go to Solution.
2022-04-11 10:51 AM
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.
2022-04-11 10:51 AM
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.
2022-04-11 12:13 PM
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.
2022-04-12 04:31 PM