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.

IWR6843: Transfer TLV data from SPI_read to UART_write

Part Number: IWR6843

My purpose is to test SPI with 2 IWR6843 EVMs. I need to de target tracking demo to customers. I modified xwr68xx demo code in SDK. I see original demo code do UART_write() with input data: header, tl. As my understanding, those data are header and TLV data frame.

Slave: do SPI_write with same input as UART_write in original demo code.

Need to do settings:

SPI_Params      spiParams;
SPI_Params_init(&spiParams);
spiParams.mode = SPI_SLAVE;

Master: do SPI_read to get data and store into a buffer (rxBuf). 

Settings as a Master

spiParams.mode = SPI_MASTER;

I wanna ask: In order to read TLV header and data frame, what size of rxBuf I need to set to get full package? How to ensure that I get TLV data by SPI_read in correct sequence to write them into UART_write? I think it's not good if I only read all at once, so I need you explain more about principle and sample code for this task is really helpful. Thank you.

In case I want to transfer TLV data from Slave to Master, should I use a fixed size array as a buffer for SPI_write? I think I only need to write head, TLV index into SPI_write. Is it correct? Besides, I don't know whether the Master can read data from Slave all at once or not.

1. Do I need some delay (i don't know what delay function in TI SDK) or something else in Master device code?

2. How to arrange the data reading on Master by SPI_read in a correct sequence? I'm concerned that header and TLV frame data can be mixed up.

Below is my code of Master and Slave.

Master code for SPI_read and UART_write to GUI

static void SPI_to_UART
(
    SPI_Handle      spiHandle,
    UART_Handle     uartHandle,
    DPC_ObjectDetection_ExecuteResult   *result,
    MmwDemo_output_message_stats        *timingInfo
)
{
//Read data from slave
spi_Read(spiHandle, (void *)rxBuf, SPI_DATA_BLOCK_SIZE);
....// 
UART_write(uartHandle, (void *)rxBuf, SPI_DATA_BLOCK_SIZE);
}

I don't know how to handle rxBuf and transfer TLV tracking data to GUI via UART_write in correct sequence (header, data frame TLV index...). Please tell me how to make it work.

Slave code for SPI_write. I modified original demo code. I replaced UART_write by SPI_write with the same input buffer. So I don't declare a txBuf here.

If you don't want to look at the huge code of MmwDemo_transmitProcessedOutput() below, here's my brief idea. Please confirm if my method for Master & Slave write/read is correct.

//UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl));  // original demo code used this line
//UART_writePolling (uartHandle,(uint8_t*)&header, sizeof(MmwDemo_output_message_header));  // original demo code used this line
	
//SPI write head and TLV index from Slave to Master
spi_Write (spiHandle, (uint8_t*)&header, sizeof(MmwDemo_output_message_header));   
spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl));

