2014-08-06 01:46 AM
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
2014-08-06 03:44 AM
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
2014-08-06 04:47 AM
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).2014-08-06 04:49 AM
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.2014-08-06 04:51 AM
You should be able to cast the float (32bit) into an int (32 bit).
That definitely won't work in a desirable fashion.2014-08-06 05:29 PM
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 issues regarding endianess, padding/alignment.2014-08-06 06:04 PM
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¤tviews=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....
2014-08-06 06:42 PM
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.