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.

Compiler/F28M36P63C2: Casting byte array to struct containing floats

Part Number: F28M36P63C2
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI C/C++ Compiler

I have the following struct that is shared between the M3 and C28 processors, and is given a value by a PC via ethernet and shared memory. I am sending the same data values from a PC to both the M3 and C28. I then cast the data buffer into the PIDCTRL struct and print out the values of the struct using the following code:

typedef struct _PIDCTRL
{
	Float32     setPoint; 
	Float32     tolerance;
	Float32     Kp;
	Float32     Ki;
	Float32     Kd;
	Float32     maxOutput;
	Float32     minOutput;
	Uint16      pidEnable; 
	Uint16      state; 
	Uint16      minStableTimeSec;
	Uint16      maxSettlingTimeSec;
	Uint16      period;
	Uint16      Reserved;
	Uint16      fields;
} PIDCTRL;

// Code is the same for the C28 / M3

uint_least8_t * replyData = <this data comes from the PC>

PIDCTRL *pid = (PIDCTRL *)replyData;

DbgInfo("Setting: %f %f %f %f %f %f %f %u %u %x %x %x %x",
    pid->setPoint, pid->tolerance, pid->Kp, pid->Ki, pid->Kd,pid->minOutput, pid->maxOutput,pid->minStableTimeSec, pid->maxSettlingTimeSec,
    replyData[0],replyData[1],replyData[2],replyData[3]);

I am sending the data values (1.0,2.0,3.0, ... 9.0) and this is what I see. The M3 correctly casts the data and prints it correctly, but the C28 does not cast the floating points correctly, only the Uint16 fields.

 M3 Setting: 1.0000 2.0000 3.0000 4.0000 5.0000 8.0000 9.0000 6 7              0 0 80 3f
 C28 Setting: 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 6 7            0 3f80 0 4000

I also printed out the first 4 words of the raw buffer and noticed the bytes were swapped in the C28, i thought the C28 and M3 were both little endian and have the same IEEE 754 floating point values. Am I missing something obvious?

Also here is some additional information. The function DbgInfo internally uses 'System_vsnprintf' to print the formatted values, and i have add 'System.extendedFormats = "%$L%$S%$F%f";' to my .cfg file so that the prints work with the extended format. I also verified the prints are work correctly on the C28 if I manually set a float field in the PID_CONF struct (e.g., pid->Kp = 5.324). I have tried modifying the struct packing, but that doesn't seem to help either.

