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.
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
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.