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.

AM5718: DSP核使用MCSPI无法触发EDMA中断

Part Number: AM5718


TI的工程师您好,我参考了TI的SPI EDMA传输例程,在使用轮询的方式下MCSPI1能够回环传输数据,但是在使用EDMA的时候,始终无法触发中断,SPI部分代码如下:

#include <xdc/std.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Diags.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/Registry.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/hal/Hwi.h>
#include <ti/ipc/Ipc.h>
#include <ti/ipc/MessageQ.h>
#include <ti/ipc/MultiProc.h>
#include <stdio.h>
#include <ti/csl/example/utils/common/inc/app_utils.h>
#include <ti/csl/soc.h>
#include <ti/csl/hw_types.h>
#include <ti/csl/csl_edma.h>
#include <ti/csl/arch/csl_arch.h>
#include <ti/drv/spi/SPI.h>
#include <ti/csl/csl_mcspi.h>
#include <ti/drv/spi/soc/SPI_soc.h>
#include <ti/drv/spi/src/SPI_osal.h>
//#include "bsp_spi.h"
//#include "edma_test.h"
#include <ti/osal/HwiP.h>
#include <ti/csl/arch/csl_arch.h>
#include <ti/csl/csl_types.h>
#include <ti/csl/csl_edma.h>
#include <ti/csl/arch/c66x/interrupt.h>
#include <ti/csl/soc/am571x/src/cslr_soc_dsp_baseaddress.h>
#include <ti/csl/src/ip/edma/V1/edma.h>
#include <ti/csl/src/ip/edma/V1/hw_edma_tpcc.h>

/* ========================================================================== */
/*                                 Macros                                     */
/* ========================================================================== */

//#define McSPI_DATA_COUNT            50U // Data Count Transaction
#define MCSPI_INSTANCE 0//0-spi1 1-spi2 2-spi3
#define MCSPI_POLLED_MODE      0

#define HSI2C_EN_SPI2      ((uint8_t) 0x40U)
#define HSI2C_ZERO      ((uint8_t) 0x00U)

#define MCSPI_OUT_FREQ              (48000000U)
#define MCSPI_IN_CLK                (48000000U)
#define McSPI_DATA_COUNT            256U // Data Count Transaction
#define MCSPI1_BASE_ADDRESS         (CSL_MPU_MCSPI1_REGS)
#define MCSPI2_BASE_ADDRESS         (CSL_MPU_MCSPI2_REGS)

/** \brief EDMA3 channel for SPI1 Channel 0 Tx and Rx*/
#define MCSPI1_TX_EVENT                  (34U)
#define MCSPI1_RX_EVENT                  (35U)

/** \brief EDMA3 channel for SPI2 Channel 0 Tx and Rx*/
#define MCSPI2_TX_EVENT                  (42U)
#define MCSPI2_RX_EVENT                  (43U)

/** \brief MCSPI Tx/Rx buffer base address */
#define MCSPI1_TX0_REG                   (SOC_MCSPI1_BASE + (0x138U))
#define MCSPI1_RX0_REG                   (SOC_MCSPI1_BASE + (0x13CU))

#define MCSPI2_TX0_REG                   (SOC_MCSPI2_BASE + (0x138U))
#define MCSPI2_RX0_REG                   (SOC_MCSPI2_BASE + (0x13CU))

/** \brief MCSPI Channel number*/
#define MCSPI_CH_NUM                    (0U)

#define EVT_QUEQUE_NUM                  (0U)
#define DUMMY_CH_NUM                    (5U)

#define EDMA_TDA2XX_U_BASE              (CSL_DSP_DSP_EDMA_CC_REGS)

#define EDMA3CC_PaRAM_BASE            (0x4000)
#define EDMA3CC_OPT(n)                (EDMA3CC_PaRAM_BASE + 0x0 + (0x20 * n))

#define EDMA3_CC_XFER_COMPLETION_INT_A15                (12U)
#define EDMA3_CC_XFER_COMPLETION_INT_M4                 (35U)

/* DSP1 EDMA3 transfer event number */
#define DSP1_EDMA3_CC_XFER_COMPLETION_INT 19
#define DSP1_EDMA3_CC_ERROR_INT 27

/* DSP1 EDAM3 region number */
#define DSP1_EDMA3_REGION 2

/* DSP1 EDMA3 channel number */
#define DSP1_EDMA3_CHANNEL 0

/* DSP1 EDMA3 tcc number */
#define DSP1_EDMA3_TCC 0

/* DSP1 EDMA3 evtq number */
#define DSP1_EDMA3_EVTQ 0

/* OPT Field specific defines */
#define OPT_SYNCDIM_SHIFT                   (0x00000002u)
#define OPT_TCC_MASK                        (0x0003F000u)
#define OPT_TCC_SHIFT                       (0x0000000Cu)
#define OPT_ITCINTEN_SHIFT                  (0x00000015u)
#define OPT_TCINTEN_SHIFT                   (0x00000014u)
#define OPT_TCCMOD_SHIFT                    (0x0000000Bu)