Derek

  • Hi Derek,

    So is replyData pointing to shared memory? Also, I'm trying to figure out what PIDCTRL looks like--you've shared PID_CONF which appears to have some of the same fields but not all. Can you clarify?

    Thanks,
    Whitney
  • Hi Whitney. Sorry, i put the wrong struct in the question! I updated the original post with the PIDCTRL struct.

    replyData is not in shared memory, the data is copied from shared memory into L0-L3.
  • Thanks for clarifying. The raw data looks like I would expect it to. Still not sure why the floats aren't coming out right. What is happening in DbgInfo()?

    Whitney
  • Its building a string message and sending it over a custom protocol back to a console for printing. DbgInfo eventually calls this function which builds the message and sends it (via shared memory and ethernet back to the PC for output).

    error_code TFProtocolDebug::SendMsg(LEVEL level, char* format, ...)
    {
        error_code eResult = TFE_UNINITIALIZED;
    
        TFTempBuffer<char> myBuf(160);
        va_list __va;
        va_start(__va, format);
    #if defined(__TI_ARM_V7M3__) || defined(__TMS320C28XX__)
        // TI RTOS: ARM Cortex M3 or C28 DSP
        //
        System_vsnprintf(myBuf, myBuf.size(), format, __va);
    #elif defined(__linux__)
        vsnprintf(myBuf, myBuf.size(), format, __va);
    #else
        // Windows
        //
        vsprintf_s(myBuf, myBuf.size(), format, __va);
    #endif
        va_end(__va);
    
        if (initialized) {
            if (level <= maxOutputLevel) {
                // Construct the basic output string based on the incoming parameters
                TFProtocolMsg * pMsgBufPtr;
    
                // Get a buffer so we can send the message
                //
                eResult = pTfRouter->GetMessageBuffer(&pMsgBufPtr);
                if (eResult == TFE_SUCCESS)
                {
    
                    // Get the pointer to the payload and cast it to our message type
                    //
                    TFProtocolDebugMsg * pDebugMsg = reinterpret_cast<TFProtocolDebugMsg *>(pMsgBufPtr->payload);
                    if (pDebugMsg == nullptr)
                    {
                        eResult = TFE_INVALID; // don't crash if we get a NULL pointer (safety check)
                    }
                    else
                    {
                        TFTempBuffer<char> myCopy(BYTES_TO_OCTETS(160));
                        strncpypack((char*) myCopy.ptr(), OCTETS_TO_BYTES(myCopy.size()), (const char*) myBuf);
                        tf_uint16 len = (tf_uint16) strlen(myBuf);
                        pDebugMsg->level = level;
                        pDebugMsg->length = len + 1;
                        memcpy(pDebugMsg->text, myCopy.ptr(), BYTES_TO_OCTETS(pDebugMsg->length));
    
                        // Prepare the message for sending
                        //
                        eResult = FinalizeMessage(destination,
                                (tf_uint16)(BYTESOF(pDebugMsg->level) + BYTESOF(pDebugMsg->length) + pDebugMsg->length),
                                pMsgBufPtr);
    
    #ifdef __BIG_ENDIAN__
                        // Protocols must be responsible for byte swapping their header data
                        pDebugMsg->level = htole16(pDebugMsg->level);
                        pDebugMsg->length = htole16(pDebugMsg->length);
    #endif
    
    
                        if (eResult == TFE_SUCCESS)
                        {
                            // Send the message on its way
                            //
                            eResult = pTfRouter->SendMessage(&pMsgBufPtr);
                        }
    
                    }
                }
            } else {
                eResult = TFE_SUCCESS;
            }
        }
    return eResult;
    }
    

  • Just some updates. I was able to get it to work by copying the data to a local buffer and casting off the local buffer:

    uint_least8_t * replyData = <this data comes from the PC>
    
    tf_int8 size = sizeof(PIDCTRL);
    tf_uint8 buf[size];
    memcpy(buf, replyData , size);
    
    
    PIDCTRL *pid = (PIDCTRL *)buf;  // this works

    I also printed the address of both the replyData (@0000996d) and buf (@0000a04c) and they both are in the L0-3 SARAM as according to my cmd file:

     L03SARAM                    : origin = 0x008000, length = 0x004000
     S04SHRAM                   : origin = 0x00C000, length = 0x005000

    The map file gives this region as HeapMem:

    00008100     204 (00008100)     _ti_sysbios_heaps_HeapMem_Instance_State_0_buf__A
    0000e104     384 (0000e100)     _m3_ipc_func_addr

  • I tried placing the 'replyData' buffer in different places in memory (L0-L3, S0-S4 (which the C28 is master), even M0-1) and they all showed the same symptoms of not correctly casting.

    I also tried doing a memcpy to a temp buffer and then memcpy that temp buffer back into the original 'replyData' buffer and did the cast and that still didn't work.

    For now, I am just using the workaround of memcopying the data and using that buffer, but it is not ideal. I'm starting to think it is a compiler issue.

  • Thanks for the updates. My gut feeling was that somewhere along the line, the fact that characters are 16 bits on the C28 and 8 bits on the M3 is causing some trouble, but I'm not sure the experiments and results you've described necessarily support that theory.

    Are you able to study the various buffers and strings using the Memory Browser in CCS or are you currently limited to debugging using the print statements?

    Whitney