Hi,

I've noticed weird problem when calling few math functions few times in a row or a loop like:

c = sin(3.0)+sin(5.0)+sin(5.0)+sin(5.0)+sin(5.0)+sin(5.0)+sin(4.0);

Actually I don't know what's going wrong but my application is audio-proccessing and sound coming out after deploying this code even when C variable is used nowhere else! It's just debugging code sample showing that adding few math functions makes something wrong to MCU and I don't even know how to to find the reason.

Problem also occurs with other math.h functions like tan or power.

My setup is uVision, Keil with project set as compiler defines:USE_STDPERIPH_DRIVER, ARM_MATH_CM4. My device is STM32F405 so it's with FPU that I'm using.

Included <math.h> files is from keil\arm\armcc\include standard location so it's original.

Note:

Executing simple x = sin(1.0) in loop works bad (many audio distortion) but when executed every like 8th iteration (or more rare) it works better so maybe math functions are so big and slow?

I've noticed weird problem when calling few math functions few times in a row or a loop like:

c = sin(3.0)+sin(5.0)+sin(5.0)+sin(5.0)+sin(5.0)+sin(5.0)+sin(4.0);

Actually I don't know what's going wrong but my application is audio-proccessing and sound coming out after deploying this code even when C variable is used nowhere else! It's just debugging code sample showing that adding few math functions makes something wrong to MCU and I don't even know how to to find the reason.

Problem also occurs with other math.h functions like tan or power.

My setup is uVision, Keil with project set as compiler defines:USE_STDPERIPH_DRIVER, ARM_MATH_CM4. My device is STM32F405 so it's with FPU that I'm using.

Included <math.h> files is from keil\arm\armcc\include standard location so it's original.

Note:

Executing simple x = sin(1.0) in loop works bad (many audio distortion) but when executed every like 8th iteration (or more rare) it works better so maybe math functions are so big and slow?

Actually I discovered it too few moments ago but you explained to me better.

My new problem is that I have issue with other "real_T" data when I use them in simple operations like multiplying. First of all I dealt with it by changing all "real_T" occurencies to "float" and it compiles fine and works fine. One small bug: if I use constants like "x * 4.0" it means that 4.0 is type of real_T (I think so, or other 64-bit) and fixing for that is putting "x * (float)4.0" what isn't nice. How can I fix this?

I should mention what "real_T" for me is. I use Matlab-generated code what includes:

/*=======================================================================*

* Target hardware information

* Device type: ARM Compatible->ARM Cortex

* Number of bits: char: 8 short: 16 int: 32

* long: 32 native word size: 32

* Byte ordering: LittleEndian

* Signed integer division rounds to: Undefined

* Shift right on a signed integer as arithmetic shift: on

*=======================================================================*/

/*=======================================================================*

* Fixed width word size data types: *

* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *

* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *

* real32_T, real64_T - 32 and 64 bit floating point numbers *

*=======================================================================*/

typedef signed char int8_T;

typedef unsigned char uint8_T;

typedef short int16_T;

typedef unsigned short uint16_T;

typedef int int32_T;

typedef unsigned int uint32_T;

typedef float real32_T;

typedef double real64_T;

/*===========================================================================*

* Generic type definitions: real_T, time_T, boolean_T, int_T, uint_T, *

* ulong_T, char_T and byte_T. *

*===========================================================================*/

typedef double real_T;

typedef double time_T;

typedef unsigned char boolean_T;

typedef int int_T;

typedef unsigned int uint_T;

typedef unsigned long ulong_T;

typedef char char_T;

typedef char_T byte_T;

Keil can do optimization with constants, generally it is capable of folding them or rearranging the computation. Remember that multiplying by 0.1 will be faster than divide by 10.0

The other big problem with the FPU compared to more effective implementations is that it's not going to be hold intermediate results at high precision, and this has a compounding effect.

Can't help you with MATLAB, really not my thing.

1) Add in Keil arm_cortexM4lf_math.lib to your project

2) #include "arm_math.h"

3) Use arm_sin_f32() instead of sin()

Regards,

A.