laboratorio di architetture e...

33
LABORATORIO DI ARCHITETTURE E PROGRAMMAZIONE DEI SISTEMI ELETTRONICI INDUSTRIALI Laboratory Lesson 10: CMSIS DSP Library and Functions Final Assignment Prof. Luca Benini <[email protected]> Simone Benatti <[email protected]> Prof Davide Rossi <[email protected]> Victor Kartsch <[email protected] >

Upload: phamxuyen

Post on 02-Aug-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

LABORATORIO DI ARCHITETTURE E PROGRAMMAZIONE DEI SISTEMI

ELETTRONICI INDUSTRIALILaboratory Lesson 10:

CMSIS DSP Library and Functions

Final Assignment

Prof. Luca Benini <[email protected]> Simone Benatti <[email protected]>Prof Davide Rossi <[email protected]> Victor Kartsch<[email protected]>

Info & Communications

Recap

LAB1: IDE & Debug

LAB2: GPIO & Systick

LAB3: Advanced Debug

LAB4: EXTI

LAB5: Timers

LAB6: FLASH & DMA

LAB7: USART

LAB8: ADC

LAB9: SPI

LAB10: CMSIS DSP

• CMSIS DSP lib and signal processing

CMSIS DSP Library

CMSIS

CMSIS: Cortex Microcontroller Software Interface Standard

• Vendor-independent hardware abstraction layer for ARM Cortex-M

• Simple software interfaces for ARM core for:• Peripherals’ interfaces

• Real-time operating systems

• Middleware

• DSP functions

DSP Functions

Abs, dot products, fixed point operations, …

Complex math…

PIDs, …

Sin, cos, tan, …

FIR,IIR, conv, LMS…

Matrix multiplication, inverse, …

Mean, RMS, variance, ...

Conversion fix to float, …

FFTs

• Provides fast development for basic math for DSP• SPEEDUP code execution

Example 1: Dot product

𝒂 ∙ 𝒃 =

𝑛=1

𝑎𝑛 ∙ 𝑏𝑛

Dot product or inner product or scalar product• One of the most used operations in all signal processing domains• Many efficient HW/SW implementations

Intuition Algebraic function

In our world vectors are…ARRAYS!

Dot product implementation

static int n;

for(n = 0 ; n<Array_dimension ; n++){

product += a[n]*b[n];}

𝒂 ∙ 𝒃 =

𝑛=1

𝑎𝑛 ∙ 𝑏𝑛

The MATH The CODE

Problems:1. Many ldr & str operations2. Many multiplications and sums

Dot product with CMSIS DSP

arm_dot_prod_f32(&srcA_buf_f32, &srcB_buf_f32, MAX_BLOCKSIZE, &testOutput);

Vector 1 Vector 2 Dimension Output

In your sample code compare the 2 executions:

nonARM_product( &srcA_buf_f32,&srcB_buf_f32, &multOutput, MAX_BLOCKSIZE)

vsarm_dot_prod_f32(&srcA_buf_f32,&srcB_buf_f32, MAX_BLOCKSIZE, &testOutput);

1900 cycles

1000 cycles

SPEEDUP x2!!

Example 2 : Digital Filters

FIR pros:1. can be designed with linear phase2. simple to implement3. good for finite precision math

FIR cons:1. FIR requires more memory and computation (more coefficients)2. Bigger filters cause delays

There are two main digital filters categories:• FIR (Finite Impulse Response)• IIR (Infinite Impulse Response)

FIR basics

𝑦(𝑛) =

𝑘=0

𝑁−1

ℎ 𝑘 𝑥(𝑛 − 𝑘)

h(k) = Coefficients (aka taps)

x(n-k) = Input data

Filter diagramFilter formula

N = filter order (aka number of coeffs.) 𝑦(𝑛)

Calculate the coefficients

Use the following Matlab script:

% Define sampling frequencyFs = 1000; %1kHz

% Define cutoff frequency Cutoff_freq = 40;

% Calculate Nyquist frequencyNyq_frequency = Fs/2;Cutoff_norm = Cutoff_freq/Nyq_frequency;

% FIR orderorder = 4;

% Calculate taps (coefficients)FIR_coeff = fir1(order,Cutoff_norm);

Simple example with 3 coefficients

𝑦 𝑛 = ℎ 0 𝑥 𝑛 + ℎ 1 𝑥 𝑛 − 1 + ℎ 2 𝑥(𝑛 − 2)

In this case we have:

Coefficients

Input data

float X[1000];

float Y[1000];

float h[N] = {0.32590173795979338000, 0.34819652408041324000, 0.32590173795979338000};

int main()

{

float yn = 0;

int i,k;

const int N = 3;

float x[N] = {0,0,0};

X[0] = 1;

for(i=0; i<1000; i++)

{

for(k=0; k < N-1; k++) {

x[N-k-1] = x[N-k-2]; //shift the data

}

x[0] = X[i]; // move input sample to buffer

yn = 0; // clear output sample

for(k=0; k < N; k++) {

yn += h[k]*x[k]; // multiply and accumulate data with coefficients

}

Y[i] = yn; // move output sample to buffer

}

}

FIR C Implementation

CMSIS DSP Implementation

#define BLOCK_SIZE 32

#define NUM_TAPS 29

#define TEST_LENGTH_SAMPLES 320

uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;

. . .

int main(void)

