how to use dsp instructions from C

cancel
Showing results for 
Search instead for 
Did you mean: 

how to use dsp instructions from C

2,016 Views
tomwood
Contributor I

The SMMLA, SMMUL and SMMLL instructions provide exactly the mathmatical function that I need to write some IIR filter routines.  The complier does not use these naturally.  How do I get the compiler to use these instructions with out wading too far into the world of assembly code?

Labels (1)
0 Kudos
9 Replies

983 Views
ndavies
Contributor V

Tom, Download and install the Kinetis software development kit. You'll find the assembly macros you are looking for in the header files located in  \platforms\CMSIS\include\

Norm Davies

0 Kudos

983 Views
tomwood
Contributor I

I have recently installed KDS and cannot find the platforms directory. I am suspicious that something is missing in my install. Any ideas?

0 Kudos

983 Views
ndavies
Contributor V

Tom, as stated, The Kinetis software development kit is a separate package from the Kinetis Design studio.

The best way to issue the DSP commands in the Kinetis Design studio is to use assembly macros. The software development kit has those macros already defined. The other option is to code a bunch of library functions in assembly and then link them to the C program.

The SDK is here: Software Development Kit for Kinetis MCUs|Freescale

The software development kit has Kinetis device drivers and many other useful pieces. The SDK also includes higher level filtering functions that rely on the DSP assembly macros. I'm sure you'll find it very useful.

Norm

0 Kudos

983 Views
tomwood
Contributor I

I am not sure why but the files are not where they should be. I think I accidentally moved them to another directory when I should have copied them. I wanted to use them as examples just to look over. I suppose the correct thing to do is reinstall everything. Or is there a simple way to reinstall these files. I guess if I understand all the files and where they should be I can just copy them back. If I am going to reinstall I’ll have to find the directions about setting up eclipse and the things that need to be installed.

I have managed to get some similar instructions working through inline assemble created in a C subroutine that I call to get the function I need. By in-lining the routine the overhead is reasonable or perhaps none. Today other things have kept me away from this.

Thanks for the help from everyone so far!!

0 Kudos

983 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Tom

let's come back to your original question, we provide the intrinsic function which are macro to implement the assembly instruction.

C:\Freescale\KSDK_1.0.0\platform\CMSIS\Include\core_cm4_simd.h

uint32_t a,b,c;

int main(void)

{

    uint16_t i;

    /* Write your code here */

    a=0x20000000;

    b=0x20000000;

    c=__SADD8(a,b);

    for(;;)

    {}

}

0 Kudos

983 Views
tomwood
Contributor I

