Other Parts Discussed in Thread: MMWAVE-SDK
Hi,
I am trying to use an IWR1443 as a spi slave connected to an MSP430 which is serving as the master. I have gotten it working with the IWR1443 sending 64 byte packets at a time but I would like to be able to read out a longer list of objects all at once. Currently reading all the detected objects requires reading out 20 separate 64 byte packets.
The mmwave sdk documentation for v 2.01.00.04 for the spi module has a mention of a MIBSPI_RAM_MAX_ELEM which is 64 but it also gives some vague information about transmitting amounts larger than the RAM buffer size as a compile time option.
1. How can I tell if this was enabled as a compile time option in the mmwave SDK and if it is not is there a way I can enable it?
2. Is there a timing diagram that describes how long the SPI master must deactivate the CS/CLK signal to allow transfers?
3. Why can the driver not load the ram buffer as the transaction progresses? Since I am only running my spi bus at 2MHz I would think the IWR processor would be able to keep the SPI module continuously fed with data to transmit?
SPI Code to send 64 bytes
#include <ti/drivers/dma/dma.h> #include <ti/drivers/gpio/gpio.h> #include <ti/drivers/pinmux/pinmux.h> #include <ti/drivers/spi/SPI.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/gates/GateMutex.h> #include <xdc/runtime/System.h> // clang-format off #include <ti/control/mmwavelink/mmwavelink.h> #include <ti/control/mmwavelink/include/rl_datatypes.h> #include <ti/control/mmwavelink/include/rl_sensor.h> // clang-format on #include "mmw.h" #include "mmw_spi.h" uint32_t numberOfDetectedObjects; MmwDemo_detectedObj objectsToSend[MMW_MAX_OBJ_OUT]; Semaphore_Handle spiOutputDataBufferReady; uint32_t qformat; rlRfTempData_t tempData = {0}; typedef struct dssCalibrationData { float rangeBias; int16_t comps[24]; } dssCalibrationData_t; dssCalibrationData_t calibrationData; // Packet format definitions // 4 byte header // 5 - 12 byte objects // 100 objects total -> 20 packets #define SPI_DATA_PACKET_SIZE 64 #define SPI_PACKETS_PER_FRAME 20 #define SPI_OBJ_PER_PACKET 5 #define PACKET_OBJ_SIZE 60 uint8_t txPlaceholder[1344] = {0x5A}; uint8_t rxPlaceholder[1344] = {0x5A}; void setCalibrationData(MmwDemo_DataPathObj* obj) { calibrationData.rangeBias = obj->cliCommonCfg->compRxChanCfg.rangeBias; int32_t i; for (i = 0; i < 12; i++) { calibrationData.comps[(i * 2)] = obj->cliCommonCfg->compRxChanCfg.rxChPhaseComp[i].real; calibrationData.comps[(i * 2) + 1] = obj->cliCommonCfg->compRxChanCfg.rxChPhaseComp[i].imag; } // Semaphore_post(spiOutputDataBufferReady); } /** * @b Description * @n * This method copies the detected objects to the buffer used by the SPI * task and then notifies the SPI task that the data is ready to be sent * * @retval * Not applicable */ void setSpiObjectsToSend(MmwDemo_DataPathObj* objects) { static int temperatureCounter = 0; temperatureCounter++; if (temperatureCounter == 10) { int32_t retVal; retVal = rlRfGetTemperatureReport(RL_DEVICE_MAP_INTERNAL_BSS, (rlRfTempData_t*)&tempData); if (retVal != 0) { // An error occurred System_printf("Error reading temperature\n"); } temperatureCounter = 0; } memcpy(&objectsToSend, objects->objOut, sizeof(MmwDemo_detectedObj) * MMW_MAX_OBJ_OUT); numberOfDetectedObjects = objects->numObjOut; qformat = objects->xyzOutputQFormat; Semaphore_post(spiOutputDataBufferReady); } /** * @b Description * @n * This task manages communications over the SPI bus. The IWR1443 behaves * as a slave to transmit data to a host processor. The IWR pulls the * SPI_HOST_INTR pin low when there is a data packet ready for transmission task * and then notifies the SPI task that the data is ready to be sent * * @retval * Not applicable */ void Spi_CommunicationsTask(UArg arg0, UArg arg1) { Semaphore_Params semParams; Semaphore_Params_init(&semParams); semParams.mode = Semaphore_Mode_BINARY; spiOutputDataBufferReady = Semaphore_create(1, &semParams, NULL); // Setup PINMUX for SPIA // P6 - SPI_HOST_INTR_1 // P5 - MISO // R8 - MOSI // R9 - SPI_CLK // R7 - SPI_CS Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINR8_PADAD, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINR8_PADAD, SOC_XWR14XX_PINR8_PADAD_SPIA_MOSI); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINP5_PADAE, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINP5_PADAE, SOC_XWR14XX_PINP5_PADAE_SPIA_MISO); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINR9_PADAF, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINR9_PADAF, SOC_XWR14XX_PINR9_PADAF_SPIA_CLK); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINR7_PADAG, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINR7_PADAG, SOC_XWR14XX_PINR7_PADAG_SPIA_CS); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINP6_PADAA, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINP6_PADAA, SOC_XWR14XX_PINP6_PADAA_GPIO_12); GPIO_setConfig(SOC_XWR14XX_GPIO_12, GPIO_CFG_OUTPUT); GPIO_write(SOC_XWR14XX_GPIO_12, 1U); // Setup the DMA module for the SPI driver to use DMA_Params dmaParams; DMA_Handle dmaHandle; int errCode; DMA_init(); DMA_Params_init(&dmaParams); dmaHandle = DMA_open(0, &dmaParams, &errCode); // Setup the SPI driver SPI_Handle spiHandle; SPI_init(); SPI_Params spiParams; SPI_Params_init(&spiParams); spiParams.mode = SPI_SLAVE; spiParams.frameFormat = SPI_POL0_PHA0; spiParams.pinMode = SPI_PINMODE_4PIN_CS; spiParams.shiftFormat = SPI_MSB_FIRST; spiParams.dmaEnable = 1; spiParams.dmaHandle = dmaHandle; spiParams.u.slaveParams.dmaCfg.txDmaChanNum = 1U; spiParams.u.slaveParams.dmaCfg.rxDmaChanNum = 0U; spiParams.u.slaveParams.chipSelect = 0U; spiParams.dataSize = 8; spiParams.transferTimeout = 50; // Time in system ticks spiParams.csHold = 1; spiParams.transferMode = SPI_MODE_BLOCKING; spiHandle = SPI_open(0, &spiParams); if (!spiHandle) { MmwDemo_debugAssert(0); return; } SPI_Transaction transaction; char transmitBuffer[SPI_DATA_PACKET_SIZE]; char receiveBuffer[SPI_DATA_PACKET_SIZE]; transaction.count = 1344; transaction.txBuf = txPlaceholder; transaction.rxBuf = rxPlaceholder; transaction.slaveIndex = 0; uint16_t frameCount = 0; while (1) { uint8_t packetCount = 0; if (Semaphore_pend(spiOutputDataBufferReady, BIOS_WAIT_FOREVER)) { // #define RUN_CALIBRATE #ifdef RUN_CALIBRATE memset(transmitBuffer, 0, sizeof(transmitBuffer)); memcpy(transmitBuffer, &calibrationData, sizeof(calibrationData)); for(packetCount = 0; packetCount <= SPI_PACKETS_PER_FRAME; packetCount++) { memcpy(transmitBuffer + 3, &calibrationData, sizeof(calibrationData)); transmitBuffer[2] = packetCount + 1; GPIO_write(SOC_XWR14XX_GPIO_12, 0U); SPI_transfer(spiHandle, &transaction); GPIO_write(SOC_XWR14XX_GPIO_12, 1U); } #else // Clear the buffer since the first memcpy does not write the entire // buffer memset(transmitBuffer, 0, sizeof(transmitBuffer)); // Set the frame count GPIO_write(SOC_XWR14XX_GPIO_12, 0U); SPI_transfer(spiHandle, &transaction); GPIO_write(SOC_XWR14XX_GPIO_12, 1U); // for (packetCount = 0; packetCount < SPI_PACKETS_PER_FRAME; // packetCount++) // { // transmitBuffer[2] = packetCount + 1; // transmitBuffer[3] = numberOfDetectedObjects & 0xFF; // int memIndex = SPI_OBJ_PER_PACKET * packetCount; // memcpy(transmitBuffer + 4, &objectsToSend[memIndex], PACKET_OBJ_SIZE); // GPIO_write(SOC_XWR14XX_GPIO_12, 0U); // SPI_transfer(spiHandle, &transaction); // GPIO_write(SOC_XWR14XX_GPIO_12, 1U); // } #endif } frameCount++; } }
SPI Code attempt to send 1344 bytes
#include <ti/drivers/dma/dma.h> #include <ti/drivers/gpio/gpio.h> #include <ti/drivers/pinmux/pinmux.h> #include <ti/drivers/spi/SPI.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/gates/GateMutex.h> #include <xdc/runtime/System.h> // clang-format off #include <ti/control/mmwavelink/mmwavelink.h> #include <ti/control/mmwavelink/include/rl_datatypes.h> #include <ti/control/mmwavelink/include/rl_sensor.h> // clang-format on #include "mmw.h" #include "mmw_spi.h" uint32_t numberOfDetectedObjects; MmwDemo_detectedObj objectsToSend[MMW_MAX_OBJ_OUT]; Semaphore_Handle spiOutputDataBufferReady; uint32_t qformat; rlRfTempData_t tempData = {0}; typedef struct dssCalibrationData { float rangeBias; int16_t comps[24]; } dssCalibrationData_t; dssCalibrationData_t calibrationData; // Packet format definitions // 4 byte header // 5 - 12 byte objects // 100 objects total -> 20 packets #define SPI_DATA_PACKET_SIZE 64 #define SPI_PACKETS_PER_FRAME 20 #define SPI_OBJ_PER_PACKET 5 #define PACKET_OBJ_SIZE 60 uint8_t txPlaceholder[1344] = {0x5A}; uint8_t rxPlaceholder[1344] = {0x5A}; void setCalibrationData(MmwDemo_DataPathObj* obj) { calibrationData.rangeBias = obj->cliCommonCfg->compRxChanCfg.rangeBias; int32_t i; for (i = 0; i < 12; i++) { calibrationData.comps[(i * 2)] = obj->cliCommonCfg->compRxChanCfg.rxChPhaseComp[i].real; calibrationData.comps[(i * 2) + 1] = obj->cliCommonCfg->compRxChanCfg.rxChPhaseComp[i].imag; } // Semaphore_post(spiOutputDataBufferReady); } /** * @b Description * @n * This method copies the detected objects to the buffer used by the SPI * task and then notifies the SPI task that the data is ready to be sent * * @retval * Not applicable */ void setSpiObjectsToSend(MmwDemo_DataPathObj* objects) { static int temperatureCounter = 0; temperatureCounter++; if (temperatureCounter == 10) { int32_t retVal; retVal = rlRfGetTemperatureReport(RL_DEVICE_MAP_INTERNAL_BSS, (rlRfTempData_t*)&tempData); if (retVal != 0) { // An error occurred System_printf("Error reading temperature\n"); } temperatureCounter = 0; } memcpy(&objectsToSend, objects->objOut, sizeof(MmwDemo_detectedObj) * MMW_MAX_OBJ_OUT); numberOfDetectedObjects = objects->numObjOut; qformat = objects->xyzOutputQFormat; Semaphore_post(spiOutputDataBufferReady); } /** * @b Description * @n * This task manages communications over the SPI bus. The IWR1443 behaves * as a slave to transmit data to a host processor. The IWR pulls the * SPI_HOST_INTR pin low when there is a data packet ready for transmission task * and then notifies the SPI task that the data is ready to be sent * * @retval * Not applicable */ void Spi_CommunicationsTask(UArg arg0, UArg arg1) { Semaphore_Params semParams; Semaphore_Params_init(&semParams); semParams.mode = Semaphore_Mode_BINARY; spiOutputDataBufferReady = Semaphore_create(1, &semParams, NULL); // Setup PINMUX for SPIA // P6 - SPI_HOST_INTR_1 // P5 - MISO // R8 - MOSI // R9 - SPI_CLK // R7 - SPI_CS Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINR8_PADAD, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINR8_PADAD, SOC_XWR14XX_PINR8_PADAD_SPIA_MOSI); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINP5_PADAE, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINP5_PADAE, SOC_XWR14XX_PINP5_PADAE_SPIA_MISO); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINR9_PADAF, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINR9_PADAF, SOC_XWR14XX_PINR9_PADAF_SPIA_CLK); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINR7_PADAG, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINR7_PADAG, SOC_XWR14XX_PINR7_PADAG_SPIA_CS); Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINP6_PADAA, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL); Pinmux_Set_FuncSel(SOC_XWR14XX_PINP6_PADAA, SOC_XWR14XX_PINP6_PADAA_GPIO_12); GPIO_setConfig(SOC_XWR14XX_GPIO_12, GPIO_CFG_OUTPUT); GPIO_write(SOC_XWR14XX_GPIO_12, 1U); // Setup the DMA module for the SPI driver to use DMA_Params dmaParams; DMA_Handle dmaHandle; int errCode; DMA_init(); DMA_Params_init(&dmaParams); dmaHandle = DMA_open(0, &dmaParams, &errCode); // Setup the SPI driver SPI_Handle spiHandle; SPI_init(); SPI_Params spiParams; SPI_Params_init(&spiParams); spiParams.mode = SPI_SLAVE; spiParams.frameFormat = SPI_POL0_PHA0; spiParams.pinMode = SPI_PINMODE_4PIN_CS; spiParams.shiftFormat = SPI_MSB_FIRST; spiParams.dmaEnable = 1; spiParams.dmaHandle = dmaHandle; spiParams.u.slaveParams.dmaCfg.txDmaChanNum = 1U; spiParams.u.slaveParams.dmaCfg.rxDmaChanNum = 0U; spiParams.u.slaveParams.chipSelect = 0U; spiParams.dataSize = 8; spiParams.transferTimeout = 50; // Time in system ticks spiParams.csHold = 1; spiParams.transferMode = SPI_MODE_BLOCKING; spiHandle = SPI_open(0, &spiParams); if (!spiHandle) { MmwDemo_debugAssert(0); return; } SPI_Transaction transaction; char transmitBuffer[SPI_DATA_PACKET_SIZE]; char receiveBuffer[SPI_DATA_PACKET_SIZE]; transaction.count = 1344; transaction.txBuf = txPlaceholder; transaction.rxBuf = rxPlaceholder; transaction.slaveIndex = 0; uint16_t frameCount = 0; while (1) { uint8_t packetCount = 0; if (Semaphore_pend(spiOutputDataBufferReady, BIOS_WAIT_FOREVER)) { // #define RUN_CALIBRATE #ifdef RUN_CALIBRATE memset(transmitBuffer, 0, sizeof(transmitBuffer)); memcpy(transmitBuffer, &calibrationData, sizeof(calibrationData)); for(packetCount = 0; packetCount <= SPI_PACKETS_PER_FRAME; packetCount++) { memcpy(transmitBuffer + 3, &calibrationData, sizeof(calibrationData)); transmitBuffer[2] = packetCount + 1; GPIO_write(SOC_XWR14XX_GPIO_12, 0U); SPI_transfer(spiHandle, &transaction); GPIO_write(SOC_XWR14XX_GPIO_12, 1U); } #else // Clear the buffer since the first memcpy does not write the entire // buffer memset(transmitBuffer, 0, sizeof(transmitBuffer)); // Set the frame count GPIO_write(SOC_XWR14XX_GPIO_12, 0U); SPI_transfer(spiHandle, &transaction); GPIO_write(SOC_XWR14XX_GPIO_12, 1U); // for (packetCount = 0; packetCount < SPI_PACKETS_PER_FRAME; // packetCount++) // { // transmitBuffer[2] = packetCount + 1; // transmitBuffer[3] = numberOfDetectedObjects & 0xFF; // int memIndex = SPI_OBJ_PER_PACKET * packetCount; // memcpy(transmitBuffer + 4, &objectsToSend[memIndex], PACKET_OBJ_SIZE); // GPIO_write(SOC_XWR14XX_GPIO_12, 0U); // SPI_transfer(spiHandle, &transaction); // GPIO_write(SOC_XWR14XX_GPIO_12, 1U); // } #endif } frameCount++; } }