cancel
Showing results for 
Search instead for 
Did you mean: 

Saving Float values into FLASH, reconstructing the Floats

harinath
Associate III
Posted on August 06, 2014 at 10:46

I have tested EEPROM emulation code for STM32F4 recently. It works fine. Now I want to save some data written the following code for saving some floats.

For conversion of floatto int32_tand again converting int32_tto float, I enabled CMSIS DSP library in project settings of IAR, defined ARM_MATH_CM4 in compiler settings, included arm_math.h.


void
EEPROMdataTest(
void
)

{

/* Unlock the Flash to enable the flash control register access *************/

HAL_FLASH_Unlock();


/* EEPROM Init */

uint16_t FlashStatus;

FlashStatus = EE_Init();

if
(FlashStatus != HAL_OK)

printf(
''err during EE_Init() %d\r\n''
, FlashStatus);


/* --- Store successively many values in the FLASH & Read---*/


float
myfloats[10] ={ 0.98345f, 1.95f, 95f, 0.01f, 99f,

-0.94f, -1.94f, -95f, -0.01f, -99f}; 

int32_t q31_var = 0; 
float
result = 0;

for
(
int
i = 0; i<10; i++){ 

uint16_t u16_var[2]; 

arm_float_to_q31(&myfloats[i], &q31_var, 1);

q31_to_u16_buffer(q31_var, &u16_var[0]);


EE_WriteVariable(VirtAddVarTab[0], u16_var[0]); 
// MS part

EE_WriteVariable(VirtAddVarTab[1], u16_var[1]); 
// LS part

HAL_Delay(10);

uint16_t u16_varRead[2];

/* read the last stored variables data*/

FlashStatus = EE_ReadVariable(VirtAddVarTab[0], &u16_varRead[0]); 
// MS part

FlashStatus = EE_ReadVariable(VirtAddVarTab[1], &u16_varRead[1]); 
// LS part

/* construct int32_t from two uint16_t values */

q31_var = ((int32_t)u16_varRead[0] << 16) | ((int32_t)u16_varRead[1]);

arm_q31_to_float(&q31_var, &result, 1); 


printf(
''%2d: %8.6f, %8.6f \r\n''
,i, myfloats[i], result);


}


/* Lock the Flash to disable the flash control register access (recommended

to protect the FLASH memory against possible unwanted operation) *********/

HAL_FLASH_Lock(); 

}
void
q31_to_u16_buffer(int32_t inval, uint16_t* pBuffer)
{
//pBuffer[0] = (uint16_t)((inval & 0xffff0000)>> 16);
//pBuffer[1] = (uint16_t)(inval & 0x0000ffff);
uint8_t big8[4];
big8[0] = (uint8_t)((inval >> 24) & 0xff);
big8[1] = (uint8_t)((inval >> 16) & 0xff);
big8[2] = (uint8_t)((inval >> 8) & 0xff);
big8[3] = (uint8_t)(inval & 0xff); 
pBuffer[0] = ((uint16_t)big8[0]<<8) | (uint16_t)big8[1];
pBuffer[1] = ((uint16_t)big8[2]<<8) | (uint16_t)big8[3];
}

I get the following result:

0: 0.983450, 0.983450 
1: 1.950000, 1.000000 
2: 949997, 1.000000 
3: 0.010000, 0.010000 
4: 989998, 1.000000 
5: -0.940000, -0.940000 
6: -1.940000, -1.000000 
7: -949997, -1.000000 
8: -0.010000, -0.010000 
9: -989998, -1.000000

Where is it going wrong ? #arm-cmsis-dsp #float-to-int
7 REPLIES 7
harinath
Associate III
Posted on August 06, 2014 at 12:44

Tried to print out everywhere:

for
(
int
i = 0; i<10; i++){ 
uint16_t u16_var[2]; 
arm_float_to_q31(&myfloats[i], &q31_var, 1);
printf(
'' %d: %8.6f, %X 

''
,i, myfloats[i], q31_var);
q31_to_u16_buffer(q31_var, &u16_var[0]);
printf(
'' %d: %8.6f, %X, %

X''
,i, myfloats[i], u16_var[0], u16_var[1]);
EE_WriteVariable(VirtAddVarTab[0], u16_var[0]); 
// MS part
EE_WriteVariable(VirtAddVarTab[1], u16_var[1]); 
// LS part
uint16_t u16_varRead[2];
/* read the last stored variables data*/
FlashStatus = EE_ReadVariable(VirtAddVarTab[0], &u16_varRead[0]); 
// MS part
FlashStatus = EE_ReadVariable(VirtAddVarTab[1], &u16_varRead[1]); 
// LS part
printf(
'' %d: %8.6f, %X, %

X''
,i, myfloats[i], u16_varRead[0], u16_varRead[1]);
/* construct int32_t from two uint16_t values */
q31_var = ((int32_t)u16_varRead[0] << 16) | ((int32_t)u16_varRead[1]);
printf(
'' %d: %8.6f, %X 

''
,i, myfloats[i], q31_var);
arm_q31_to_float(&q31_var, &result, 1); 
printf(
''%d: %8.6f, %8.6f 

''
,i, myfloats[i], result);
}