#define EDMA3_ERROR_INT_A15                              (14)
#define EDMA3_ERROR_INT_A15_1                            (15)
#define EDMA3_ERROR_INT_M4                               (36)
#define EDMA3_ERROR_INT_M4_1                             (37)

#define EDMA3_CC_REGION_A15                             (0U)
#define EDMA3_CC_REGION_M4                              (1U)

#define MCSPI_MASTERSLAVE_POLLED_MODE_TEST   ('1')
#define MCSPI_MASTERSLAVE_DMA_MODE_TEST      ('2')
#define EXIT(opt)                   (('x' == opt) || ('X' == opt))



/**********************************************************************
 ************************** Global Variables **************************
 **********************************************************************/
uint32_t dataToSlave;

uint32_t          gChNum  = 0;
uint32_t          length = 0;
uint8_t           dataFromSlave;
uint8_t           rxBuffer[McSPI_DATA_COUNT + 10];
uint8_t           txBuffer[McSPI_DATA_COUNT + 10];
uint8_t           txSlvBuffer[McSPI_DATA_COUNT + 10];
uint8_t           rxSlvBuffer[McSPI_DATA_COUNT + 10];
uint8_t           gRxBuffer[McSPI_DATA_COUNT];
uint8_t           gTxBuffer[McSPI_DATA_COUNT];

static void(*cb_Fxn[EDMA3_NUM_TCC]) (uint32_t tcc,
                                     uint32_t status);

volatile uint8_t  flagTx    = 0;
volatile uint8_t  flagRx    = 0;
volatile uint8_t  flagSlvTx = 0;
volatile uint8_t  flagSlvRx = 0;

/* ========================================================================== */
/*                          Function Declarations                             */
/* ========================================================================== *//* clock callback function */
void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction);
static void McSPI1SetUp(void);
static void McSPIMSTransfer(uint16_t length);
static void McSPIVerifyData(void);
static void McSPIInitializeBuffers(void);
void McSPIMasterSlaveAppTest(void);
static void McSPIConfigureDma(uint32_t length);

static void McSpi1TxEdmaParamSet(uint32_t tccNum, uint32_t chNum,
                                 volatile uint8_t *buffer,
                                 uint16_t buffLength);
static void McSpi1RxEdmaParamSet(uint32_t tccNum, uint32_t chNum,
                                 volatile uint8_t *buffer,
                                 uint16_t buffLength,
                                 uint32_t destBidxFlag);
static void CallBack_McSPI1(uint32_t tccNum, uint32_t status);
static void TxDummyPaRAMConfEnable(void);
static void RequestEDMA3Channels(void);
static void EDMA3Initialize(void);
static void spiedma_cb_isr(UInt32 event_id);
static int EDMA3IntConfigure(void);


/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

void McSPIMasterSlaveAppTest(void)
{
    /* Do the necessary set up configurations for McSPI.*/
//    EDMA3Init(EDMA_TDA2XX_U_BASE, 0);

    /* Initialize the EDMA3 instance.*/
    EDMA3Initialize();

    /* Request EDMA3CC for Tx and Rx channels for SPI0. */
    RequestEDMA3Channels();

    McSPI1SetUp();
    McSPIInitializeBuffers();
    McSPIConfigureDma(McSPI_DATA_COUNT);
    McSPIMSTransfer(McSPI_DATA_COUNT);

    Task_sleep(1000);
    /* Verify whether the data written by Master and the one read by
     * Slave are Equal */
    McSPIVerifyData();
}

static void EDMA3Initialize(void)
{
    /* Configuring the AINTC to receive EDMA3 Interrupts */
    EDMA3IntConfigure();
}

/*
** This function configures the AINTC to receive EDMA3 interrupts.
*/
static int EDMA3IntConfigure(void)
{
#ifdef _TMS320C6X
    /* Initialize DSP interrupt controller and enable interrupts */
    Hwi_Params hwiParams;
        Error_Block eb;

        EDMAsetRegion(DSP1_EDMA3_REGION);

        EDMA3Init(CSL_DSP_DSP_EDMA_CC_REGS, 0);

        Hwi_Params_init(&hwiParams);
        Error_init(&eb);

        /* set the event id of the peripheral assigned to this interrupt */
        hwiParams.eventId = DSP1_EDMA3_CC_XFER_COMPLETION_INT;

        /* set the argument passed to ISR function */
        hwiParams.arg = DSP1_EDMA3_CC_XFER_COMPLETION_INT;

        hwiParams.maskSetting = Hwi_MaskingOption_SELF;

        Hwi_create(12, spiedma_cb_isr, &hwiParams, &eb);
        if (Error_check(&eb)) {
            Log_print0(Diags_INFO, "Hwi create failed \n");
            return -1;
        }

        /* set the event id of the peripheral assigned to this interrupt */
        hwiParams.eventId = DSP1_EDMA3_CC_ERROR_INT;

        /* set the argument passed to ISR function */
        hwiParams.arg = DSP1_EDMA3_CC_ERROR_INT;

        hwiParams.maskSetting = Hwi_MaskingOption_SELF;

        Hwi_create(13, spiedma_cb_isr, &hwiParams, &eb);
        if (Error_check(&eb)) {
            Log_print0(Diags_INFO, "Hwi create failed \n");
            return -1;
        }

        Hwi_enable();
#endif
}

