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: McSPI interrupt callback issue

Part Number: AM5728
Other Parts Discussed in Thread: SN65HVS882

I am taking McSPI_DMA_serializer as an reference. Following it to the point, with multi channel in blocking mode with Interrupt mode goes to idle loop.

Tried same with callback mode, same result. For MCSPI, I am tracing back the word_count and txtrig & rxtrig val, those looks fine to me. Can you tell what else can be the problem here?

Thanks and Regards,

Ranganath

  • Hi Ranganath,

    Could you please provide below details:

    - do you use AM57x PSDK RTOS? If yes, which version? Latest version is 6.01 and is available at below location:

    http://software-dl.ti.com/processor-sdk-rtos/esd/AM57X/latest/index_FDS.html


    - do you use AM572x TI board (evmAM572x, idkAM572x) or AM572x custom board?

    - do you use the default McSPI_DMA_serializer code or you are making some custom changes?


    Regards,
    Pavel

  • Hi Pavel,

    thanks for the reply.

    we are using processor_sdk_rtos_am57xx_4_02_00_09.

    bios version: 6_52_00_12

    pdk ver: pdk_am57xx_1_0_7

    yes,we are using Am572x custom board.

    here am attaching my code with changes to McSPI_DMA_serializer.

    /**
     *  \file   main_mcspi_example.c
     *
     *  \brief  Example application main file.
     *
     *  \details This application will read the input data generated from the
     *           industrial input module. The data will be read through MCSPI
     *           interface. This application will read one byte of data from the
     *           industrial input module. To generate the data from the industrial
     *           input module, first load signal has to be asserted using the
     *           gpio pins. On the IDK EVM, in the header J37, short the pins
     *           1 and 2. This should generate an input "0x01" and the same should
     *           be read through the MCSPI interface.
     *           The received data will vary based on the shorting of pins:
     *           Default input(no pins are shorted)   :  received data - 0x00
     *           Pins 1 and 2 shorted                 :  received data - 0x01
     *           Pins 3 and 4 shorted                 :  received data - 0x02
     *           Pins 5 and 6 shorted                 :  received data - 0x04
     *           Pins 7 and 8 shorted                 :  received data - 0x08
     *           Pins 9 and 10  shorted               :  received data - 0x10
     *           Pins 11 and 12 shorted               :  received data - 0x20
     *           Pins 13 and 14 shorted               :  received data - 0x40
     *           Pins 15 and 16 shorted               :  received data - 0x80
     *
     */
    
    /*
     * 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.
     *
     */
    //#define SPI_DMA_ENABLE
    /* 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/soc/SPI_soc.h>
    #include <ti/drv/spi/src/SPI_osal.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>
    
    #ifdef SPI_DMA_ENABLE
    #include <ti/osal/CacheP.h>
    
    /* EDMA3 Header files */
    #include <ti/sdo/edma3/drv/edma3_drv.h>
    #include <ti/sdo/edma3/rm/edma3_rm.h>
    #include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
    #endif
    
    /**********************************************************************
     ************************** Macros ************************************
     **********************************************************************/
    #define BOARD_MCSPI_SERIALIZER_INSTANCE 0
    
    /* Maximum # of channels per SPI instance */
    #define MCSPI_MAX_NUM_CHN (4U)
    
    /* Transfer length in bytes */
    #define MCSPI_XFER_LEN    (16U)
    
    /* DSP core number*/
    #define DSP_INSTANCE 1
    
    /**********************************************************************
     ************************** 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 **************************
     **********************************************************************/
    
    uint32_t testChNum;
    
    /* Reference Serializer data */
    char EXp_Data[1];
    
    /* Buffer containing the known data that needs to be written to flash */
    uint8_t txBuf[4U];
    
    /* Buffer containing the received data */
    uint8_t rxBuf[4U];
    
    uint32_t terminateXfer = 0;
    
    /* Flag to check transfer completion in callback mode */
    uint32_t txCompleteCallbackFlag = 1U;
    
    /* Transfer length */
    uint32_t transferLength;
    
    /* Transaction data */
    SPI_Transaction transaction;
    
    #ifdef SPI_DMA_ENABLE
    static EDMA3_RM_Handle MCSPIApp_edmaInit(void);
    #endif
    
    /* Callback mode variables */
    SemaphoreP_Params cbSemParams;
    SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = { NULL, NULL, NULL, NULL };
    
    void MCSPI_callback0(MCSPI_Handle handle, SPI_Transaction *transaction)
    {
    printf("callback function");
        SPI_osalPostLock(cbSem[0]);
    }
    
    void MCSPI_callback1(MCSPI_Handle handle, SPI_Transaction *transaction)
    {
        SPI_osalPostLock(cbSem[1]);
    }
    
    void MCSPI_callback2(MCSPI_Handle handle, SPI_Transaction *transaction)
    {
        SPI_osalPostLock(cbSem[2]);
    }
    
    void MCSPI_callback3(MCSPI_Handle handle, SPI_Transaction *transaction)
    {
        SPI_osalPostLock(cbSem[3]);
    }
    
    void padConfig_prcmEnable()
    {
    
    #if defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x)
    
        HW_WR_REG32(
                CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_SPI1_SCLK,
                0x000C0000);
        HW_WR_REG32(
                CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_SPI1_D1,
                0x000C0000);
        HW_WR_REG32(
                CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_SPI1_D0,
                0x000C0000);
    
        HW_WR_REG32(
                CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_SPI1_CS0,
                0x00060000);
        HW_WR_REG32(
                CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_SPI1_CS1,
                0x00060000);
        HW_WR_REG32(
                CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_SPI1_CS2,
                0x00060000);
    
    //    CSL_xbarIrqConfigure(CSL_XBAR_IRQ_CPU_ID_DSP1, CSL_XBAR_INST_DSP1_IRQ_49, CSL_XBAR_MCSPI3_IRQ);
        //CSL_xbarIrqConfigure(CSL_XBAR_IRQ_CPU_ID_DSP1, CSL_XBAR_INST_DSP1_IRQ_90, CSL_XBAR_MCSPI1_IRQ);
    
    
    #endif
    }
    /*
     *  ======== SPI init config ========
     */
    static void SPI_initConfig(uint32_t instance, bool multiChn)
    {
        padConfig_prcmEnable();
    
        SPI_v1_HWAttrs spi_cfg;
    
        bool pollMode = false;
    #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;
            }
        }
    
        spi_cfg.chNum = 0;
        testChNum = spi_cfg.chNum;
        spi_cfg.chMode = MCSPI_MULTI_CH;//MCSPI_SINGLE_CH
    //    spi_cfg.chnCfg[spi_cfg.chNum].trMode = MCSPI_TX_RX_MODE;
        printf("trMode = %d\n", spi_cfg.chnCfg[spi_cfg.chNum].trMode);
        spi_cfg.chnCfg[spi_cfg.chNum].dataLineCommMode =
                MCSPI_DATA_LINE_COMM_MODE_4;
    
        spi_cfg.txTrigLvl = 128;
        spi_cfg.rxTrigLvl = 128;
    
    
        /* 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;
        int i;
    //    /* Buffer containing the known data that needs to be written to flash */
    //    uint8_t txBuf[4];
    //
    //    /* Buffer containing the received data */
    //    uint8_t rxBuf[4];
    
    
        /* Load data */
        uint32_t ret_read;
        bool testPassed = true;
        /* Initiate transfer */
    //    txBuf[0] = 0x11;
        for (i = 0; i < 4; i++)
        {
            txBuf[i] = i + 5; //5,6,7,8
        }
    
    //    transaction.status= SPI_TRANSFER_STARTED;
        transaction.count = MCSPI_XFER_LEN;
        transaction.txBuf = (uint8_t *) &txBuf;
        transaction.rxBuf = (uint8_t *) &rxBuf;
        transaction.arg = (void *) &terminateXfer;
    
    
    #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");
            testPassed = false;
            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 = MCSPI_callback0;//cbSem[testChNum];
                }
                else
                {
                    sem = cbSem[0];
                }
                if (SPI_osalPendLock(sem, timeout) != SemaphoreP_OK)
                {
                    goto Err;
                }
            }
    
    
    //        retVal = VerifyData((uint8_t *)&txBuf[0], &rxBuf[0], MCSPI_XFER_LEN);
    
            for (i = 0; i < 4; i++)
            {
                if (txBuf[i] != rxBuf[i])
    
                {
                    testPassed = false;
                    //                printf("\n ******failed *****\n");
                    printf("Tx : %d Data : % \n", txBuf[i], rxBuf[i]);
                    break;
                }
                else
                {
                    testPassed = true;
                    printf("Tx : %x Data : %x \n", txBuf[i], rxBuf[i]);
                }
    
            }
            return retVal;
        }
        printf("\n SPI_Transfer returned transaction status = %d\n",
               transaction.status);
    //    memset(txBuf, 0, MCSPI_XFER_LEN);
    //    memset(rxBuf, 0, MCSPI_XFER_LEN);
        Err: return (retVal);
    
    }
    
    /*
     *  ======== test function ========
     */
    void 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;
        bool cbMode = true;
        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_POL0_PHA0;
    
        mcSpiParams.transferTimeout = timeout;
        printf("transferTimeout = %d\n",mcSpiParams.transferTimeout);
        if (cbMode)
        {
            mcSpiParams.transferMode = SPI_MODE_CALLBACK;
        }
    
        MCSPI_init();
        while (1)
        {
            /* Open the default channel first */
            chn = testChNum;
            if (cbMode == true)
            {
                cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
                mcSpiParams.transferCallbackFxn = MCSPI_callback0;//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;
                }
            }
            Task_sleep(1000);
    
    //    return (retVal);
        }
    
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    
    {
        Task_Handle task;
        Error_Block eb;
    
        Error_init(&eb);
    
        /* Call board init functions */
        Board_initCfg boardCfg;
        boardCfg = BOARD_INIT_PINMUX_CONFIG |
        BOARD_INIT_MODULE_CLOCK |
        BOARD_INIT_UART_STDIO;
        Board_init(boardCfg);
    
        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)
    {
    #if 0
        uint32_t idx = 0;
        uint32_t match = 1;
        bool retVal = false;
    
        printf("expData = %d, rxData = %d",*expData,*rxData);
        for(idx = 0; ((idx < length) && (match != 0)); idx++)
        {
            if(*expData != *rxData) match = 0;
            expData++;
            rxData++;
        }
    
        if(match == 1) retVal = true;
    #endif
    
    }
    
    #ifdef SPI_DMA_ENABLE
    EDMA3_RM_Handle gEdmaHandle = NULL;
    
    /**
     * \brief      Function to initialize the edma driver and get the handle to the
     *             edma driver;
     */
    static EDMA3_RM_Handle MCSPIApp_edmaInit(void)
    {
        EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
        uint32_t edma3Id;
    
        if (gEdmaHandle != NULL)
        {
            return (gEdmaHandle);
        }
    
        edma3Id = 0;
        gEdmaHandle = (EDMA3_RM_Handle)edma3init(edma3Id, &edmaResult);
        if (edmaResult != EDMA3_DRV_SOK)
        {
            /* Report EDMA Error */
            System_printf("\nEDMA driver initialization FAIL\n");
        }
        else
        {
            System_printf("\nEDMA driver initialization PASS.\n");
        }
        return(gEdmaHandle);
    }
    #endif
    
    

     when i put a breakpoint inside the isr function MCSPI_v1_hwiFxn in Spi_v1.c Its not hitting the breakpoint so transfer is not happening.

    can you please test this and suggest me what am missing in my code.

    thanks and regards

    Ranganath

  • Ranganath,

    Ranganath V N said:
    here am attaching my code with changes to McSPI_DMA_serializer.mcspi_loopback.c

    To which McSPI example your custom code is based?

    For AM572x device we have:

    {PDK}/packages/ti/drv/spi/example/mcspi_slavemode

    {PDK}/packages/ti/drv/spi/example/mcspi_serializer

    {PDK}/packages/ti/drv/spi/example/mcspiLoopbackApp

    {PDK}/packages/ti/drv/spi/test/src/main_mcspi_test.c

    Check below user guide and make sure you are following the instructions for the successful example execution:

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_device_drv.html#mcspi-qspi-ospi

    Regards,
    Pavel

  • Hi Pavel,

    I am using the {PDK}/packages/ti/drv/spi/example/mcspi_serializer 

    as reference and modified for our custom board which i already attached above.

    Thanks

    Ranganath

     

  • Ranganath,

    Do you run this test (default mcspi_serializer)  successful on AM57x IDK board? Or you are directly porting on AM572x custom board?

    On AM57x IDK board, to run this test, we need to do the following: Short pins 1 and 2 on header J37 (Industrial I/O). We have AM57x McSPI3 connected to SN65HVS882, which connect to J37 I/O chip. Do you copy the same design for your custom board? If not, what are the design changes related to McSPI3?

    Regards,
    Pavel

  • Hi Pavel,

    As for my knowledge mCspi works in this way,

    Open the Mcspi all the channels(chip selects) in the initialization time. then use whichever channel we want for transactions in parallel with the other channels of the same bus

    and close the particular channel of the bus after transaction.

    correct me if am wrong, clarify me the how MCspi works.

    Regards

    Ranganath

  • Ranganath,

    McSPI module can operate in several modes, depending on how you configure it. I would suggest you to check below pointers for more info:

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_device_drv.html#mcspi-qspi-ospi

    {PDK}/packages/ti/drv/spi/docs/ReleaseNotes_SPI_LLD.pdf

    AM572x DM, section 7.15 Multichannel Serial Peripheral Interface (McSPI)

    AM572x TRM, section 24.4 Multichannel Serial Peripheral Interface

    Regards,
    Pavel