SushiHangover

PowerShell, Learn it or Perish ;-)

master nix
Gitter

LLVM, CMSIS DSP and Cortex-M3 & M0

"CMSIS Version 3 Block Diagram (Source: Arm.com)" I added ARM’s CMSIS 3.01 to my LLVM project and wanted to test out the pre-compiled DSP libraries that are supplied.

I borrowed one of the cos/sin examples and added some semihosting printfs using NEWLIB and cleaned up the code a bit.

CMSIS-DSP: DSP Library Collection with over 60 Functions for various data types: fix-point (fractional q7, q15, q31) and single precision floating-point (32-bit). The library is available for Cortex-M0, Cortex-M3, and Cortex-M4. The Cortex-M4 implementation is optimized for the SIMD instruction set.

Updating my Makefile to include the correct CMSIS libraries (arm_cortexM3l_math) for the ld and the currect headers for Clang/LLVM and the result works great for Cortex-M3. I copied the project over and mod’d the Makefile so it picks up the correct Cortex-M0 lib (arm_cortexM0l_math) and everything looks on this core also.

Clang/LLVM compile and link:

1
2
3
clang -Os  -nostdlib -ffreestanding   -target arm-none-eabi  -mcpu=cortex-m0   -mfloat-abi=soft  -mthumb  -DARM_MATH_CM3 -I/Users/administrator/Code/llvm_superproject/install/arm-none-eabi/newlib-syscalls/arm-none-eabi/include -I/Users/administrator/Code/llvm_superproject/install/arm-none-eabi/arm-none-eabi/include -I/Users/administrator/Code/llvm_superproject/install/arm-none-eabi/CMSIS/Include   -o obj/arm_sin_cos_example_f32.o -c src/arm_sin_cos_example_f32.c
clang -Os  -nostdlib -ffreestanding   -target arm-none-eabi  -mcpu=cortex-m0   -mfloat-abi=soft  -mthumb  -DARM_MATH_CM3 -I/Users/administrator/Code/llvm_superproject/install/arm-none-eabi/newlib-syscalls/arm-none-eabi/include -I/Users/administrator/Code/llvm_superproject/install/arm-none-eabi/arm-none-eabi/include -I/Users/administrator/Code/llvm_superproject/install/arm-none-eabi/CMSIS/Include   -o obj/startup.o -c src/startup.c
arm-none-eabi-ld -nostartfiles   -nostdlib -nostartupfiles  --gc-sections  --print-gc-sections  -Map bin/main.axf.map  -T src/cortex_M0.ld  --library-path /Users/administrator/Code/llvm_superproject/install/arm-none-eabi/newlib-syscalls/arm-none-eabi/lib/thumb/thumb2 --library-path /Users/administrator/Code/llvm_superproject/install/arm-none-eabi/lib/gcc/arm-none-eabi/4.8.3/armv7-m --library-path /Users/administrator/Code/llvm_superproject/install/arm-none-eabi/CMSIS/LIB/GCC    obj/arm_sin_cos_example_f32.o obj/startup.o --start-group --library=gcc --library=c --library=m --library=arm_cortexM0l_math --end-group -o bin/main.axf

Sample semihousting output from a Cortex-M3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
qemu-system-arm -cpu cortex-m3  -semihosting -nographic -kernel  bin/main.axf
Starting Test...
Cos -1.244917 = 0.320142
Sin -1.244917 = -0.947370
Cos squared 0.320142 = 0.102491
Sin squared -0.947370 = 0.897509
Add 0.102491 and 0.897509 = 1.000000
Cos -4.793534 = 0.081056
Sin -4.793534 = 0.996710
Cos squared 0.081056 = 0.006570
Sin squared 0.996710 = 0.993430
Add 0.006570 and 0.993430 = 1.000000
...
...
Cos 1.985805 = -0.403198
Sin 1.985805 = 0.915113
Cos squared -0.403198 = 0.162568
Sin squared 0.915113 = 0.837431
Add 0.162568 and 0.837431 = 1.000000
Ending Test...
https://github.com/sushihangover/llvm_baremetal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <stdlib.h> 
#include <math.h>     
#include "arm_math.h" 

/* ---------------------------------------------------------------------- 
* Defines each of the tests performed 
* ------------------------------------------------------------------- */
#define MAX_BLOCKSIZE    32 
#define DELTA           (0.000001f) 


/* ---------------------------------------------------------------------- 
* Test input data for Floating point sin_cos example for 32-blockSize 
* Generated by the MATLAB randn() function 
* ------------------------------------------------------------------- */

const float32_t testInput_f32[MAX_BLOCKSIZE] =
{
 -1.244916875853235400, -4.793533929171324800,  0.360705030233248850,
  0.827929644170887320, -3.299532218312426900,  3.427441903227623800, 
  3.422401784294607700,    -0.108308165334010680,  0.941943896490312180,
  0.502609575000365850,    -0.537345278736373500,  2.088817392965764500,
 -1.693168684143455700,  6.283185307179590700, -0.392545884746175080,
  0.327893095115825040,     3.070147440456292300,  0.170611405884662230,
 -0.275275082396073010, -2.395492805446796300,  0.847311163536506600,
 -3.845517018083148800,  2.055818378415868300,  4.672594161978930800,
 -1.990923030266425800,  2.469305197656249500,  3.609002606064021000,
 -4.586736582331667500, -4.147080139136136300,  1.643756718868359500,
 -1.150866392366494800,  1.985805026477433800
};

const float32_t testRefOutput_f32 = 1.000000000;

/* ---------------------------------------------------------------------- 
* Declare Global variables  
* ------------------------------------------------------------------- */
uint32_t blockSize = 32;
float32_t  testOutput;
float32_t  cosOutput;
float32_t  sinOutput;
float32_t  cosSquareOutput;
float32_t  sinSquareOutput;

/* ---------------------------------------------------------------------- 
* Max magnitude FFT Bin test 
* ------------------------------------------------------------------- */

arm_status status;

int32_t main(void)
{
   float32_t diff;
   uint32_t i;

   printf("Starting Test...\n");
   for (i=0; i < blockSize; i++)
   {
      cosOutput = arm_cos_f32(testInput_f32[i]);
      printf("Cos %f = %f\n", testInput_f32[i], cosOutput);

      sinOutput = arm_sin_f32(testInput_f32[i]);
      printf("Sin %f = %f\n", testInput_f32[i], sinOutput);

      arm_mult_f32(&cosOutput, &cosOutput, &cosSquareOutput, 1);
      printf("Cos squared %f = %f\n", cosOutput, cosSquareOutput);

      arm_mult_f32(&sinOutput, &sinOutput, &sinSquareOutput, 1);
      printf("Sin squared %f = %f\n", sinOutput, sinSquareOutput);

      arm_add_f32(&cosSquareOutput, &sinSquareOutput, &testOutput, 1);
      printf("Add %f and %f = %f\n", cosSquareOutput, sinSquareOutput, testOutput);

      /* absolute value of difference between ref and test */
      diff = fabsf(testRefOutput_f32 - testOutput);
      /* Comparison of sin_cos value with reference */
      if (diff > DELTA)
      {
         printf("Diff failure %f\n", diff);
         exit(EXIT_FAILURE); /* just for QEMU testing */
         while(1);
      }
   }
   printf("Ending Test...\n");
   exit(EXIT_SUCCESS); /* just for QEMU testing */
   while(1); /* main function does not return */
}

Comments