static void spiedma_cb_isr(UInt32 event_id)
{
    System_printf("spiedma_cb_isr...\r\n");
    switch(event_id) {
    case DSP1_EDMA3_CC_XFER_COMPLETION_INT:
        /* Transfer completed successfully */
//        (*cb_Fxn[indexl])(indexl, EDMA3_XFER_COMPLETE);
        break;
    case DSP1_EDMA3_CC_ERROR_INT:
        /* Transfer resulted in error. */

        break;
    default:
        break;
    };

    EDMA3ClrIntr(CSL_DSP_DSP_EDMA_CC_REGS, DSP1_EDMA3_TCC);
}

/*
** This function allocates EDMA3 channels to McSPI0 for trasmisssion and
** reception purposes.
*/
static void RequestEDMA3Channels(void)
{
    /* Request DMA Channel and TCC for SPI Transmit*/
    EDMA3RequestChannel(EDMA_TDA2XX_U_BASE, EDMA3_CHANNEL_TYPE_DMA, \
                        MCSPI1_TX_EVENT, MCSPI1_TX_EVENT, EVT_QUEQUE_NUM);
    EDMA3EnableEvtIntr(EDMA_TDA2XX_U_BASE, MCSPI1_TX_EVENT);

    /* Request DMA Channel and TCC for SPI Receive*/
    EDMA3RequestChannel(EDMA_TDA2XX_U_BASE, EDMA3_CHANNEL_TYPE_DMA, \
                        MCSPI1_RX_EVENT, MCSPI1_RX_EVENT, EVT_QUEQUE_NUM);
    EDMA3EnableEvtIntr(EDMA_TDA2XX_U_BASE, MCSPI1_RX_EVENT);
}

/*
** This function will call the necessary McSPI APIs which will configure the
** McSPI controller.
*/
static void McSPI1SetUp(void)
{
    uint32_t status = 1U; // FALSE

    /* Reset the McSPI instance.*/
    McSPIReset(MCSPI1_BASE_ADDRESS);

    /* CLOCKACTIVITY bit - OCP and Functional clocks are maintained           */
    /* SIDLEMODE     bit - Ignore the idle request and configure in normal mode
     */
    /* AUTOIDLE      bit - Disable (OCP clock is running free, no gating)     */
    MCSPISysConfigSetup(MCSPI1_BASE_ADDRESS, MCSPI_CLOCKS_OCP_ON_FUNC_ON,
                        MCSPI_SIDLEMODE_NO, MCSPI_WAKEUP_DISABLE,
                        MCSPI_AUTOIDLE_OFF);

    /* Enable chip select pin.*/
    McSPICSEnable(MCSPI1_BASE_ADDRESS);

    /* Enable master mode of operation.*/
    McSPIMasterModeEnable(MCSPI1_BASE_ADDRESS);

    /* Perform the necessary configuration for master mode. */
    status = McSPIMasterModeConfig(MCSPI1_BASE_ADDRESS, MCSPI_SINGLE_CH,
                                   MCSPI_TX_RX_MODE,
                                   MCSPI_DATA_LINE_COMM_MODE_6,
                                   gChNum);

    if (0 == status)
    {
        //UARTConfigPuts(uartBaseAddr,"\nMcSPI1 - Communication not supported by SPIDAT[1:0]",-1);
    }

    /* Configure the McSPI bus clock depending on clock mode. */
    McSPIClkConfig(MCSPI1_BASE_ADDRESS, MCSPI_IN_CLK, MCSPI_OUT_FREQ, gChNum,
                   MCSPI_CLK_MODE_0);

    /* Configure the word length.*/
    McSPIWordLengthSet(MCSPI1_BASE_ADDRESS, MCSPI_WORD_LENGTH(8), gChNum);

    /* Set polarity of SPIEN to low.*/
    McSPICSPolarityConfig(MCSPI1_BASE_ADDRESS,
                          (MCSPI_CH0CONF_EPOL_ACTIVELOW <<
                           MCSPI_CH0CONF_EPOL_SHIFT), gChNum);

    /* Enable the transmitter FIFO of McSPI peripheral.*/
    McSPITxFIFOConfig(MCSPI1_BASE_ADDRESS, MCSPI_TX_FIFO_ENABLE, gChNum);

    /* Enable the receiver FIFO of McSPI peripheral.*/
    McSPIRxFIFOConfig(MCSPI1_BASE_ADDRESS, MCSPI_RX_FIFO_ENABLE, gChNum);
}


