This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F280049C: Data alignment issues for breaking float value into byte chunks and for joining byte chunks into float value

Part Number: TMS320F280049C

Fullscreen
1
2
3
4
5
6
7
char chunkdata[2] = {0};
uint16_t array_read[20] = {...};//initialized with some values
float32_t var;
chunkdata[0] = array_read[OFFSET] + (array_read[OFFSET+1] << 8);
chunkdata[1] = array_read[OFFSET+2] + (array_read[OFFSET+3] << 8);
var = *(float_t *)(&chunkdata[0]);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

In the above code, the value of var is correct only if &chunkdata[0]  has even value (chunk data is even aligned). But that depends on chance . If odd aligned address is supplied , then value of var is wrong. C28x decrements the address and then combines the value. __align() doesn't work for local variables according to compiler, so using it didn't help.

I want to split float into 4 8-bit chunks and join 4 8-bit chunks into float for EEPROM and CAN communication purposes. How to do it robustly? Also MISRA C compliance check is planned later. I am starting this post because I had marked previous post as resolved and now I can't undo it.

  • Hi Arpan,

    I just closed your previous post to avoid multiple posts of similar issue.  Please continue posting here.  After your fix from the other thread, can you share the MISRA C violation?

    Thanks,

    Joseph

  • As an update to the thread, the following code solved the alignment issues and is working as expected:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    float fvar;
    char * chunkdata;
    chunkdata = (char *)&fvar;
    uint16_t array_read[20] = {...};//initialized with some values
    float32_t var;
    chunkdata[0] = array_read[OFFSET] + (array_read[OFFSET+1] << 8);
    chunkdata[1] = array_read[OFFSET+2] + (array_read[OFFSET+3] << 8);
    var = *(float_t *)(&chunkdata[0]);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    But it is violating MISRA guidelines. To test for MISRA, I created a separate CCS project with just main.c, which is as follows

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /*
    */
    /**
    * main.c
    */
    #include <stdint.h>
    void main(void);
    void main(void)
    {
    float fvar;
    char * chunkdata;
    chunkdata = (char *)&fvar;
    uint16_t array_read[4] = {1,2,3,4};
    float var;
    chunkdata[0] = array_read[0] + (array_read[1] << 8);
    chunkdata[1] = array_read[2] + (array_read[3] << 8);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    The MISRA issues are as follows. The line numbering is verified:

  • 2nd update to this thread. In the separate project, I have been able to write code that will break float into chunks and vice versa without any MISRA warnings and errors. I have verified working of the code. Please have a look at it so that I can be sure that this code will always work. Thanks a lot Joseph!!

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdint.h>
    /******************************************************************************/
    /* 32-bit & 64-bit float type from "types.h"*/
    /******************************************************************************/
    #ifndef C2000_IEEE754_TYPES
    #define C2000_IEEE754_TYPES
    typedef float float32_t;
    typedef long double float64_t;
    #endif /* C2000_IEEE754_TYPES */
    int16_t main(void);
    float32_t fvar = 0.0f;
    int16_t main(void)
    {
    uint16_t chunkdata[4] = {0};/*8-bit style storage*/
    uint16_t intermediate[2] = {0};/*16-bit style storage*/
    float32_t var = 14.51234f;
    float32_t float_new = 0.0f;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Arpan,

    Using memcpy is a better solution for allocating space for the new float variable compared to the pointer assignment example that I provided as it violates MISRA C guidelines.  I have a concern though that you are still using 16-bit variable 'intermediate' to copy it back as a 'float_new' in the last memcpy statement as the 16-bit variable may not be properly aligned.

    Here's a different version that uses just one float variable and copies the contents of that float variable into 32-bit int data which is the ieee754 equivalent using memcpy.  A 16-bit array holds the byte data, which can be used to hold the de constructed data from the 32-bit location or vise versa. 

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    float floatdata;
    Uint32 intdata;
    Uint16 canbyte[4];
    floatdata = 3.1415926;
    memcpy(&intdata,&floatdata,sizeof(float));
    // de-construct 32-bit data into bytes
    canbyte[0]=intdata&0xff;
    canbyte[1]=(intdata>>8)&0xff;
    canbyte[2]=(intdata>>16)&0xff;
    canbyte[3]=(intdata>>24)&0xff;
    // group byte chunks into 32-bit number
    intdata=0;
    intdata=canbyte[0]+(canbyte[1]<<8)+(((canbyte[2])+(canbyte[3]<<8))*65536);
    floatdata=0;
    memcpy(&floatdata,&intdata,sizeof(float));
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     

    Regards,

    Joseph

  • Hi Joseph,

    According to me, in 
    memcpy(&float_new, intermediate, sizeof(float32_t));
    intermediate is a 16-bit variable. So read to it  by memcpy does not require aligned address. What do you think?

  • Hi Arpan,

    I guess so.  Going by the definition of memcpy, it copies length of data 'intermediate' from the sizeof function to 'float_new' and as such does not require address alignment.

    Regards,

    Joseph

  • Hi Joseph,

    So I will stick with the solution I have highlighted as resolved. Thanks a lot for your continuous help over the last 2 days.

    Regards,
    Arpan