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.

AM5728: Multiple devices on one SPI

Part Number: AM5728

Hi,

I am using  PROCESSOR-SDK-RTOS-AM57X - pdk_am57xx_1_0_7.

We had a query in forum about using the McSPI for mutiple devices, but we didn't get any solution so am opening the thread for the same.

https://e2e.ti.com/support/processors/f/791/t/754225

We are stuck in the issue that we are not able to access the two devices on the same Spi bus.

When we tried to access the device, other device chip select is also asserting. 

we tried with all suggestions we got from forum in the above link mentioned.

And when we tried to configure both channels as MCSPI_MULTI_CH, we are observing that both the channels are not working.

Can you please test the multi channel example from your side and suggest us another example for multi-channel.

for exmple; when we tried to use the SPI_BUS1 which has two devices. CS0->device_1 and CS1->device_2.

when we tired to use CS0, CS1 also active and vice versa.

Please take this one as higher priority, this is blocker for the further work.

Thanks in advance.

Ranganath V N

  • Multi-channel mode is supported in the Proc-SDK, but due to the h/w limitation, we only tested one channel case. You may refer to the master/slave example for details. By default, the driver sets the channel in single channel mode (chMode = MCSPI_SINGLE_CH in SPI_v1_HWAttrs). The example should use SPI_socSetInitCfg() API to change it to MCSPI_MULTI_CH in multi channel mode.

    the current example in the PDK that we support (SPI LLD master-slave example) has a multichannel test doesn`t set MCSPI_MULTI_CH mode in the SOC configuration . The example seems to open multiple handles in single channel mode and test transactions on each channel so what we are testing is not multichannel mode but single channel mode operation using different channels.

  • Hi Rahul,

    Thanks for your answer.

    We already tried this already and have suggested previously on the other thread regarding same issue. when we configured both the channels as multi_channel none of the channels are not getting any data 

    or any transaction is not happening on that bus.

    When we tried multi-channel for one channel that channel only receiving the data, we are suspecting that channels are not configuring properly. 

    Thanks and regards,

    Ranganath

  • Hi,

    Here am attaching our code which is modified from the example(main_mcspi_example.c) given in ti\pdk_am57xx_1_0_7 according to our needs on the custom board.

    In this we are opening all the channels of the particular Spi Instance and trying to test the loopback on of data only on the single channel,

    but when we looked at the wave-forms other channel chip selects are also asserting. As shown in the attached image.

    Please suggest the answer and whats wrong in this example.Its critical for us.

    Green is channel 1 and Blue is channel 2.

    we want only transcation on channel 1 but channel 2 is also asserting.

    /**
     *  \file   main_mcspi_example.c
     *
     *
     */
    
    /*
     * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * Redistributions of source code must retain the above copyright
     * notice, this list of conditions and the following disclaimer.
     *
     * Redistributions in binary form must reproduce the above copyright
     * notice, this list of conditions and the following disclaimer in the
     * documentation and/or other materials provided with the
     * distribution.
     *
     * Neither the name of Texas Instruments Incorporated nor the names of
     * its contributors may be used to endorse or promote products derived
     * from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    #include <stdio.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <xdc/runtime/Error.h>
    
    /* TI-RTOS Header files */
    #include <ti/drv/spi/SPI.h>
    #include <ti/drv/spi/test/src/SPI_log.h>
    #include <ti/drv/spi/test/src/SPI_board.h>
    #include <ti/drv/spi/soc/SPI_v1.h>
    #include <ti/csl/csl_mcspi.h>
    
    #include <ti/csl/soc.h>
    #include <ti/csl/hw_types.h>
    
    
    #include <ti/board/board.h>
    
    /**********************************************************************
     ************************** Macros ************************************
     **********************************************************************/
    
    
    /**********************************************************************
     ************************** Internal functions ************************
     **********************************************************************/
    /* Delay function */
    static void delay(unsigned int delayValue);
    
    
    
    /* Callback function to be called in callback mode */
    void MCSPICallbackFxn(SPI_Handle handle, SPI_Transaction * transaction);
    
    /* Function to verify data */
    bool VerifyData(uint8_t *expData, uint8_t *rxData, uint32_t length);
    
    #if defined(SOC_AM572x) || defined (SOC_AM571x)
    extern void  MCSPI_Board_crossbarInit(void);
    #endif
    
    #if defined(SOC_AM572x) || defined (SOC_AM571x)
    #if defined (__TI_ARM_V7M4__)
    #define DELAY_VALUE       (100U)
    #else
    #define DELAY_VALUE       (1000U)
    #endif
    #else
    #define DELAY_VALUE       (1000U)
    #endif
    
    /**********************************************************************
     ************************** Global Variables **************************
     **********************************************************************/
    
    /* Reference Serializer data */
    extern char serializerData[1];
    
    /* Buffer containing the known data that needs to be written to flash */
    uint8_t txBuf[1U];
    
    /* Buffer containing the received data */
    uint8_t rxBuf[1U] = {0xFFU};
    
    /* Flag to check transfer completion in callback mode */
    uint32_t txCompleteCallbackFlag = 1U;
    
    /* Transfer length */
    uint32_t transferLength;
    
    
    
    /*
     *  ======== SPI init config ========
     */
    static void SPI_initConfig(uint32_t instance, bool multiChn)
    {
    
        SPI_v1_HWAttrs spi_cfg;
    
    	bool        pollMode = true;
    #ifdef SPI_DMA_ENABLE
        bool        dmaMode = true;
    #endif
    
        /* Get the default SPI init configurations */
        SPI_socGetInitCfg(instance, &spi_cfg);
    
        /*
         * Set blocking mode (dma mode or non-dma interrupt mode)
         * or callback mode
         */
        if (pollMode == true)
        {
            /* polling mode */
            spi_cfg.enableIntr = false;
        }
        else
        {
            /* interrupt enabled */
            spi_cfg.enableIntr = true;
    #ifdef SPI_DMA_ENABLE
            if (dmaMode == true)
            {
                /* Set the DMA related init config */
                spi_cfg.edmaHandle = MCSPIApp_edmaInit();
                spi_cfg.dmaMode    = TRUE;
            }
            else
    #endif
            {
                spi_cfg.edmaHandle = NULL;
                spi_cfg.dmaMode    = FALSE;
            }
        }
        testChNum = spi_cfg.chNum;
        spi_cfg.chMode = MCSPI_MULTI_CH;
    
        /* Set the SPI init configurations */
        SPI_socSetInitCfg(instance, &spi_cfg);
    }
    
    
    /*
     *  ======== spi_test_transfer ========
     */
    bool spi_test_transfer(void *spi, bool cbMode, uint32_t timeout, bool dmaMode, bool multChn)
    {
        bool retVal;
        SemaphoreP_Handle sem;
    
        /* Load data */
    
        /* Initiate transfer */
        txBuf[0] = 0xAAU;
        memset(rxBuf, 0, MCSPI_XFER_LEN);
    
        transaction.status= SPI_TRANSFER_STARTED;
        transaction.count = MCSPI_XFER_LEN;
        transaction.txBuf = &txBuf[0];
        transaction.rxBuf = &rxBuf[0];
    
    #ifdef SPI_DMA_ENABLE
        if (dmaMode)
        {
            CacheP_wb((void *)txBuf, (int32_t)MCSPI_XFER_LEN);
            CacheP_wb((void *)rxBuf, (int32_t)MCSPI_XFER_LEN);
        }
    #endif
    
    
            retVal = MCSPI_transfer((MCSPI_Handle)spi, &transaction);
      
    
    #ifdef SPI_DMA_ENABLE
        if (dmaMode == true)
        {
            CacheP_Inv((void *)rxBuf, (int32_t)MCSPI_XFER_LEN);
        }
    #endif
    
        if(false == retVal)
        {
            printf("\n Error occurred in spi transfer \n");
            goto Err;
        }
        else
        {
            /**
             *  wait for the semaphore is posed in the callback mode to indicate the
             *  transfer completion.
             */
            if(cbMode == true)
            {
                if (multChn == true)
                {
                    sem = cbSem[testChNum];
                }
                else
                {
                    sem = cbSem[0];
                }
                if (SPI_osalPendLock(sem, timeout) != SemaphoreP_OK)
                {
                    goto Err;
                }
            }
    
            retVal = VerifyData((uint8_t *)&serializerData[0], &rxBuf[0], MCSPI_XFER_LEN);
    
        }
        printf("\n SPI_Transfer returned transaction status = %d\n",transaction.status);
    
    Err:
        return (retVal);
    }
    
    
    /*
     *  ======== test function ========
     */
    bool spi_test_multiple_channel(void *arg)
    {
        MCSPI_Params      mcSpiParams;
        MCSPI_Handle      spi[MCSPI_MAX_NUM_CHN];
        MCSPI_CallbackFxn cbFxn[MCSPI_MAX_NUM_CHN] = {MCSPI_callback0, MCSPI_callback1, MCSPI_callback2, MCSPI_callback3};
        uint32_t          instance, chn;
        bool              retVal;
        SPI_Tests        *test = (SPI_Tests *)arg;
        bool              cbMode = false;
        bool              dmaMode = false;
        uint32_t          timeout = SemaphoreP_WAIT_FOREVER;
    
        if (cbMode == true)
        {
            /* Create call back semaphore */
            SPI_osalSemParamsInit(&cbSemParams);
            cbSemParams.mode = SemaphoreP_Mode_BINARY;
        }
    
        instance = BOARD_MCSPI_SERIALIZER_INSTANCE;
        SPI_initConfig(instance, true);
    
        /* Default SPI configuration parameters */
        MCSPI_Params_init(&mcSpiParams);
        mcSpiParams.frameFormat  = SPI_POL1_PHA0;
        mcSpiParams.transferTimeout = timeout;
        if (cbMode)
        {
            mcSpiParams.transferMode = SPI_MODE_CALLBACK;
        }
    
        /* Open the default channel first */
        chn = testChNum;
        if (cbMode == true)
        {
            cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
            mcSpiParams.transferCallbackFxn = cbFxn[chn];
        }
        spi[chn] = MCSPI_open(instance, chn, &mcSpiParams);
        if (spi[chn] == NULL)
        {
            printf("Error initializing SPI");
            goto Err;
        }
        else
        {
            printf("SPI instance %d channel %d initialized\n",
                    instance, chn);
        }
    
        for (chn = 0; chn < MCSPI_MAX_NUM_CHN; chn++)
        {
            if (chn == testChNum) continue;
            if (cbMode == true)
            {
                cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
                mcSpiParams.transferCallbackFxn = cbFxn[chn];;
            }
    
            spi[chn] = MCSPI_open(instance, chn, &mcSpiParams);
    
            if (spi[chn] == NULL)
            {
                printf("Error initializing SPI");
                goto Err;
            }
            else
            {
                printf("SPI instance %d channel %d initialized\n",
                        instance, chn);
            }
        }
    
        retVal = spi_test_transfer((void *)spi[testChNum], cbMode, timeout, dmaMode, true);
    
    Err:
        for (chn = 0; chn < MCSPI_MAX_NUM_CHN; chn++)
        {
            if (spi[chn])
            {
                MCSPI_close(spi[chn]);
            }
    
            if (cbSem[chn])
            {
                SPI_osalDeleteBlockingLock(cbSem[chn]);
                cbSem[chn] = NULL;
            }
        }
    
        return (retVal);
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        /* Call board init functions */
        Board_initCfg boardCfg;
      boardCfg = BOARD_INIT_PINMUX_CONFIG |
            BOARD_INIT_MODULE_CLOCK |
            BOARD_INIT_UART_STDIO;
        Board_init(boardCfg);
    
    
        Task_Handle task;
        Error_Block eb;
    
        Error_init(&eb);
    
        task = Task_create(spi_test_multiple_channel, NULL, &eb);
            if (task == NULL) {
                System_printf("Task_create() failed!\n");
                BIOS_exit(0);
            }
    
    #if defined(SOC_AM572x) || defined (SOC_AM571x)
        MCSPI_Board_crossbarInit();
    #endif
    
        /* Start BIOS */
        BIOS_start();
        return (0);
    }
    
    
    
    
    
    /*
     *  ======== Delay function ========
     */
    void delay(unsigned int delayValue)
    {
        volatile uint32_t delay1 = delayValue*10000;
        while (delay1--) ;
    }
    
    /*
     *  ======== Callback function ========
     */
    void MCSPICallbackFxn(SPI_Handle handle, SPI_Transaction * transaction)
    {
        txCompleteCallbackFlag = 0;
    }
    
    /*
     *  ======== CompareData ========
     */
    bool VerifyData(uint8_t *expData, uint8_t *rxData, uint32_t length)
    {
        uint32_t idx = 0;
        uint32_t match = 1;
        bool retVal = false;
    
        for(idx = 0; ((idx < length) && (match != 0)); idx++)
        {
            if(*expData != *rxData) match = 0;
            expData++;
            rxData++;
        }
    
        if(match == 1) retVal = true;
    
        return retVal;
    }
    

    thanks and regards,

    Ranganath

  • Hi, 

    In addition to the above post  we have tried with interrupt mode also, the execution falls in infinite loop and am not getting any data.

    please check the configurations for the interrupt mode also. if anything fond wrong please suggest me.

    thanks and regards,

    Ranganath.