static void McSPIInitializeBuffers(void)
{
    uint32_t index = 0;

    static int cnt = 0;
    char msg[McSPI_DATA_COUNT] = {"Initialize the txBuffer McSPI1 with a known pattern of data:"};
    for (index = 0; index < McSPI_DATA_COUNT; index++)
    {
        /* Initialize the txBuffer McSPI1 with a known pattern of data */

//        txBuffer[index] = (uint8_t) index;
        /* Initialize the rxBuffer McSPI1 with 0 */
        rxBuffer[index] = (uint8_t) 0;
    }
    sprintf(txBuffer,"%s%d",msg,cnt++);
    for (index = 0; index < McSPI_DATA_COUNT; index++)
    {
        /* Initialize the txBuffer McSPI1 with a known pattern of data */
        txSlvBuffer[index] = (uint8_t) index;
        /* Initialize the rxBuffer McSPI1 with 0 */
        rxSlvBuffer[index] = 0;
    }
}


static void McSPIConfigureDma(uint32_t length)
{
    /* DMA PaRAM Configuration for McSPI1 */
    /* Configure the read data parameters of McSPI for Edma transmit.*/
    McSpi1TxEdmaParamSet(MCSPI1_TX_EVENT, MCSPI1_TX_EVENT, txBuffer,
                         length);

    /* Configure the read data parameters of McSPI for Edma receive.*/
    McSpi1RxEdmaParamSet(MCSPI1_RX_EVENT, MCSPI1_RX_EVENT, rxBuffer,
                         length, TRUE);

    /* Register the call-back function for Tx/Rx edma events of McSPI.*/
    cb_Fxn[MCSPI1_TX_EVENT] = &CallBack_McSPI1;
    cb_Fxn[MCSPI1_RX_EVENT] = &CallBack_McSPI1;

    /* Set the word count field with the data length to be transferred.*/
    McSPIWordCountSet(MCSPI1_BASE_ADDRESS, length);
    /* Enable the Tx/Rx DMA events for McSPI. */
    McSPIDMAEnable(MCSPI1_BASE_ADDRESS,
                   (MCSPI_DMA_RX_EVENT | MCSPI_DMA_TX_EVENT),
                   MCSPI_CH_NUM);
}

/*
** Call back function. Here we disable the Tx/Rx DMA events of McSPI
** peripheral.
*/
static void CallBack_McSPI1(uint32_t tccNum, uint32_t status)
{
    System_printf("CallBack_McSPI1...\r\n");
    if (tccNum == MCSPI1_TX_EVENT)
    {
        flagTx = 1;

        System_printf("MCSPI1_TX_EVENT\r\n");
        /* Disable McSPI Transmit event */
        McSPIDMADisable(MCSPI1_BASE_ADDRESS, MCSPI_CH0CONF_DMAW_MASK,
                        MCSPI_CH_NUM);
    }

    if (tccNum == MCSPI1_RX_EVENT)
    {
        flagRx = 1;

        System_printf("MCSPI1_RX_EVENT\r\n");
        /* Disable McSPI Receive event */
        McSPIDMADisable(MCSPI1_BASE_ADDRESS, MCSPI_CH0CONF_DMAR_MASK,
                        MCSPI_CH_NUM);
    }
}

