linking with libarm_cortexM3l_math.a ?

Hi all,

I was trying to use CMSIS DSP library on the DUE.
this library is the file libarm_cortexM3l_math.a (instead of in .cpp source code, like the
run-of-the-mill arduino (user)libraries)

the headers for this library are available by including

#define ARM_MATH_CM3
#include <arm_math.h>

in your sketch.

this gives the error (in an example sketch, seen here : DUE's more advanced FFT capabilities - #8 by system - Arduino Due - Arduino Forum)

dsptest_due.cpp.o: In function `loop':
/home/raalst/arduino-1.5.1/dsptest_due.ino:51: warning: undefined reference to `arm_cfft_radix4_init_q31'
/home/raalst/arduino-1.5.1/dsptest_due.ino:54: warning: undefined reference to `arm_cfft_radix4_q31'
/home/raalst/arduino-1.5.1/dsptest_due.ino:59: warning: undefined reference to `arm_cmplx_mag_q31'
/home/raalst/arduino-1.5.1/dsptest_due.ino:62: warning: undefined reference to `arm_max_q31'

So i conclude I must now tweak the IDE to also use library libarm_cortexM3l_math.a when linking.
I found this file in the arduino 1.5.1 IDE distribution

Can somebody tell me how to achieve that ? I'm not much at home in gcc.

I did check with nm --print-armap that the function names
of the DSP lib are indeed in this library, so I think I have the right one.
I put the .a file in a lot of directories where .a files were already present (like .....arduino-1.5.1/hardware/arduino/sam/variants, where the library libsam_sam3x8e_gcc_rel.a lives).

I also added -larm_cortexM3l_math in boards.txt :
arduino_due_x_dbg.build.extra_flags=-D__SAM3X8E__ -mthumb -DUSB_PID={build.pid} -DUSB_VID={build.vid} -DUSBCON -larm_cortexM3l_math

but no luck yet....

I would be very grateful for a bit of explanation of what goes where and how to add this DSPlib library when linking the sketch.
Or the confirmation that this "should just work" and I have hit a little bugette 8)

Try to give a look at the platforms.txt file (in the same folder where boards.txt is) you should change the line:

## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group

and add your library just after

... "{build.variant.path}/{build.variant_system_lib}" "{build.variant.path}/**YOURLIBHERE**.a" ...

something like this should do fine:

## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" **"{build.variant.path}/libarm_cortexM3l_math.a"** "{build.path}/{archive_file}" -Wl,--end-group

but remember, this is a totally Untested Solution™.

I understand I'm on my own, targeting my own feet with my large guns 8)

But thank you VERY much for this help, let's see...

Success !!!

the software links, and runs the example. this means I have a lot of DSP goodies at my disposal, together with two DAC's and a lot of
ADC's.

Wheeeeeeeee !

sketch from /arduino-1.5.1/hardware/arduino/sam/system/CMSIS/CMSIS/DSP_Lib/Examples, mutilated by me

#define ARM_MATH_CM3
#include <arm_math.h>

#define TEST_LENGTH_SAMPLES 2048 


 
static float32_t testOutput[TEST_LENGTH_SAMPLES/2]; 
 
uint32_t M = 0;
 
/* ------------------------------------------------------------------ 
* Global variables for FFT Bin Example 
* ------------------------------------------------------------------- */ 
uint32_t fftSize = 1024; 
uint32_t ifftFlag = 0; 
uint32_t doBitReverse = 1; 
 
/* Reference index at which max energy of bin ocuurs */ 
uint32_t refIndex = 213, testIndex = 0; 
 
/* ----------------------------------------------------------------------
Test Input signal contains 10KHz signal + Uniformly distributed white noise
** ------------------------------------------------------------------- */

float32_t testInput_f32_10khz[2048] = 
{   
-0.865129623056441, 	0.000000000000000, 	-2.655020678073846, 	0.000000000000000, 	0.600664612949661, 	0.000000000000000, 	0.080378093886515, 	0.000000000000000, 	
... lots more numbers clipped away (see mentioned example dir, fft_bin example for full table ....
-2.899160484012034, 	0.000000000000000, 	2.563004262857762, 	0.000000000000000, 	3.078328403304206, 	0.000000000000000, 	0.105906778385130, 	0.000000000000000, 	
};

void setup() {
  Serial.begin(19200);
  Serial.println(" start program ");
}

void loop() {
       
     
       /** \example arm_fft_bin_example_f32.c 
  */  

	arm_status status; 
	arm_cfft_radix4_instance_f32 S; 
	float32_t maxValue; 
	 
	status = ARM_MATH_SUCCESS; 
	 
	/* Initialize the CFFT/CIFFT module */  
	status = arm_cfft_radix4_init_f32(&S, fftSize, ifftFlag, doBitReverse); 
	Serial.println("step 1"); 
	/* Process the data through the CFFT/CIFFT module */ 
	arm_cfft_radix4_f32(&S, testInput_f32_10khz); 
	Serial.println("step 2");  
	 
	/* Process the data through the Complex Magnitude Module for  
	calculating the magnitude at each bin */ 
	arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize);  
	Serial.println("step 3");  
	/* Calculates maxValue and returns corresponding BIN value */ 
	arm_max_f32(testOutput, fftSize, &maxValue, &testIndex); 
	Serial.println("step 4");  
        Serial.println(testIndex,DEC);
        Serial.println(refIndex,DEC);       
        
    while(1);                             /* main function does not return */
    
}

output :

 start program 
step 1
step 2
step 3
step 4
213
213

to reproduce this, follow cmaglie's advice (with caution..)

and be sure the library mentioned (.../arduino-1.5.1/hardware/arduino/sam/system/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a) has been copied to directory .../arduino-1.5.1/hardware/arduino/sam/variants/arduino_due_x

for an idea what is in this library, have a look at
.../arduino-1.5.1/hardware/arduino/sam/system/CMSIS/CMSIS/Documentation/DSP_Lib/html/index.html
It even contains a PID controller ! and examples...

btw, additional examples about how to program various bits of the DUE can be found here (I'm not sure if this is about
the same library, or something that looks like it) : http://asf.atmel.com/docs/3.1.3/api.html.
click on a subject (be sure to select sam3x8e, or whatever matches this code most) and hope there is an example shown...

running all 4 fft computations in the example 1000 times
(and assuming Millis() works correctly on the DUE)
takes about 35 seconds.
hence 35 milliseconds per fft, for 1024 bins,

and 28 fft1024 calculations per second.

Im falling in love with this beast...

 start program 
34939
69320

I am looking to read one of the ADC lines which has an Adafruit electret mic amp board on it, perform an FFT, then display a frequency vs. amplitude plot with the data. Has anyone progressed to something similar to this point?

raalst:
running all 4 fft computations in the example 1000 times
(and assuming Millis() works correctly on the DUE)
takes about 35 seconds.
hence 35 milliseconds per fft, for 1024 bins,

and 28 fft1024 calculations per second.

Im falling in love with this beast...

 start program 

34939
69320

I followed all your steps, I edited the platforms.txt file, butno glory, when my Arduino Due boots, it freezes.
It freezes whenever I call any of the functions of your example, i.e. arm_cfft_radix4_init_f32. If I comment ount that line, everything works.

When I compile I get the following errors:

EXTRACTOR_FFT_ARDUINO_DUE.cpp.o: In function `Ejecuta_FFT()':
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:131: warning: undefined reference to `arm_cfft_radix4_init_f32'
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:135: warning: undefined reference to `arm_cfft_radix4_f32'
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:140: warning: undefined reference to `arm_cmplx_mag_f32'
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:143: warning: undefined reference to `arm_max_f32'
Binary sketch size: 23.212 bytes (of a 524.288 byte maximum) - 4% used

Any hint on this?
Thank you.

Please turn on verbose mode in preferences and post the full output. I followed the instructions here and it worked fine.

Is there any reason not to include this modification in the next IDE release? It doesn't affect sketches which don't use the functions.

stimmer:
Please turn on verbose mode in preferences and post the full output. I followed the instructions here and it worked fine.

Is there any reason not to include this modification in the next IDE release? It doesn't affect sketches which don't use the functions.

Ok, I have spotted the error.

First I restarted the Arduino IDE. XD XD

Then I tried to change the points of the FFT to the half by using:

 #define TEST_LENGTH_SAMPLES 1024 
uint32_t fftSize = 512;

So I get the error at the call:

arm_cfft_radix4_f32(&S, testInput_f32_10khz);

after step 1.

Then I checked the file arm_cfft_radix4_init_f32.c, and there is not a 512 point fft!!!
Is there any way to introduce it?

I have seen that in the CMSIS library, those functions exist in radix2 format as well:

http://mazsola.iit.uni-miskolc.hu/DATA/segedletek/arm/cmsis/CMSIS/Documentation/DSP/html/group___radix2___c_f_f_t___c_i_f_f_t.html

But they are not included in the Arduino Due Libraries, why? Is it possible to add them? If it is, will they work with similar performance?

Thank you

Just spent half an hour trying to figure out why it wouldn't compile before I realized I still had the board selected as UNO ... (facepalm)

Anyway moving on. Just to confirm did I also need to modify the board.txt file as per what raalst tried first or was the change to the platforms.txt all that was needed? I've changed both and it's working like a dream but I won't leave board.txt modified if the change wasn't needed.

I've been finding and comparing different PID and FFT libraries for the DUE and to have them so neatly pre-packaged and (according to the docs) cortex optimized is way beyond what I expected to get, so big thanks raalst & cmaglie. I'm going to be trying to FFT a piezo sensor input to identify vibration modes in machinery as a fault finding/early fault detection system. If I get it right I'll make a post for it.

Cheers

Andrew

Only platform.txt needs to be changed, as per cmaglie's post.

Just to reiterate what I said before - I've now had this modification for 2 months and have used the IDE heavily and have had absolutely no problems or incompatibilities at all with sketches not using the library. I would recommend this change to be included in the next IDE release.

Nice to hear the post has been useful.

I'm making good progress attaching a mic, sampling it and displaying the FFT on a simple 128x64 glcd.
this requires use of the ADC, use of the DMA (pdc), the dsp library and U8glib. and a lot of large arrays.
but it still fits.

I created my own constants to refer to the registers, just to be sure to understand the datasheet

the DMA is freerunning, the sampling rate controlled by the prescaler value.
when needed I ask the PDC to get an array worth of ADC data, then busy-wait for the array to be filled.
after that FFT and display.

I am confused by the large amount of clocks in the system. it is correct to assume MCK is 4 Mhz in the DUE ?
does anybody know for sure ?
I do see FFT output, but relating it to frequencies is out of my league and currently done by running
the baudline (great piece of software !) tone generator at a known frequency in my PC.

current code (as an example, quite possibly of "how not to program"..) : see attachment

ownDMA_ADC_GLCD_fft_v3.ino (63.6 KB)

Great work raalst. I would hope that DMA sampling could be rolled into a library some day. Sooner than that I'd hope the Arduino Team would support formally some of the ARM libraries like the math one which includes the FFT - the power and code is already there, just make it easier for the development community to use it in the same spirit that has been done for other platforms.

Good links deserve plugging :
this link is about the only one I found that goes into any detail on the DUE ADC capabilities and settings

Wow nice find, a quick skim brings up this line:

"analogRead() in a tight loop takes 39uS per loop" ...Some config changes here ... "And the ADC loop now takes 4.4uS. Cool" :astonished:

I'll do a bit more digging into this to find out if there are any undesirable results from making this change, it seems too good to be true although the author seems pretty aware of what he's doing. If everything does work out nice and stable this will massively reduce the overhead of getting samples for our fft's.

When attempting to compile I receive the following error:

arm-none-eabi-g++: C:\arduino-1.5.2\hardware\arduino\sam\variants\arduino_due_x/libsam_sam3x8e_gcc_rel.aC:\arduino-1.5.2\hardware\arduino\sam\variants\arduino_due_x/libarm_cortexM3l_math.aC:\Users\PETRUS~1\AppData\Local\Temp\build6749693034922762752.tmp/core.a: Invalid argument

Did everything as explained but cant find the problem, please help

I am having problems with doing this and get the following error message
Arduino: 1.5.5-r2 (Windows 7), Board: "Arduino Due (Programming Port)"

arm-none-eabi-g++: C:\Program Files (x86)\Arduino\hardware\arduino\sam\variants\arduino_due_x/libsam_sam3x8e_gcc_rel.a""C:\Program Files (x86)\Arduino\hardware\arduino\sam\variants\arduino_due_x/libarm_cortexM3l_math.a""C:\Users\Barry\AppData\Local\Temp\build1011798555410636296.tmp/core.a: No such file or directory

I have checked that libsam_sam3x8e_gcc_rel.a and libarm_cortexM3l_math.a are in the folder arduino_due_x and also that the Platform.txt file has been changed to include them as mentioned in previous posts.

As a newbie to this, I'm out of my depth. Help please.

So for me the path given by the error didn't include the "arduino_due_x".

All I had to do was move the file into the path the error gives you and make sure it is named the same as the error. For some reason the error expected there to be "libarm_cortex3M1_math.a" The 3 and the M switched. I have no idea how or why but as soon as I put the right file (copied from ...\Arduino\hardware\arduino\sam\system\CMSIS\CMSIS\Lib\GCC) and renamed to match the error.

Hope that helps you.

Hello. If you want to use this library with data collected from a microphone, do you to scale the values? In one of their examples, the input values where somewhere between -5 and 5 (floats with more than 10 digits, don't know exactly the range). Thank you!