This is what it prints. Seems problem in using the arm lib function: arm_float_to_q31(&myfloats[i], &q31_var, 1);or is it my input is wrong ?

0: 0.983450, 7DE1B080 
0: 0.983450, 7DE1, B080
0: 0.983450, 7DE1, B080
0: 0.983450, 7DE1B080 
0: 0.983450, 0.983450 
1: 1.950000, 7FFFFFFF 
1: 1.950000, 7FFF, FFFF
1: 1.950000, 7FFF, FFFF
1: 1.950000, 7FFFFFFF 
1: 1.950000, 1.000000 
2: 949997, 7FFFFFFF 
2: 949997, 7FFF, FFFF
2: 949997, 7FFF, FFFF
2: 949997, 7FFFFFFF 
2: 949997, 1.000000 
3: 0.010000, 147AE14 
3: 0.010000, 147, AE14
3: 0.010000, 147, AE14
3: 0.010000, 147AE14 
3: 0.010000, 0.010000 
4: 989998, 7FFFFFFF 
4: 989998, 7FFF, FFFF
4: 989998, 7FFF, FFFF
4: 989998, 7FFFFFFF 
4: 989998, 1.000000 
5: -0.940000, 87AE1480 
5: -0.940000, 87AE, 1480
5: -0.940000, 87AE, 1480
5: -0.940000, 87AE1480 
5: -0.940000, -0.940000 
6: -1.940000, 80000000 
6: -1.940000, 8000, 0
6: -1.940000, 8000, 0
6: -1.940000, 80000000 
6: -1.940000, -1.000000 
7: -949997, 80000000 
7: -949997, 8000, 0
7: -949997, 8000, 0
7: -949997, 80000000 
7: -949997, -1.000000 
8: -0.010000, FEB851EC 
8: -0.010000, FEB8, 51EC
8: -0.010000, FEB8, 51EC
8: -0.010000, FEB851EC 
8: -0.010000, -0.010000 
9: -989998, 80000000 
9: -989998, 8000, 0
9: -989998, 8000, 0
9: -989998, 80000000 
9: -989998, -1.000000

chen
Associate II
Posted on August 06, 2014 at 13:47

Hi

I do not understand why you are trying to separate the 32 bit number into 2 separate 16bit numbers??

Someone else had similar issues :

https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fSTM32Discovery%2fSTM32F4%20Discovery%20-%20Write%20float%20in%20Flash%20memory&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867...

You should be able to cast the float (32bit) into an int (32 bit).

Posted on August 06, 2014 at 13:49

Isn't Q31 a fixed point representation?

Why would you not just save the 32-bit float as a pair of 16-bit words? Use a union structure.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 06, 2014 at 13:51

You should be able to cast the float (32bit) into an int (32 bit).

That definitely won't work in a desirable fashion.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
harinath
Associate III
Posted on August 07, 2014 at 02:29

After reading 

The Designer's Guide to the Cortex-M Processor Family: A Tutorial Approach

By Martin 

book, I came to know that the CMSIS DSP library functions are designed to take values between +1 and -1. So before passing the float value to  function, we must scale it, after reconstruction again we must scale that float into original range.

Please note that I'm utilizing EEPROM emulation strategy for writing into FLASH ( we need to have 2 bytes virtual address for each 2 byte value).

clive1: using union not a better idea I think as it will have

http://www.cplusplus.com/doc/tutorial/other_data_types/

issues regarding endianess, padding/alignment. 

harinath
Associate III
Posted on August 07, 2014 at 03:04


union u32_u16{

uint32_t u32;

struct
{

uint16_t hi;

uint16_t lo;

}s;

}myu32, myu32_t; 


/* Here is the for loop which does all the stuff */

float
result = 0; uint32_t q32u_var=0;

for
(
int
i = 0; i<10; i++){ 

q32u_var = *(uint32_t*)&myfloats[i];

myuu32 = q32u_var;

printf(
'' %d: %8.6f, %X 

''
,i, myfloats[i], myuu32);

printf(
'' %d: %8.6f, %X, %

X''
,i, myfloats[i], myus.hi, myus.lo);

EE_WriteVariable(VirtAddVarTab[0], myus.hi); 
// MS part

EE_WriteVariable(VirtAddVarTab[1], myus.lo); 
// LS part

uint16_t u16_varRead[2];

/* read the last stored variables data*/

FlashStatus = EE_ReadVariable(VirtAddVarTab[0], &u16_varRead[0]); 
// MS part

FlashStatus = EE_ReadVariable(VirtAddVarTab[1], &u16_varRead[1]); 
// LS part

printf(
'' %d: %8.6f, %X, %

X''
,i, myfloats[i], u16_varRead[0], u16_varRead[1]);

/* construct int32_t from two uint16_t values */

myu32_t.s.hi = u16_varRead[0]; myu32_t.s.lo = u16_varRead[1];

printf(
'' %d: %8.6f, %X 

''
,i, myfloats[i], myu32_t.u32);

result = *(
float
*)&myu32_t.u32;

printf(
''%d: %8.6f, %8.6f 

''
,i, myfloats[i], result);

}