/*
** This function is used to set the PaRAM entries of EDMA3 for the Receive
** event of channel 0 of McSPI1 instance. The corresponding EDMA3 channel
** is also enabled for reception.
*/
static void McSpi1RxEdmaParamSet(uint32_t tccNum, uint32_t chNum,
                                 volatile uint8_t *buffer,
                                 uint16_t buffLength,
                                 uint32_t destBidxFlag)
{
    EDMA3CCPaRAMEntry paramSet = {0};

    /* Fill the PaRAM Set with Receive specific information.*/

    /* srcAddr holds address of SPI Rx FIFO.*/
    paramSet.srcAddr = (uint32_t) (MCSPI1_RX0_REG);

    /* destAddr is address of memory location named buffer.*/
    paramSet.destAddr = (uint32_t) buffer;

    /* aCnt holds the number of bytes in an array.*/
    paramSet.aCnt = 1;

    /* bCnt holds the number of such arrays to be transferred.*/
    paramSet.bCnt = buffLength;

    /* cCnt holds the number of frames of aCnt*bBcnt bytes to be transferred.*/
    paramSet.cCnt = 1;

    /* The srcBidx should not be incremented since it is a h/w register.*/
    paramSet.srcBIdx = 0;

    if (TRUE == destBidxFlag)
    {
        /* The destBidx should be incremented for every byte.*/
        paramSet.destBIdx = 1;
    }
    else
    {
        /* The destBidx should not be incremented.*/
        paramSet.destBIdx = 0;
    }

    /* A sync Transfer Mode. */
    /* srCIdx and destCIdx set to zero since ASYNC Mode is used.*/
    paramSet.srcCIdx  = 0;
    paramSet.destCIdx = 0;

    /* Linking transfers in EDMA3 are not used.*/
    paramSet.linkAddr = 0xFFFF;

    paramSet.bCntReload = 0;

    paramSet.opt = 0x00000000;

    /* Set TCC field in OPT with the tccNum.*/
    paramSet.opt |= ((tccNum << EDMA_TPCC_OPT_TCC_SHIFT) &
                     EDMA_TPCC_OPT_TCC_MASK);

    /* EDMA3 Interrupt is enabled and Intermediate Interrupt Disabled.*/
    paramSet.opt |= (1 << EDMA_TPCC_OPT_TCINTEN_SHIFT);

    /* Now write the PaRam Set to EDMA3.*/
    EDMA3SetPaRAM(EDMA_TDA2XX_U_BASE, chNum, &paramSet);

    /* EDMA3 Transfer is Enabled.*/
    EDMA3EnableTransfer(EDMA_TDA2XX_U_BASE, chNum, EDMA3_TRIG_MODE_EVENT);
}

/*
** This function is used to set the PaRAM entries of EDMA3 for the Transmit
** Channel 0 of SPI1 instance. The corresponding EDMA3 channel is also enabled
** for transmission.
*/
static void McSpi1TxEdmaParamSet(uint32_t tccNum, uint32_t chNum,
                                 volatile uint8_t *buffer,
                                 uint16_t buffLength)
{
    EDMA3CCPaRAMEntry paramSet = {0};

    /* Fill the PaRAM Set with transfer specific information. */

    /* srcAddr holds address of memory location buffer. */
    paramSet.srcAddr = (uint32_t) buffer;

    /* destAddr holds address of McSPI_TX register. */
    paramSet.destAddr = (uint32_t) (MCSPI1_TX0_REG);

    /* aCnt holds the number of bytes in an array. */
    paramSet.aCnt = 1;

    /* bCnt holds the number of such arrays to be transferred. */
    paramSet.bCnt = buffLength;

    /* cCnt holds the number of frames of aCnt*bBcnt bytes to be transferred. */
    paramSet.cCnt = 1;

    /*
    ** The srcBidx should be incremented by aCnt number of bytes since the
    ** source used here is memory.
    */
    paramSet.srcBIdx  = 1;
    paramSet.destBIdx = 0;

    /* Async Transfer Mode is set in OPT.*/
    /* srCIdx and destCIdx set to zero since ASYNC Mode is used. */
    paramSet.srcCIdx  = 0;
    paramSet.destCIdx = 0;

    /* Linking transfers in EDMA3 are not used. */
    paramSet.linkAddr   = (EDMA3CC_OPT(DUMMY_CH_NUM));
    paramSet.bCntReload = 0;

    paramSet.opt = 0x00000000;

    /* SAM and DAM fields both are set to 0 */

    /* Set TCC field in OPT with the tccNum. */
    paramSet.opt |= ((tccNum << EDMA_TPCC_OPT_TCC_SHIFT) &
                     EDMA_TPCC_OPT_TCC_MASK);

    /* EDMA3 Interrupt is enabled and Intermediate Interrupt Disabled.*/
    paramSet.opt |= (1 << EDMA_TPCC_OPT_TCINTEN_SHIFT);

    /* Now write the PaRam Set to EDMA3.*/
    EDMA3SetPaRAM(EDMA_TDA2XX_U_BASE, chNum, &paramSet);

    /* Dummy param set is enabled */
    TxDummyPaRAMConfEnable();

    /* EDMA3 Transfer is Enabled. */
    EDMA3EnableTransfer(EDMA_TDA2XX_U_BASE, chNum, EDMA3_TRIG_MODE_EVENT);
}