static void MmwDemo_transmitProcessedOutput
(
SPI_Handle      spiHandle, UART_Handle uartHandle, DPC_ObjectDetection_ExecuteResult *result, MmwDemo_output_message_stats *timingInfo ) { SPI_Handle spiHandle; MmwDemo_output_message_header header; MmwDemo_GuiMonSel *pGuiMonSel; MmwDemo_SubFrameCfg *subFrameCfg; uint32_t tlvIdx = 0; //uint32_t tlvIdx_spi = 0; uint32_t index; uint32_t numPaddingBytes; uint32_t packetLen; uint8_t padding[MMWDEMO_OUTPUT_MSG_SEGMENT_LEN]; MmwDemo_output_message_tl tl[MMWDEMO_OUTPUT_MSG_MAX]; int32_t errCode; uint16_t *detMatrix = (uint16_t *)result->detMatrix.data; DPIF_PointCloudCartesian *objOut; cmplx16ImRe_t *azimuthStaticHeatMap; DPIF_PointCloudSideInfo *objOutSideInfo; DPC_ObjectDetection_Stats *stats; //spiDataMsg *pTestMsgOut; //uint16_t seqNo; //uint16_t dc_offset; //int rangeLength,i; /* Get subframe configuration */ subFrameCfg = &gMmwMssMCB.subFrameCfg[result->subFrameIdx]; /* Get Gui Monitor configuration */ pGuiMonSel = &subFrameCfg->guiMonSel; /* Clear message header */ memset((void *)&header, 0, sizeof(MmwDemo_output_message_header)); //Read data from slave //spi_Read(spiHandle, (void *)rxBuf, SPI_DATA_BLOCK_SIZE); //pTestMsgOut = (spiDataMsg *)&rxBuf[0]; /****************************************************************** Send out data that is enabled, Since processing results are from DSP, address translation is needed for buffer pointers *******************************************************************/ { detMatrix = (uint16_t *) SOC_translateAddress((uint32_t)detMatrix, SOC_TranslateAddr_Dir_FROM_OTHER_CPU, &errCode); DebugP_assert ((uint32_t)detMatrix!= SOC_TRANSLATEADDR_INVALID); objOut = (DPIF_PointCloudCartesian *) SOC_translateAddress((uint32_t)result->objOut, SOC_TranslateAddr_Dir_FROM_OTHER_CPU, &errCode); DebugP_assert ((uint32_t)objOut != SOC_TRANSLATEADDR_INVALID); objOutSideInfo = (DPIF_PointCloudSideInfo *) SOC_translateAddress((uint32_t)result->objOutSideInfo, SOC_TranslateAddr_Dir_FROM_OTHER_CPU, &errCode); DebugP_assert ((uint32_t)objOutSideInfo != SOC_TRANSLATEADDR_INVALID); stats = (DPC_ObjectDetection_Stats *) SOC_translateAddress((uint32_t)result->stats, SOC_TranslateAddr_Dir_FROM_OTHER_CPU, &errCode); DebugP_assert ((uint32_t)stats != SOC_TRANSLATEADDR_INVALID); result->radarCube.data = (void *) SOC_translateAddress((uint32_t) result->radarCube.data, SOC_TranslateAddr_Dir_FROM_OTHER_CPU, &errCode); DebugP_assert ((uint32_t) result->radarCube.data!= SOC_TRANSLATEADDR_INVALID); } /* Header: */ header.platform = 0xA6843; header.magicWord[0] = 0x0102; header.magicWord[1] = 0x0304; header.magicWord[2] = 0x0506; header.magicWord[3] = 0x0708; header.numDetectedObj = result->numObjOut; header.version = MMWAVE_SDK_VERSION_BUILD | (MMWAVE_SDK_VERSION_BUGFIX << 8) | (MMWAVE_SDK_VERSION_MINOR << 16) | (MMWAVE_SDK_VERSION_MAJOR << 24); packetLen = sizeof(MmwDemo_output_message_header); if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) && (result->numObjOut > 0)) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS; tl[tlvIdx].length = sizeof(DPIF_PointCloudCartesian) * result->numObjOut; packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } /* Side info */ if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0)) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO; tl[tlvIdx].length = sizeof(DPIF_PointCloudSideInfo) * result->numObjOut; packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } if (pGuiMonSel->logMagRange) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_PROFILE; tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins; packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } if (pGuiMonSel->noiseProfile) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_NOISE_PROFILE; tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins; packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } if (pGuiMonSel->rangeAzimuthHeatMap) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP; tl[tlvIdx].length = result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t); packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } if (pGuiMonSel->rangeDopplerHeatMap) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP; tl[tlvIdx].length = subFrameCfg->numRangeBins * subFrameCfg->numDopplerBins * sizeof(uint16_t); packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } if (pGuiMonSel->statsInfo) { tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_STATS; tl[tlvIdx].length = sizeof(MmwDemo_output_message_stats); packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length; tlvIdx++; } header.numTLVs = tlvIdx; /* Round up packet length to multiple of MMWDEMO_OUTPUT_MSG_SEGMENT_LEN */ header.totalPacketLen = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN * ((packetLen + (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1))/MMWDEMO_OUTPUT_MSG_SEGMENT_LEN); header.timeCpuCycles = Pmu_getCount(0); header.frameNumber = stats->frameStartIntCounter; header.subFrameNumber = result->subFrameIdx; //UART_writePolling (uartHandle,(uint8_t*)&header, sizeof(MmwDemo_output_message_header)); //SPI write from Slave to Master //spi_Write (spiHandle, (uint8_t*)pTestMsgOut, SPI_DATA_BLOCK_SIZE); spi_Write (spiHandle, (uint8_t*)&header, sizeof(MmwDemo_output_message_header)); tlvIdx = 0; /* Send detected Objects */ if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) && (result->numObjOut > 0)) { //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); /*Send array of objects */ //UART_writePolling (uartHandle, (uint8_t*)objOut, sizeof(DPIF_PointCloudCartesian) * result->numObjOut); spi_Write (spiHandle, (uint8_t*)objOut, sizeof(DPIF_PointCloudCartesian) * result->numObjOut); tlvIdx++; } /* Send detected Objects Side Info */ if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0)) { //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); //UART_writePolling (uartHandle, (uint8_t*)objOutSideInfo, sizeof(DPIF_PointCloudSideInfo) * result->numObjOut); spi_Write (spiHandle, (uint8_t*)objOutSideInfo, sizeof(DPIF_PointCloudSideInfo) * result->numObjOut); tlvIdx++; } /* Send Range profile */ if (pGuiMonSel->logMagRange) { //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx], sizeof(MmwDemo_output_message_tl)); for(index = 0; index < subFrameCfg->numRangeBins; index++) { //UART_writePolling (uartHandle,(uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins], sizeof(uint16_t)); spi_Write (spiHandle, (uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins], sizeof(uint16_t)); } tlvIdx++; } /* Send noise profile */ if (pGuiMonSel->noiseProfile) { uint32_t maxDopIdx = subFrameCfg->numDopplerBins/2 -1; //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); for(index = 0; index < subFrameCfg->numRangeBins; index++) { //UART_writePolling (uartHandle,(uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins + maxDopIdx],sizeof(uint16_t)); spi_Write (spiHandle, (uint8_t*)&detMatrix[index*subFrameCfg->numDopplerBins + maxDopIdx],sizeof(uint16_t)); } tlvIdx++; } /* Send data for static azimuth heatmap */ if (pGuiMonSel->rangeAzimuthHeatMap) { azimuthStaticHeatMap = (cmplx16ImRe_t *) SOC_translateAddress((uint32_t)result->azimuthStaticHeatMap, SOC_TranslateAddr_Dir_FROM_OTHER_CPU, &errCode); DebugP_assert ((uint32_t)azimuthStaticHeatMap!= SOC_TRANSLATEADDR_INVALID); //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); //UART_writePolling (uartHandle,(uint8_t *)azimuthStaticHeatMap,result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t)); spi_Write (spiHandle, (uint8_t *)azimuthStaticHeatMap,result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t)); tlvIdx++; } /* Send data for range/Doppler heatmap */ if (pGuiMonSel->rangeDopplerHeatMap == 1) { //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); //UART_writePolling (uartHandle,(uint8_t*)detMatrix,tl[tlvIdx].length); spi_Write (spiHandle, (uint8_t*)detMatrix,tl[tlvIdx].length); tlvIdx++; } /* Send stats information */ if (pGuiMonSel->statsInfo == 1) { //UART_writePolling (uartHandle,(uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); spi_Write (spiHandle, (uint8_t*)&tl[tlvIdx],sizeof(MmwDemo_output_message_tl)); /* Address translation is done when buffer is received*/ //UART_writePolling (uartHandle,(uint8_t*)timingInfo,tl[tlvIdx].length); spi_Write (spiHandle, (uint8_t*)timingInfo,tl[tlvIdx].length); tlvIdx++; } /* Send padding bytes */ numPaddingBytes = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN - (packetLen & (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1)); if (numPaddingBytes<MMWDEMO_OUTPUT_MSG_SEGMENT_LEN) { //UART_writePolling (uartHandle,(uint8_t*)padding,numPaddingBytes); spi_Write (spiHandle, (uint8_t*)padding,numPaddingBytes); } }
  • Dear Hector:

    From the code that you have provided, the API for the SPI driver appears to not be the API that is included in the SDK. Could you please provide the source of this API so we can verify this.

    If you haven't already I would read about the difference between UART_write() and UART_writePolling() because if you are going to make a one to one replacement with SPI you need to have a firm understanding of the capability of the SPI API so that it can provide the same functionality of UART_writePolling().

    Also follow this path to review the structure and size of the data sent from the radar device:

    <SDK Install Path>/packages/ti/demo/xwr68xx/mmw/docs/doxygen/html/index.html

    Let me know specifically about the details of how you are using SPI.

    Best regards,

    Connor Desmond

  • Hi Connor,

    I use SPI lib in TI package. It belongs to SDK. SPI_write just perform SPI_transfer in case we set a value txBuf and set rxBuf = NULL. UART_write and UART_writePolling is just the way we name it, not mandatory to fixed with it. No matter how I wrote the code, can you give me a code for 2 IWR6843 EVMs that work as Master & Slave communicate via SPI ? I made SPI test code in SPI driver folder do SPI_write as a Master. But xwr68xx demo code still not work. You don't need to care how I wrote my code above. Please show me a simplified code that transfer TLV data between Master & Slave via SPI. It'd be good if you can add SPI function in the code of 3D_people_count or HVAC (in toolbox 4.2.1).

    Anyways, normally, we do SPI_read on Master and SPI_write on Slave. Can we also do SPI_write on Master and SPI_read on Slave?

  • Hector,

    I am closing this thread as it is a duplicate of the following thread:

    https://e2e.ti.com/support/sensors/f/1023/p/897434/3346266#3346266

    -Connor Desmond

  • Connor,

    Even if u want to close it, please join the discussion of that thread and help me. Thanks