ARM-software / CMSIS-DSP

CMSIS-DSP embedded compute library for Cortex-M and Cortex-A
https://arm-software.github.io/CMSIS-DSP
Apache License 2.0
507 stars 131 forks source link

How to disable unused functions in MPLAB X IDE, XC32, Harmony 3 #89

Closed Rimatara closed 1 year ago

Rimatara commented 1 year ago

I try to compile arm_sin_cos_example_f32.c in the MPLAB X IDE, XC32, Harmony 3 but I get an error:

commontables.o: Link Error: Could not allocate section .rodata, size = 920376 bytes, attributes = code Link Error: Could not allocate program memory

How can I disable unused functions to fit program to ATSAMD21J18 (Cortex-M0+), Data/Program 32k/256k? Sin_Cos_Example_f32.zip

christophe0606 commented 1 year ago

@Rimatara You can disable tables for FFT. Either all tables or only the ones you don't use. It is explained in the README and should give you all the information you need

tobermory commented 1 year ago

I am not familiar with your IDE/toolchain, but if it is GNU GCC-based you could also go down the path of excluding code at link time, rather at compile time, which is the what the solution above does. You would use a compiler flag

-ffunction-sections

which results in every function being assigned its own section in the compiled code. By default, all functions in a single source file are assigned to a section named after that source file. You then use a linker option to 'discard all unreferenced sections':

-Xlinker --gc-sections

The linker works at the unit of sections, not routines, but if you force one section per function, you achieve discarding at the function level.

There is also

-fdata-sections

for doing the same thing for data. I use the two in combination in my (GCC-based+Makefile) builds:

CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Xlinker --gc-sections
tobermory commented 1 year ago

Hmm, I see now that 'XC32' is a C compiler from Microchip. Given that, the blurb about options in GCC may not prove particularly useful to you, sorry.

tobermory commented 1 year ago

Well, turns out XC32 is a port of GCC, so maybe the suggested flags WILL work??

Rimatara commented 1 year ago

@tobermory

I tried your suggestion, but unfortunately it didn't work in my Microchip MPLAB X IDE with XC32 compiler.

The problem is that by default all DSP functions are togather in one block in the libarm_cortexM0l_math.a 2 095 kBlibrary file. I had to create a new library and separate functions into sections libgen.X.a 3 710 kB by means of command: -DDISABLEFLOAT16 -DARM_DSP_CONFIG_TABLES -DARM_FAST_ALLOW_TABLES -DARM_FFT_ALLOW_TABLES -DARM_TABLE_TWIDDLECOEF_F32_16 -DARM_TABLE_BITREVIDX_FLT_16 -DARM_TABLE_TWIDDLECOEF_F32_64 -DARM_TABLE_BITREVIDX_FLT_64 -DARM_TABLE_TWIDDLECOEF_RFFT_F32_128 -DARM_ALL_FAST_TABLES

I had to exclude all “combinator include” files like BasicMathFunctions.c and BasicMathFunctionsF16.c too.

Than it works and I can compile program easy: Data/Program 141/4 520 Bytes.

XC32-gcc_Options

tobermory commented 1 year ago

I too tried to build the DSP library and the same example as you. I am using pure GNU arm-none-eabi toolchain and GNU make, so no IDE to speak of. I suspect your xc32 compiler is derived from this toolchain.

Like you, it (the example) would NOT build with

-ffunction-sections

but it WOULD with

-ffunction-sections -fdata-sections

for both Cortex M0 and M3. For an CM0 build, I am using the gcc_arm.ld linker file that bundles with the CMSIS_5 repo. I copied it locally, and made the ROM and RAM sizes match yours (256k/32k).

The arm_sin_cos_example will build for me. The resulting .bin file is 7800 bytes. I did not do ANY optimisations.

I created two Makefiles, one in DSP_ROOT/Source and one in DSP_ROOT/Examples/ARM/arm_sin_cos_example. I can share them if of use to you.

christophe0606 commented 1 year ago

@Rimatara There are 2 possible code size issues : functions and constant data. Your error in the github issue was about .rodata so the problem is likely related to the constant tables.

The linker should be able to remove the unused functions. For constant tables it is more difficult because some code may reference a table even if the table is finally not used at runtime (switch/case, if/then/else etc ...).

Relying on the linker only (and weak symbols ...) is a solution which is not always working and also is not very portable since it is not standard C. Since CMSIS-DSP is used on more and more high-end system too we have switched to a mechanism using compilation flags.