{

. . .

/* Initialize input and output buffer pointers */

inputF32 = &testInput_f32_1kHz_15kHz[0];

outputF32 = &testOutput[0];

/* Call FIR init function to initialize the instance structure. */

arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32[0], &firStateF32[0], blockSize);

/* Call the FIR process function for every blockSize samples */

for(i=0; i < numBlocks; i++) {

arm_fir_f32(&S, inputF32 + (i * blockSize), outputF32 + (i * blockSize), blockSize);

}

. . .

}

Check the code implementation!

Optimization: going faster!

You can tell your compiler to optimize the code when compiling, making the

execution faster ( >50% faster).

Optimization is not for dummies, use it only when you carefully debugged the code.

• some code that work without optimization may NOT work when you optimize, so

pay attention!

• It is strongly compiler dependent (in our case GCC)

We have several optimization flags (O0 – O3). The most popular are:

• O0 No optimization.

Direct correspondence between each line of code and the resulting machine

instructions

• O2 Enables more optimizations.

This mode turns on nearly all optimizations.

Optimization: going faster!

To set an optimization level in your project:Project proprieties -> C/C++ Build -> Settings -> MCU GCC Compiler -> Optimization -> select optimization level

If the code is well-written, optimization is more effective

CMSIS functions are specifically well-written for our platform:they enable loop unrolling, MAC instructions and other DSP features of our Cortex M4 MCU

Performance: Dot product

0

0,5

1

1,5

2

Dot product -O0 Dot product -O2

KCyc

les NO CMSIS

CMSIS DSP

NO CMSIS CMSIS DSP

Dot product -O0 1,9 0,99

Dot product -O2 0,3 0,24

Performance: FIR filter

0

200

400

600

800

1000

FIR -O0 FIR -O2

KCyc

les NO CMSIS

CMSIS DSP

NO CMSIS CMSIS DSP

FIR -O0 823 201

FIR -O2 138 43

Libraries and code organization

Functions: declaration

Function prototype:• function name (must be unique)• type of input parameters (may be void)• type of return variable (may be void)• equivalent to variable declaration

Functions: implementation

Function implementation:• The actual code that is executed when

the function is called• The code is written only once, but it can

be used several times with different input parameters

Functions: use

Function use:• the actual call to the function• defines when the code is called during the

execution of a program• must provide the correct input parameters

Functions: libraries

Local function:• Delared and implemented in the current file• Can be only called within that file

Library function:• Declared in separate header file (.h) and

implemented in dedicated source file (.c)• Can be used in any file that includes its

header

Code organization

Until now we have always put everything in the main file:• OK for simple projects• NOT OK for complex and large projects• NOT OK for code sharing and re-use

You can create your own libraries!• Different files with collection of useful functions, for easy re-use• Try to be organized: group functions in a logical way

You have functions that compute mean, variance and min/max, and you want to put them in a features library… how? • Create file features.h in the ./inc subdirectory of your project• Put the functions prototypes in features.h• Create file features.c in the ./src subdirectory of your project• Put the functions implementations in features.c• In main: add #include “functions.h” and call your functions with the correct parameters.

Libraries and folders

When dealing with multiple files and libraries you can use folders and sub-folders to organize them• It is up to you, but some common practices are good to follow

Libraries and folders

When dealing with multiple files and libraries you can use folders and sub-folders to organize them• It is up to you, but some common practices are good to follow

When you create a project you already have a starting folder structure:• Main application files are in ./inc and ./src

Libraries and folders

When dealing with multiple files and libraries you can use folders and sub-folders to organize them• It is up to you, but some common practices are good to follow

When you create a project you already have a starting folder structure: • Main application files are in ./inc and ./src• StdPeriph_Driver: library organized with inc and src sub-floders

Libraries and folders

When dealing with multiple files and libraries you can use folders and sub-folders to organize them• It is up to you, but some common practices are good to follow

When you create a project you already have a starting folder structure:• Main application files are in ./inc and ./src• StdPeriph_Driver: library organized with inc and src sub-floders• Utilities: library with a common folder for header and source

files

Libraries and folders

When dealing with multiple files and libraries you can use folders and sub-folders to organize them• It is up to you, but some common practices are good to follow

When you create a project you already have a starting folder structure:• Main application files are in ./inc and ./src• StdPeriph_Driver: library organized with inc and src sub-floders• Utilities: library with a common folder for header and source

files

So what is the difference between putting a header file in ./inc or ./Utilities or ./StdPeriph_Driver/inc or creating a new (sub)directory?

Nothing, but you must ensure that the compiler and linker know when to get those files!

Libraries: project settings

If you add your files in the main src/inc folders everything will be ok……but, if you create a new folder to organize your files, it will give you lots of errors…!

You have to add the new folders to the compiler and linker paths!

• Create the folder/files you want or copy them in the project’s main folder• If you copy files outside Eclipse, you have to refresh to see them• You have to add any folder containing header files (.h) to the include paths• You have to add any folder containing source files (.c) to the source paths• If a folder contains both, add it in both paths• Subfolders are usually ok, but you may have to check

Libraries: include paths

You have to add any folder containing header files (.h) to the include paths:

Project proprieties -> C/C++ Build -> Settings -> MCU GCC Compiler -> Includes -> add the desired folder in the Include paths panel

You should use relative paths:• If you copy or export the project it will work• use project directory or workspace directory

as reference• copy from the folders already listed there

Libraries: source paths

You have to add any folder containing source files (.c) to the source paths:

Project proprieties -> C/C++ General -> Paths and Symbols -> Source Location (TAB) -> add the desired folder