I tried the technique pointed

/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/STM32F4%20Discovery%20-%20Write%20float%20in%20Flash%20memory&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=50

about mimic a float as uint32_t. This code works fine (need to test with lost more float values). Though this code works, you may see the endianess issue.

0: 0.983450, 7DE1B080 0: 0.983450, 3F7BC361 
0: 0.983450, 7DE1, B080 0: 0.983450, C361, 3F7B
0: 0.983450, 7DE1, B080 0: 0.983450, C361, 3F7B
0: 0.983450, 7DE1B080 0: 0.983450, 3F7BC361 
0: 0.983450, 0.983450 0: 0.983450, 0.983450 
1: 1.950000, 7FFFFFFF 1: 1.950000, 3FF9999A 
1: 1.950000, 7FFF, FFFF 1: 1.950000, 999A, 3FF9
1: 1.950000, 7FFF, FFFF 1: 1.950000, 999A, 3FF9
1: 1.950000, 7FFFFFFF 1: 1.950000, 3FF9999A 
1: 1.950000, 1.000000 1: 1.950000, 1.950000 
2: 949997, 7FFFFFFF 2: 949997, 42BFE666 
2: 949997, 7FFF, FFFF 2: 949997, E666, 42BF
2: 949997, 7FFF, FFFF 2: 949997, E666, 42BF
2: 949997, 7FFFFFFF 2: 949997, 42BFE666 
2: 949997, 1.000000 2: 949997, 949997 
3: 0.010000, 147AE14 3: 0.010000, 3C23D70A 
3: 0.010000, 147, AE14 3: 0.010000, D70A, 3C23
3: 0.010000, 147, AE14 3: 0.010000, D70A, 3C23
3: 0.010000, 147AE14 3: 0.010000, 3C23D70A 
3: 0.010000, 0.010000 3: 0.010000, 0.010000 
4: 989998, 7FFFFFFF 4: 989998, 42C7FAE1 
4: 989998, 7FFF, FFFF 4: 989998, FAE1, 42C7
4: 989998, 7FFF, FFFF 4: 989998, FAE1, 42C7
4: 989998, 7FFFFFFF 4: 989998, 42C7FAE1 
4: 989998, 1.000000 4: 989998, 989998 
5: -0.940000, 87AE1480 5: -0.940000, BF70A3D7 
5: -0.940000, 87AE, 1480 5: -0.940000, A3D7, BF70
5: -0.940000, 87AE, 1480 5: -0.940000, A3D7, BF70
5: -0.940000, 87AE1480 5: -0.940000, BF70A3D7 
5: -0.940000, -0.940000 5: -0.940000, -0.940000 
6: -1.940000, 80000000 6: -1.940000, BFF851EC 
6: -1.940000, 8000, 0 6: -1.940000, 51EC, BFF8
6: -1.940000, 8000, 0 6: -1.940000, 51EC, BFF8
6: -1.940000, 80000000 6: -1.940000, BFF851EC 
6: -1.940000, -1.000000 6: -1.940000, -1.940000 
7: -949997, 80000000 7: -949997, C2BFE666 
7: -949997, 8000, 0 7: -949997, E666, C2BF
7: -949997, 8000, 0 7: -949997, E666, C2BF
7: -949997, 80000000 7: -949997, C2BFE666 
7: -949997, -1.000000 7: -949997, -949997 
8: -0.010000, FEB851EC 8: -0.010000, BC23D70A 
8: -0.010000, FEB8, 51EC 8: -0.010000, D70A, BC23
8: -0.010000, FEB8, 51EC 8: -0.010000, D70A, BC23
8: -0.010000, FEB851EC 8: -0.010000, BC23D70A 
8: -0.010000, -0.010000 8: -0.010000, -0.010000 
9: -989998, 80000000 9: -989998, C2C7FAE1 
9: -989998, 8000, 0 9: -989998, FAE1, C2C7
9: -989998, 8000, 0 9: -989998, FAE1, C2C7
9: -989998, 80000000 9: -989998, C2C7FAE1 
9: -989998, -1.000000 9: -989998, -989998

Still looking for any other ways to do this....
Posted on August 07, 2014 at 03:42

clive1: using union not a better idea I think as it will have

http://www.cplusplus.com/doc/tutorial/other_data_types/

issues regarding endianess, padding/alignment. 

Perhaps on a global scale, but locally on a micro with closely coupled eeprom, not so much. A 32-bit float and a 32-bit unsigned int, are going to take 32-bit which ever way you choose to stuff them. Shuffling them about in the manner you are is not particular endian safe either, you'd still need to be explicitly aware, and code for, byte and word level ordering issues, as well as platforms with alternate mantissa/exponent formats.

A double double, well that's another order of fun.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..