/*
** This configures the PaRAM set for the Dummy Transfer.
*/
static void TxDummyPaRAMConfEnable(void)
{
    EDMA3CCPaRAMEntry dummyPaRAMSet;

    EDMA3GetPaRAM(EDMA_TDA2XX_U_BASE, DUMMY_CH_NUM, &dummyPaRAMSet);

    dummyPaRAMSet.aCnt       = 1;
    dummyPaRAMSet.bCnt       = 0;
    dummyPaRAMSet.cCnt       = 0;
    dummyPaRAMSet.srcAddr    = 0;
    dummyPaRAMSet.destAddr   = 0;
    dummyPaRAMSet.srcBIdx    = 0;
    dummyPaRAMSet.destBIdx   = 0;
    dummyPaRAMSet.srcCIdx    = 0;
    dummyPaRAMSet.destCIdx   = 0;
    dummyPaRAMSet.linkAddr   = 0xFFFFU;
    dummyPaRAMSet.bCntReload = 0;
    dummyPaRAMSet.opt        = 0;

    EDMA3SetPaRAM(EDMA_TDA2XX_U_BASE, DUMMY_CH_NUM, &dummyPaRAMSet);
}

static void McSPIMSTransfer(uint16_t length)
{
    /* Enable the McSPI channel for communication.*/
    McSPIChannelEnable(MCSPI1_BASE_ADDRESS, gChNum);

    /* SPIEN line is forced to low state.*/
    McSPICSAssert(MCSPI1_BASE_ADDRESS, gChNum);

    Task_sleep(1000);
    /* Force SPIEN line to the inactive state.*/
    McSPICSDeAssert(MCSPI1_BASE_ADDRESS, gChNum);

    /* Disable the McSPI channel.*/
    McSPIChannelDisable(MCSPI1_BASE_ADDRESS, gChNum);
}

/*
** This function will verify the data written to and read from flash and print
** the appropriate message.
*/
static void McSPIVerifyData(void)
{
    uint32_t index = 0;
    uint32_t error = 0;

//    for (index = 0; index < McSPI_DATA_COUNT; index++)
//    {
//        if ((rxSlvBuffer[index] != txBuffer[index]) ||
//            (txSlvBuffer[index] != rxBuffer[index]))
//        {
//            //UARTConfigPuts(uartBaseAddr,"\nData Mismatch found at index : \r",-1);
//            error = 1;
//            break;
//        }
//    }
    System_printf("txBuffer:%s\r\n",txBuffer);
    System_printf("rxBuffer:%s\r\n",rxBuffer);
    memset(txBuffer,0,McSPI_DATA_COUNT);
//    memset(rxBuffer,0,McSPI_DATA_COUNT);
    if (error == 0)
    {
        //UARTConfigPuts(uartBaseAddr,"\nThe data written by Master and the one read by Slave are Equal",-1);
    }
}

我在单独使用EDMA在内存中传输数据时能够触发中断,但是为什么变成MCSPI事件触发就无法成功了呢?

