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.

RTOS/IWR1443: Using Chip Select for IWR as SPI slave

Part Number: IWR1443

Tool/software: TI-RTOS

Hi, 

I am trying to talk to multiple IWR1443 radars from a single MSP430 on the same SPI bus using chip select lines from the MSP430. The driver documentation says the SPI driver operates transparent from the chip select. How do I enable the SPI module in the IWR1443 to be chip select aware?

Thanks,

Kevin

  • Hi Kevin,

    When using the SPI in slave mode, the driver enables the hardware to chip select 0 automatically by default.  You can change it to use a different chip select on the device by adding the line below in bold to your code and changing the value.

    SPI Slave setup example code snippet from mmwave_sdk_01_02_00_05/packages/ti/drivers/spi/docs/doxygen/html/index.html:

    SPI_Handle      handle;

    SPI_Params      params;

    SPI_Transaction spiTransaction;

    SPI_Params_init(&params);

    params.mode = SPI_SLAVE;

    params.frameFormat = SPI_POL0_PHA0;

    params.pinMode = SPI_PINMODE_4PIN_CS;

    params.shiftFormat = SPI_MSB_FIRST;

    params.dmaEnable = 1;

    params.dmaHandle = gDmaHandle;

    params.u.slaveParams.dmaCfg.txDmaChanNum =1U;

    params.u.slaveParams.dmaCfg.rxDmaChanNum =0U;

    params.u.slaveParams.chipSelect =0U;  // 0 = chip select 0, 1 = chip select 1, etc.

    handle = SPI_open(someSPI_configIndexValue, &params);

    if (!handle) {

       System_printf("SPI did not open");

    }

    If you are interested in more information on the hardware itself, the SPI slave chip select functionality is enabled using the SPIPC0 register in the SPI module.  The "Multi-Buffered Serial Peripheral Interface Module (MibSPI)" section in the Industrial Family TRM doc has more details.

    Regards,

    John

  • Thanks John,

    I gave this a try with chipSelect set to 0,  1, and 2. I am using the IWR1443 boost eval kit. When it was set to 0, it did not receive any data regardless of the chip select. When set to 1 or 2, it received data regardless of the chip select.

    What is the correct chipSelect number for the SPI_CS_1 pin on the IWR1443?

    My code is as follows:

    mmw_spi.c
    #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/gates/GateMutex.h>
    #include <xdc/runtime/System.h>
    
    #include "mmw_config.h"
    #include "mmw_spi.h"
    
    #include "data_path.h"
    
    uint32_t numberOfDetectedObjects;
    MmwDemo_detectedObj objectsToSend[MMW_MAX_OBJ_OUT];
    Semaphore_Handle spiOutputDataBufferReady;
    GateMutex_Handle spiOutputDataBufferMutex;
    
    #define SPI_DATA_OBJ_SIZE 12
    
    void setSpiObjectsToSend(MmwDemo_DataPathObj* objects)
    {
        // UInt key = GateMutex_enter(spiOutputDataBufferMutex);
    
        memcpy(&objectsToSend, objects->objOut,
               sizeof(MmwDemo_detectedObj) * MMW_MAX_OBJ_OUT);
        numberOfDetectedObjects = objects->numObjOut;
    
        Semaphore_post(spiOutputDataBufferReady);
    
        // GateMutex_leave(spiOutputDataBufferMutex, key);
    }
    
    /**
     *  @b Description
     *  @n
     *      This task manages communications over the SPI bus. The IWR1443 behaves
     * as a slave
     *      to transmit data to a host processor
     *
     *  @retval
     *      Not applicable
     */
    void Spi_CommunicationsTask(UArg arg0, UArg arg1)
    {
        GateMutex_Params gateParams;
        GateMutex_Params_init(&gateParams);
        spiOutputDataBufferMutex = GateMutex_create(&gateParams, NULL);
    
        Semaphore_Params semParams;
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        spiOutputDataBufferReady = Semaphore_create(1, &semParams, NULL);
    
        // Setup PINMUX to SPIA
        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);
    
        // Pin for notifying spi host that data is ready, active low
        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);
    
        DMA_Params dmaParams;
        DMA_Handle dmaHandle;
        int errCode;
        DMA_init();
        DMA_Params_init(&dmaParams);
        dmaHandle = DMA_open(0, &dmaParams, &errCode);
    
        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.pinMode = SPI_PINMODE_3PIN;
        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 = 10;             // Time in system ticks
        spiParams.transferMode = SPI_MODE_BLOCKING; // KJL: Still not sure what
        // affect this has on operation
    
        spiHandle = SPI_open(0, &spiParams);
        if (!spiHandle)
        {
            MmwDemo_debugAssert(0);
            return;
        }
        SPI_Transaction transaction;
        char transmitBuffer[SPI_DATA_OBJ_SIZE];
        char receiveBuffer[16];
        Bool transferOk;
        transaction.count = 2;
        transaction.txBuf = transmitBuffer;
        transaction.rxBuf = receiveBuffer;
    
        enum spiState
        {
            IDLE = 0,
            RUNNING = 1,
            SEND_CONFIG = 2,
            INVALID_IDLE_COMMAND = 3,
            INVALID_RUNNING_COMMAND = 4,
            ERROR = 5
        };
        enum spiState spiState;
        spiState = IDLE;
    
        while (1)
        {
            switch (spiState)
            {
            case IDLE:
            {
                transmitBuffer[0] = 0x01;
                System_printf("Idle");
            }
            break;
            case RUNNING:
            {
                while (1)
                {
                    if (Semaphore_pend(spiOutputDataBufferReady, BIOS_WAIT_FOREVER))
                    {
    
                        int key = GateMutex_enter(spiOutputDataBufferMutex);
                        int i;
    
                        // Send data length
                        transaction.count = 2;
                        transmitBuffer[0] = 0xAA; // Data Ready flag
                        transmitBuffer[1] = numberOfDetectedObjects;
                        GPIO_write(SOC_XWR14XX_GPIO_12, 0U);
                        int retryCount = 0;
                        do
                        {
                            retryCount++;
                            SPI_transfer(spiHandle, &transaction);
                            if (retryCount > 15)
                            {
                                break;
                            }
                        } while (transaction.status != SPI_TRANSFER_COMPLETED);
    
                        transmitBuffer[0] = 0x12;
                        memcpy(&transmitBuffer[0], (void*)objectsToSend,
                               SPI_DATA_OBJ_SIZE);
                        transaction.count = SPI_DATA_OBJ_SIZE;
                        retryCount = 0;
                        do
                        {
                            SPI_transfer(spiHandle, &transaction);
                            if (retryCount > 15)
                            {
                                break;
                            }
                            retryCount++;
                        } while (transaction.status != SPI_TRANSFER_COMPLETED);
    
                        GPIO_write(SOC_XWR14XX_GPIO_12, 1U);
    
                        GateMutex_leave(spiOutputDataBufferMutex, key);
                    }
                }
            }
            break;
            case SEND_CONFIG:
            {
                transmitBuffer[0] = 0x03;
                System_printf("Send Config");
            }
            case INVALID_IDLE_COMMAND:
            {
                transmitBuffer[0] = 0x0F;
                System_printf("Invalid command");
                spiState = IDLE;
            }
            break;
            case INVALID_RUNNING_COMMAND:
            {
                transmitBuffer[0] = 0x0F;
                System_printf("Invalid command");
                spiState = RUNNING;
            }
            break;
            case ERROR:
            {
                transmitBuffer[0] = 0x7a;
                System_printf("Error");
            }
            break;
            default:
                // Should never get here
            }
            transaction.count = 2;
            do
            {
                int ret = SPI_transfer(spiHandle, &transaction);
            } while (transaction.status != SPI_TRANSFER_COMPLETED);
    
            MmwDemo_debugAssert(transaction.status == SPI_TRANSFER_COMPLETED);
    
            switch (receiveBuffer[1])
            {
            case 0x01: // Sensor Stop
            {
                if (spiState == RUNNING)
                {
                    System_printf("Stopping Sensor");
                    MmwDemo_notifySensorStop();
                    MmwDemo_waitSensorStopComplete();
                    spiState = IDLE;
                }
                else
                {
                    spiState = INVALID_IDLE_COMMAND;
                    System_printf("Sensor is already stopped");
                }
            }
            break;
            case 0x02: // Sensor Start
            {
                // Sensor Start
                if (spiState == RUNNING)
                {
                    spiState = INVALID_RUNNING_COMMAND;
                    System_printf("Sensor is already running");
                }
                else
                {
                    spiState = RUNNING;
                    MmwDemo_notifySensorStart(true);
                    System_printf("Sensor is already stopped");
                    MmwDemo_waitSensorStartComplete();
                }
            }
            break;
            case 0xfa:
            {
                // Load full config defaults and start sensor
                LoadDefaultConfig();
                System_printf("Starting sensor withe default config");
                spiState = RUNNING;
            }
            break;
            default:
                System_printf("Invalid command");
            }
        }
    }
    

  • Hi Kevin,

    Since there is only one chip select pin on the device per SPI peripheral the SPI_CS_1 pin should correspond to chip select 0 for the first SPI peripheral (MIBSPIA (index = 0 for SPI_open() function)). If you have a IWR1443 Rev B EVM you may want to check that S1 is open so that the SPI/CAN mux is selecting SPI (see the Rev B EVM schematic for more details).

    Regards,
    John
  • Thanks John,

    This was helpful. I was missing setting the spiParams.csHold = 1; since I am sending multiple bytes without reasserting the chip select. The chip select is working now.

    Thanks,

    Kevin