That is pretty much what I tried first so I tried again.I get the following errors: D:\dspKinetisExperiments\kinetisK22Jan62014\tryinstructionsOne\Debug/../Sources/main.c:102: undefined reference to `__SADD8'

collect2.exe: error: ld returned 1 exit status

make: *** Error 1

0 Kudos

983 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Tom,

I do not know why I can not download the WRD000.jpg you attached here, Anyway I suppose that you have installed the KDS and SDK tools, currently, SDK only supports part of Kinetis family not all Kinetis family. I send you an example based on KV31 and KDS plus SDK, as you know, SDK supports KV31. I also attach two screenshot which tell you how to add the *.h and library to the project. Note that libarm_cortexM4l_math.a adapts to the M4 core without float coprocessor, libarm_cortexM4lf_math.a adapts to the M4 core with float coprocessor, libarm_cortexM0l_math.a to the M0 core.

Hope it can help you

BR

XiangJun Rong

0 Kudos

983 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Tom,

From all the description including Norm and Martyn, I see that you are using KDS tools to develop the code. If it is the case, as Mr Norm Davies suggested, after you installed KDS, you have to install SDK, which is code generator and library. In the SDK, there is a lot of example, the CMSIS is one of the directory.

after you installed SDK, pls refer to the example

C:\Freescale\KSDK_1.0.0\demos\sai_demo\kds\twrk64f120m, the equalizer.c use the CMSIS to develop FFT, it is helpful to understand how to call FIR. I copy the code here:

You can refer the FIR code:

C:\Freescale\KSDK_1.0.0\platform\CMSIS\DSP_Lib\Source\FilteringFunctions

Pls download SDK from the the website:


http://tinyurl.com/kd79d7y


equalizer.c

/*******************************************************************************

* Standard C Included Files

******************************************************************************/

#include <string.h>

#include <math.h>

#include <stdbool.h>

#include <stdlib.h>

#include <stdio.h>

/*******************************************************************************

* SDK Included Files

******************************************************************************/

#include "fsl_soundcard.h"

#include "fsl_sai_driver.h"

#include "fsl_sai_features.h"

#include "fsl_sgtl5000_driver.h"

/*******************************************************************************

* Application Included Files

******************************************************************************/

#include "audio.h"

#include "equalizer.h"

#include "terminal_menu.h"

/*******************************************************************************

* Include CMSIS-DSP library

******************************************************************************/

#include "arm_math.h"

/*******************************************************************************

* Global Variables

******************************************************************************/

/*******************************************************************************

* Function Definitions

******************************************************************************/

float32_t do_fft(sai_data_format_t *dataFormat, uint8_t *buffer, float32_t *fftData, float32_t *fftResult)

{

    /* Counter variable for navigating buffers */

    uint32_t counter;

    /* Return value for wav frequency in hertz */

    float32_t wavFreqHz;

    /* CMSIS status & FFT instance */

    arm_status status;                  /* ARM status variable */

    arm_cfft_radix2_instance_f32 fft;   /* ARM FFT instance */

    /* Frequency analysis variables */

    float32_t maxValue;                                                 /* max value for greatest FFT bin amplitude */

    uint32_t testIndex = 0;                                             /* value for storing the bin location with maxValue*/

    uint32_t complexBuffSize = AUDIO_BUFFER_BLOCK_SIZE * 2;

    uint32_t fftSize = AUDIO_BUFFER_BLOCK_SIZE;                         /* FFT bin size  */

    uint32_t ifftFlag = 0;                                              /* Flag for the selection of CFFT/CIFFT */

    uint32_t doBitReverse = 1;                                          /* Flag for selection of normal order or bit reversed order */

    uint32_t sampleRate = dataFormat->sample_rate;                      /* Get sample rate from current format */

    float32_t hzPerBin = 2 * ((float32_t)sampleRate/(float32_t)fftSize);    /* Calculate hz per FFT bin */

    uint8_t *temp8;             /* Point to data for 8 bit samples */

    uint8_t  temp8Data;

    uint16_t *temp16;             /* Point to data for 16 bit samples */

    int16_t   temp16Data;

    uint32_t *temp32;             /* Point to data for 32 bit samples */

    int32_t   temp32Data;

    /* Set status as success */

    status = ARM_MATH_SUCCESS;

    /* Wav data variables */

    switch(dataFormat->bits)

    {

        case 8:

            temp8 = (uint8_t *)buffer;

            temp8Data = 0;

            /* Copy wav data to fft input array */

            for(counter = 0; counter < complexBuffSize; counter++)

            {

                if(counter % 2 == 0)

                {

                    temp8Data = (uint8_t)*temp8;

                    fftData[counter] = (float32_t)temp8Data;

                    temp8++;

                }

                else

                {

                    fftData[counter] = 0.0;

                }

            }

            /* Set instance for Real FFT */

            status = arm_cfft_radix2_init_f32(&fft, fftSize, ifftFlag, doBitReverse);

            /* Perform Real FFT on fftData */

            arm_cfft_radix2_f32(&fft, fftData);

            /* Populate FFT bins */

            arm_cmplx_mag_f32(fftData, fftResult, fftSize);

            /* Zero out non-audible, low-frequency noise from FFT Results. */

            fftResult[0] = 0.0;

            /* Find max bin and location of max (first half of bins as this is the only valid section) */

            arm_max_f32(fftResult, fftSize, &maxValue, &testIndex);

            break;

        case 16:

            temp16 = (uint16_t *)buffer;

            temp16Data = 0;

            /* Copy wav data to fft input array */

            for(counter = 0; counter < complexBuffSize; counter++)

            {

                if(counter % 2 == 0)

                {

                    temp16Data = (int16_t)*temp16;

                    fftData[counter] = (float32_t)temp16Data;

                    temp16++;

                }

                else

                {

                    fftData[counter] = 0.0;

                }

            }

            /* Set instance for Real FFT */

            status = arm_cfft_radix2_init_f32(&fft, fftSize, ifftFlag, doBitReverse);

            /* Perform Real FFT on fftData */

            arm_cfft_radix2_f32(&fft, fftData);

            /* Populate FFT bins */

            arm_cmplx_mag_f32(fftData, fftResult, fftSize);

            /* Zero out non-audible, low-frequency noise from FFT Results. */

            fftResult[0] = 0.0;

            /* Find max bin and location of max (first half of bins as this is the only valid section) */

            arm_max_f32(fftResult, fftSize, &maxValue, &testIndex);

            break;

        case 32:

            temp32 = (uint32_t *)buffer;

            temp32Data = 0;

            /* Copy wav data to fft input array */

            for(counter = 0; counter < complexBuffSize; counter++)

            {

                if(counter % 2 == 0)

                {

                    temp32Data = (int32_t)*temp32;

                    fftData[counter] = (float32_t)temp32Data;

                    temp32++;

                }

                else

                {

                    fftData[counter] = 0.0;

                }

            }

            /* Set instance for Real FFT */

            status = arm_cfft_radix2_init_f32(&fft, fftSize, ifftFlag, doBitReverse);

            /* Perform Real FFT on fftData */

            arm_cfft_radix2_f32(&fft, fftData);

            /* Populate FFT bins */

            arm_cmplx_mag_f32(fftData, fftResult, fftSize);

            /* Zero out non-audible, low-frequency noise from FFT Results. */

            fftResult[0] = 0.0;

            /* Find max bin and location of max (first half of bins as this is the only valid section) */

            arm_max_f32(fftResult, fftSize, &maxValue, &testIndex);

            break;

        default:

            __asm("NOP");

            break;

    }

    if(status != ARM_MATH_SUCCESS)

    {

        wavFreqHz = 0;     /* If an error has occured set frequency of wav data to 0Hz*/

        printf("\r\nFFT compuation error.\r\n");

    }

    else

    {

        wavFreqHz = testIndex * hzPerBin;  /* Set wavFreqHz to bin location of max amplitude multiplied by the hz per bin */

    }

    return wavFreqHz;

}

/*******************************************************************************

* EOF                                          

*******************************************************************************/

0 Kudos

983 Views
martynhunt
NXP Employee
NXP Employee

Hi Tom,

Which compiler are you using? IAR and ARM compilers should recognize what you are trying to achieve and use the DSP instructions. If you are not seeing these instructions being used after compiling your C code, increase the compiler optimizations.

If you are still not seeing the correct instructions being used, then you will have to use inline assembly in your C code.

Please let me know if you have further questions.

Thank you,

Martyn

0 Kudos