期待您的宝贵意见!谢谢!

  • 请详细说明一下是在哪个例程上做了哪些修改。

  • 例程:processor_sdk_rtos_am57xx_06_03_02_08\pdk_am57xx_1_0_18\packages\ti\csl\example\mcspi\mcspiMasterSlave\mcspiMasterSlave_spi1_spi2.c

    修改部分:1、static int EDMA3IntConfigure(void);  2、SOC_EDMA_TPCC_BASE_VIRT换成CSL_DSP_DSP_EDMA_CC_REGS

    修改原因:1、找不到IntRegister等函数。2、程序运行失败

    也参考了MCSPI_BasicExample_Dma_idkAM571x_c66xTestProject的方式,但是程序会卡在edma3init,因此没有采用这种方式。

    参考帖子:https://e2e.ti.com/support/processors-group/processors/f/processors-forum/922081/tda2hg-mcspi-edma-rx-event-can-t-receive/3432812?tisearch=e2e-sitesearch&keymatch=MCSPI%2525252520EDMA#3432812

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/651588/am5728-rtos-issues-with-spi?tisearch=e2e-sitesearch&keymatch=MCSPI%2525252520EDMA#

    尝试了很多种方式,也看了很多论坛的帖子,没有找到可以使用的方式,如果这种方式不能够使用的话,您能提供一个例程吗?

  • 好的,稍后我会升级到英文论坛。

  • 你好,发布到英文论坛了吗

  • 您好,Nancy,我使用LLD的方式(MCSPI_BasicExample_Dma_idkAM571x_c66xTestProject)实现了EDMA传输,解决方式是将edmainit的edma3Id改为1,但是又回到了我之前一个帖子的问题(https://e2echina.ti.com/support/processors/f/processors-forum/215638/am5718-dsp-spi),最大只能使用3Mhz了(使用超过3Mhz的CLK时在示波器能看到输出波形,数据量小的时候可以进入回调函数,但是无法传输数据,而数据量大的时候会卡在spi_transfer,也不会进入中断回调函数),部分测试代码如下:

    /****************************************************************************************************************/
    /****************************************test_spi_LLD************************************************************/
    /****************************************************************************************************************/
    
    #include <string.h>
    
    /* 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 "System_printf.h"
    //#include "SPI_test.h"
    
    /* GPIO Header files */
    #include <ti/drv/gpio/GPIO.h>
    #include <ti/drv/gpio/soc/GPIO_v1.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
    /* Maximum # of channels per SPI instance */
    #define MCSPI_MAX_NUM_CHN (1U)
    #define McSPI_DATA_COUNT            3U
    /* Transfer length in bytes */
    
    #define MCSPI_OUT_FREQ              (48000000U)
    #define MCSPI_IN_CLK                (48000000U)
    
    /* Buffer containing the known data that needs to be written to flash */
    
    //#pragma DATA_ALIGN (txBuf, 32)
    uint8_t txBuf[McSPI_DATA_COUNT] = {1,2,3};//"123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.";
    
    /* Buffer containing the received data */
    //#pragma DATA_ALIGN (rxBuf, 32)
    uint8_t rxBuf[McSPI_DATA_COUNT] = {0};
    
    
    /* Transaction data */
    SPI_Transaction   transaction;
    
    /* Flag to check transfer completion in callback mode */
    uint32_t txCompleteCallbackFlag = 1U;
    
    /* Callback mode variables */
    SemaphoreP_Params cbSemParams;
    SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = {NULL};
    
    uint32_t testChNum = 0;
    
    /* Callback mode functions */
    void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction)
    {
        SPI_osalPostLock(cbSem[0]);
        System_printf("SPI_callback\r\n");
    }
    #ifdef MCSPI_MULT_CHANNEL
    void MCSPI_callback0(MCSPI_Handle handle, SPI_Transaction *transaction)
    {
        SPI_osalPostLock(cbSem[0]);
        System_printf("MCSPI_callback0\r\n");
    }
    
    #endif
    
    /*
     *  ======== 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;
        System_printf("txBuffer:%d\r\n",txBuf[1]);
        System_printf("rxBuffer:%d\r\n",rxBuf[1]);
        return retVal;
    }
    
    /*
     *  ======== 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_DATA_COUNT);
    
        transaction.status= SPI_TRANSFER_STARTED;
        transaction.count = McSPI_DATA_COUNT;
        transaction.txBuf = &txBuf[0];
        transaction.rxBuf = &rxBuf[0];
    
    #ifdef SPI_DMA_ENABLE
        if (dmaMode)
        {
            CacheP_wb((void *)txBuf, (int32_t)McSPI_DATA_COUNT);
            CacheP_wb((void *)rxBuf, (int32_t)McSPI_DATA_COUNT);
        }
    #endif
    
    #ifdef MCSPI_MULT_CHANNEL
        if (multChn == true)
        {
            retVal = MCSPI_transfer((MCSPI_Handle)spi, &transaction);
        }
        else
    #endif
        {
            retVal = SPI_transfer((SPI_Handle)spi, &transaction);
        }
    
    #ifdef SPI_DMA_ENABLE
        if (dmaMode == true)
        {
            CacheP_Inv((void *)rxBuf, (int32_t)McSPI_DATA_COUNT);
        }
    #endif
    
        if(false == retVal)
        {
            System_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;
                }
            }
    
    //        Task_sleep(1000);
            retVal = VerifyData((uint8_t *)&txBuf[0], &rxBuf[0], McSPI_DATA_COUNT);
    
        }
        System_printf("\n SPI_Transfer returned transaction status = %d,retVal = %d\n",transaction.status,retVal);
    
    Err:
        return (retVal);
    }
    
    /*
     *  ======== SPI init config ========
     */
    static void SPI_initConfig(uint32_t instance,  bool multiChn)
    {
        SPI_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;
            }
        }
    //    System_printf("spi_cfg.inputClkFreq = %d\n",spi_cfg.inputClkFreq);
        spi_cfg.inputClkFreq =  MCSPI_IN_CLK;
    //    spi_cfg.chnCfg[0].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_0;
    
    #ifdef MCSPI_MULT_CHANNEL
    //    testChNum = spi_cfg.chNum;
    
        /*
         * Set multi or single channel mode
         */
    //    if (multiChn == true)
    //    {
    //        spi_cfg.chMode = MCSPI_MULTI_CH;
    //    }
    //    else
    //    {
    //        spi_cfg.chMode = MCSPI_SINGLE_CH;
    //    }
    #endif
    
        /* Set the SPI init configurations */
        SPI_socSetInitCfg(instance, &spi_cfg);
    }
    
    //#define BOARD_MCSPI_SERIALIZER_INSTANCE 0U
    /*
     *  ======== spi_test_single_channel ========
     */
    bool spi_test_single_channel(void *arg)
    {
        SPI_Params      spiParams;           /* SPI params structure */
        SPI_Handle      spi;                 /* SPI handle */
        uint32_t        instance;
        bool            retVal = FALSE;      /* return value */
        bool            cbMode = false;
        bool            dmaMode = true;
        uint32_t        timeout = SemaphoreP_WAIT_FOREVER;
    
        if (cbMode == true)
        {
            /* Create call back semaphore */
            SPI_osalSemParamsInit(&cbSemParams);
            cbSemParams.mode = SemaphoreP_Mode_BINARY;
            cbSem[0] = SPI_osalCreateBlockingLock(0, &cbSemParams);
        }
    
        instance = 0;
        SPI_initConfig(instance, false);
    
        /* Default SPI configuration parameters */
        SPI_Params_init(&spiParams);
        spiParams.frameFormat  = SPI_POL1_PHA0;
        spiParams.transferTimeout = timeout;
        spiParams.bitRate = MCSPI_OUT_FREQ;
        if (cbMode)
        {
            spiParams.transferMode = SPI_MODE_CALLBACK;
            spiParams.transferCallbackFxn = SPI_callback;
        }
    
        /* Open QSPI driver */
        spi = SPI_open(instance, &spiParams);
    
        if (spi == NULL)
        {
            System_printf("Error initializing SPI\n");
            goto Err;
        }
        else
        {
            System_printf("SPI initialized\n");
        }
    
        retVal = spi_test_transfer((void *)spi, cbMode, timeout, dmaMode, false);
    
    Err:
        if (spi)
        {
            SPI_close(spi);
        }
    
        if (cbSem[0])
        {
            SPI_osalDeleteBlockingLock(cbSem[0]);
            cbSem[0] = NULL;
        }
    
        return (retVal);
    }
    
    #ifdef MCSPI_MULT_CHANNEL
    /*
     *  ======== spi_test_multiple_channel ========
     */
    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};
        uint32_t          instance, chn;
        bool              retVal = FALSE;
        bool              cbMode = true;
        bool              dmaMode = true;
        uint32_t          timeout = SemaphoreP_WAIT_FOREVER;
    
        if (cbMode == true)
        {
            /* Create call back semaphore */
            SPI_osalSemParamsInit(&cbSemParams);
            cbSemParams.mode = SemaphoreP_Mode_BINARY;
        }
    
        instance = 0;
        SPI_initConfig(instance,  true);
    
        /* Default SPI configuration parameters */
        MCSPI_Params_init(&mcSpiParams);
        mcSpiParams.frameFormat  = SPI_POL0_PHA0;
        mcSpiParams.transferTimeout = timeout;
        mcSpiParams.bitRate = MCSPI_OUT_FREQ;
        mcSpiParams.dataSize = 8;
        mcSpiParams.mode = SPI_MASTER;
    
        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)
        {
            System_printf("Error initializing SPI");
            goto Err;
        }
        else
        {
            System_printf("SPI instance %d channel %d initialized\n",
                    instance, chn);
        }
    
        retVal = spi_test_transfer((void *)spi[testChNum], cbMode, timeout, dmaMode, true);
    
    Err:
    
    
        if (spi[chn])
        {
              MCSPI_close(spi[chn]);
        }
    
        if (cbSem[chn])
        {
              SPI_osalDeleteBlockingLock(cbSem[chn]);
              cbSem[chn] = NULL;
        }
        return (retVal);
    }
    #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;
     */
    EDMA3_RM_Handle MCSPIApp_edmaInit(void)
    {
        EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
        uint32_t         edma3Id;
    
        if (gEdmaHandle != NULL)
        {
            return (gEdmaHandle);
        }
        System_printf("\nMCSPIApp_edmaInit\n");
        edma3Id = 1;
        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
    
    void spi_lld_test(void)
    {
    //    spi_test_single_channel(NULL);
    //    McSPI1SetUp();
        spi_test_multiple_channel(NULL);
    }
    

    所以目前有两个问题:

    1、CSL的方式如何才能触发EDMA中断?

    2、LLD的方式为什么不能实现48Mhz传输?

  • 你好,Nancy,很抱歉,就在刚刚回复你过后,我实现了LLD方式48Mhz传输,在分配内存前增加了 #pragma DATA_ALIGN (txBuf, 32),但是每次只能传输32字节,这是在手册上规定的吗,可我在手册上没有看到,还需要注意哪些地方才能传输更大的数据呢?

  • 应该没有字节数的限定,这部分内容我没有测试过,我认为可能是与EDMA部分的配置有关系。

    https://www.ti.com/lit/ug/sprugs5b/sprugs5b.pdf

    https://e2echina.ti.com/support/processors/f/processors-forum/194970/edma3-sysbios

  • 好的,我再研究下,谢谢!

  • 谢谢你,Nancy,我在使用了04版本的RTOS SDK过后,这部分问题解决了,没有字节数的限制。

  • 好的,感谢分享!

  • 非常抱歉,最近测试出,之前触发的只是SPI传输中断,并不是DMA中断,如果在cfg文件中调用Spi.Setting.useDma="true";就无法再触发回调函数了,也就是说,DMA传输并没有成功。