So, it means that the library has to be rebuilt with the right defines. You can rebuild the library without the f16 functions which are useless on M0.

With all of this, you should be able to use only what you need and decrease the size of the library as much as possible.

It is more work than having the linker do some magic but it gives better control and portability.

I think I'll have to detail this much more in the documentation.

tobermory commented 1 year ago

Fair points all. I don't treat garbage collection of unused sections as linker magic by GCC ld, it's just a feature as I see it. Your conditional compilation flags number 10 as I see it, i.e you've had to define 10 -D variables. And you had to work out the dependency graph of your program in the same way as the gcc linker will do.

You have arbitrary programs P on chips like CM0, CM3, CM4, etc. If the DSP library has to be built from source for ALL such combinations of program requirements and hardware platforms, that leads to many lib files. Now you having a lib file naming issue. By that point, you don't have a general purpose library at all. Instead, the DSP code that you select to build is essentially a part of the application build.

Rimatara commented 1 year ago

I am trying to create program for my real 1024 uint16 ADC data acquired by sampling stepped sinusoidal signal 5 kHz generated by DAC. The signal is sampled by free running ADC with a sample period 5.81E-6 s. Besides that I don't know how to convert uint16 data to float to prepare the inputdata vector for FTT calculation and I am having troubles with building project.

I build the library LIB-1.14.3.X.a with ..\include, ..\include\dsp and ..\PrivateInclude set GCC to "isolate each function in a section", "Place data into its own sections" and added command:

-DDISABLEFLOAT16 -DARM_DSP_CONFIG_TABLES -DARM_FAST_ALLOW_TABLES -DARM_FFT_ALLOW_TABLES -DARM_TABLE_TWIDDLECOEF_F32_16 -DARM_TABLE_BITREVIDX_FLT_16 -DARM_TABLE_TWIDDLECOEF_F32_64 -DARM_TABLE_BITREVIDX_FLT_64 -DARM_TABLE_TWIDDLECOEF_RFFT_F32_128 -DARM_ALL_FAST_TABLES

and excluded BasicMathFunctions.h and BasicMathFunctionsF16.h from build.

AR is set to "Break line into multiple lines".

Than in the program project I added window_function.h from (v1.15.0) because this function was missing in the older default MPLAB X IDE, CMSIS-DSP library (*.h files v1.9.0 ).

I replaced libarm_cortexM0l_math.a library with generated LIB-1.14.3.X.a, set GCC the same way as for generating librarary.

Now while building the project I got error:

../src/main.c:65:5: error: implicit declaration of function 'arm_hanning_f32'; did you mean 'arm_mat_init_f32'? [-Werror=implicit-function-declaration] arm_hanning_f32(inputdata, DATA_LENGTH); ^~~~~~~ arm_mat_init_f32

although arm_mat_init_f32 is in the matrix_functions.h and arm_hanning_f32 in window_functions.h

What should I do? I think I don't need to copy .c source files for these .h files from where I generated the new lib file.

FFT_Test_Build LIB-1 14 3-Header_Files LIB-1 14 3-gcc LIB-1 14 3-ar LIB-1 14 3-Exclusion

christophe0606 commented 1 year ago

@Rimatara It looks like the windows_functions.h is not included by arm_math.h (it should so it is an error). But you can also use #include "dsp/window_functions.h"

Note that you no more need to include arm_math.h. You can only includes the headers for the sub modules you use ...

In support function folder you have some functions to convert between float / q15

Rimatara commented 1 year ago

I have 1024 unsigned 16bit ADC data (i.e. float value would be Data/4096*3. 3V. What DSP functions would you recommend to me to allocate minimum space (Data/Program) in my ATSAMD21-XPRO 32k/256k?

I think I can remove the DC offset by subtracting the mean value for each data value and then convert 16bit data to Q15 fractional format. I need to calculate max. frequency based on max. abs value. I know the sampling period 5.81E-6 s and would like to use Hanning window function before FFT.

I don't care about the speed. Once a week I will measure the volume of the septic tank by tapping the solenoid on the outer plastic wall, read the response with a piezoelectric sensor and process the ADC data with FTT.

christophe0606 commented 1 year ago

Basic maths + Support + Windows + Transforms and only including the needed tables for FFT

It should give you the needed functions.

Since you're now able to build and avoid including all the FFT tables, I'll consider this github issue as handled.

Rimatara commented 1 year ago

OK, I close this case.