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.

同时使用DSP的SPI_EDMA中断和GPIO引脚中断,只响应GPIO中断 ,EDMA中断不响应。

程序设计使用SPI_EDMA,通过GPIO中断来判断何时来读,但现在情况是进入了GPIO中断以后,SPI读FLASH一直死在 while((0 == flagTx) || (0 == flagRx));,感觉是EDMA的callback中断函数没有响应,请问这是什么情况?有什么解决办法吗?

  • 请问芯片型号是什么?
  • 您好,我使用的是OMAPL138。
  • SPI_EDMA是参考的哪里的程序?是否有做哪些修改?
  • 您好,这是我参考官方例程修改后的程序,运行每次都会卡在while((0 == flagTx) || (0 == flagRx));这边,您看下是什么情况。 谢谢


    /****************************************************************************/
    /* */
    /* SPI FLASH 读写测试 */
    /* */
    /* 2014年05月19日 */
    /* */
    /****************************************************************************/
    // 注意:DSP ports, Shared RAM, UART0, EDMA, SPI0, MMC/SDs,
    // VPIF, LCDC, SATA, uPP, DDR2/mDDR (bus ports), USB2.0, HPI, PRU
    // 这些外设使用的时钟来源为 PLL0_SYSCLK2 默认频率为 CPU 频率的二分之一
    // 但是,ECAPs, UART1/2, Timer64P2/3, eHRPWMs,McBSPs, McASP0, SPI1
    // 这些外设的时钟来源可以在 PLL0_SYSCLK2 和 PLL1_SYSCLK2 中选择
    // 通过修改 System Configuration (SYSCFG) Module
    // 寄存器 Chip Configuration 3 Register (CFGCHIP3) 第四位 ASYNC3_CLKSRC
    // 配置时钟来源
    // (默认值) 0 来源于 PLL0_SYSCLK2
    // 1 来源于 PLL1_SYSCLK2
    // 如果不是为了降低功耗,不建议修改这个值,它会影响所有相关外设的时钟频率

    #include "EDMA_SPI.h"
    #include "TL6748.h" // 创龙 DSP6748 开发板相关声明

    #include "soc_C6748.h"
    #include "hw_psc_C6748.h"

    #include "uart.h"
    #include "spi.h"
    #include "psc.h"
    #include "hw_psc_C6748.h"
    #include "edma_event.h"
    #include "edma.h"

    #include "hw_types.h"

    #include "uartStdio.h"

    #include "interrupt.h"

    #include <string.h>

    #include "gpio.h" // 通用输入输出口宏及设备抽象层函数声明

    void Edma3ComplHandlerIsr(void);
    void (*cb_Fxn[EDMA3_NUM_TCC]) (unsigned int tcc,unsigned int status);
    void callback(unsigned int tccNum,unsigned int status);

    /******************************************************************/
    /* MACRO DEFINITIONS */
    /******************************************************************/
    #define SIMO_SOMI_CLK_CS (0x00000E01)
    #define CHAR_LENGTH (0x08)

    //读写FLASH的地址
    #define SPI_FLASH_ADDR_MSB1 (0x0A)
    #define SPI_FLASH_ADDR_MSB0 (0x00)
    #define SPI_FLASH_ADDR_LSB (0x00)

    //擦除
    #define SPI_FLASH_SECTOR_ERASE (0xD8)

    //页编程
    #define SPI_FLASH_PAGE_WRITE (0x02)

    //读状态寄存器
    #define SPI_FLASH_STATUS_RX (0x05)

    // 写使能
    #define SPI_FLASH_WRITE_EN (0x06)

    //FLASH数据读命令
    #define SPI_FLASH_READ (0x03)

    //检查SPI FLASH的状态
    #define WRITE_IN_PROGRESS (0x01)
    #define WRITE_ENABLE_LATCH (0x02)


    void CSHoldDeassert(void);
    void FlashSectorErase(void);
    void FlashPageProgram(volatile char *originalData);
    void ReadFromFlash(volatile char *readFlash);
    void WriteEnable(void);

    void USER0KEYIsr(void);
    /******************************************************************/
    /* GLOBAL VARIABLES */
    /******************************************************************/
    volatile unsigned int flagTx = 0;
    volatile unsigned int flagRx = 0;

    volatile char originalData[1024] = {0};
    char readFlash[1024] = {0};
    char readall[51200] = {0};

    unsigned int retVal = 0;
    unsigned int times = 0;
    void PSCInit()
    {
    // 使能GPIO模块
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
    }

    // GPIO 管脚复用配置(应该是针对特定的接口)
    void GPIOBankPinMuxSet()
    {
    // 配置相应的 GPIO 口功能为普通输入输出口
    // GPIOBank0Pin8PinMuxSetup(); //为什么没有?

    // 测试硬件中断功能
    // 底板按键
    GPIOBank0Pin6PinMuxSetup();
    }

    // GPIO 管脚初始化
    void GPIOBankPinInit()
    {
    // 配置GPIO0[8] 为输入模式(由FPGA输入?)
    GPIODirModeSet(SOC_GPIO_0_REGS, 9, GPIO_DIR_INPUT); // USER0 KEY GPIO0[8] = 9 GPIO0[6] = 7

    // 测试: 配置GPIO0[6] 为输入模式
    GPIODirModeSet(SOC_GPIO_0_REGS, 7, GPIO_DIR_INPUT); // USER0 KEY GPIO0[6]

    // GPIOIntTypeSet(SOC_GPIO_0_REGS, 7, GPIO_INT_TYPE_FALLEDGE); // 配置 USER0 KEY GPIO0[6] 为下降沿触发
    // 配置 USER0 KEY GPIO0[6] 为上升沿触发
    GPIOIntTypeSet(SOC_GPIO_0_REGS, 7, GPIO_INT_TYPE_RISEDGE); //配置为上升沿触发不会发生两次中断
    // end
    // 配置 USER0 KEY GPIO0[8]为上升沿触发
    GPIOIntTypeSet(SOC_GPIO_0_REGS, 9, GPIO_INT_TYPE_RISEDGE);
    // 使能 GPIO BANK 中断
    GPIOBankIntEnable(SOC_GPIO_0_REGS, 0); // USER0 KEY GPIO0
    // 注册中断服务函数
    IntRegister(C674X_MASK_INT6, USER0KEYIsr);
    // IntRegister(C674X_MASK_INT5, USER1KEYIsr);
    //
    // // 映射中断到 DSP 可屏蔽中断
    IntEventMap(C674X_MASK_INT6, SYS_INT_GPIO_B0INT);
    // // IntEventMap(C674X_MASK_INT5, SYS_INT_GPIO_B6INT);
    //
    // // 使能 DSP 可屏蔽中断
    IntEnable(C674X_MASK_INT6);
    }


    /****************************************************************************/
    /* */
    /* DSP 中断初始化 */
    /* */
    /****************************************************************************/
    void InterruptInit(void)
    {
    // 初始化 DSP 中断控制器
    IntDSPINTCInit();

    // 使能 DSP 全局中断
    IntGlobalEnable();
    }

    void USER0KEYIsr(void)
    {

    if(GPIOPinIntStatus(SOC_GPIO_0_REGS, 9) == GPIO_INT_PEND)
    {
    // 清除 GPIO0[6] 中断状态
    // GPIOPinIntClear(SOC_GPIO_0_REGS, 7);
    ReadFromFlash(readFlash);
    // retVal = 1;
    // Flag=0;
    }
    // 清除 GPIO0[8] 中断状态
    GPIOPinIntClear(SOC_GPIO_0_REGS, 9);
    // 清除 GPIO0[6] 中断状态
    GPIOPinIntClear(SOC_GPIO_0_REGS, 7);
    //// 使能 GPIO BANK 0 中断
    // GPIOBankIntEnable(SOC_GPIO_0_REGS, 0);
    }

    int main(void)
    {

    // unsigned int retVal = 0;
    // unsigned char choice;
    InterruptInit();

    //初始化串口
    UARTStdioInit();

    UARTPuts("Welcome to SPI EDMA application.\r\n", -1);
    UARTPuts("Here the SPI controller on the SoC communicates with", -1);
    UARTPuts(" the SPI Flash present on the SoM.\r\n\r\n", -1);

    //初始化EDMA
    EDMA3Initialize();

    //初始化SPI
    SPIInitialize();

    //请求EDMA通道
    RequestEDMA3Channels();

    //使能SPI
    SPIEnable(SOC_SPI_1_REGS);
    // 外设使能配置
    PSCInit();
    // 管脚复用配置
    GPIOBankPinMuxSet();
    // GPIO 管脚初始化
    GPIOBankPinInit();
    //读
    // ReadFromFlash(readFlash);

    while(1);
    }

    /*
    ** This function reads data bytes from SPI Flash.
    */

    void ReadFromFlash(volatile char *pReadFlash)
    {
    volatile char writeFlash[1024] = {0};
    unsigned int buffLength = 0;
    unsigned int index = 0;

    writeFlash[0] = SPI_FLASH_READ;
    writeFlash[1] = SPI_FLASH_ADDR_MSB1;
    writeFlash[2] = SPI_FLASH_ADDR_MSB0;
    writeFlash[3] = SPI_FLASH_ADDR_LSB;

    for(index = 4; index < 1024; index++)
    {
    writeFlash[index] = 0;
    }

    buffLength = index;

    /* Configure the PaRAM registers in EDMA for Transmission.*/
    SpiTxEdmaParamSet(EDMA3_CHA_SPI1_TX, EDMA3_CHA_SPI1_TX, writeFlash, buffLength);

    /* Registering Callback Function for Transmission. */
    cb_Fxn[EDMA3_CHA_SPI1_TX] = &callback;

    /* Configure the PaRAM registers in EDMA for Reception.*/
    SpiRxEdmaParamSet(EDMA3_CHA_SPI1_RX, EDMA3_CHA_SPI1_RX, pReadFlash, buffLength, TRUE);

    /* Registering Callback Function for Reception. */
    cb_Fxn[EDMA3_CHA_SPI1_RX] = &callback;

    /* Assert the CSHOLD line corresponding to the SPI Flash. */
    CSHoldAssert();

    /* Enable SPI controller to generate DMA events */
    SPIIntEnable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);

    /* Wait until both the flags are set to 1 in the callback function. */
    while((0 == flagTx) || (0 == flagRx));

    flagTx = 0;
    flagRx = 0;

    /* Deassert the CSHOLD line corresponding to the SPI Flash. */
    CSHoldDeassert();
    }

    unsigned int IsWriteEnabled(void)
    {
    volatile unsigned char temp = 0;
    unsigned int retVal = FALSE;

    /* Reading the Status Register of SPI Flash. */
    temp = FlashStatusRead();

    if (temp & WRITE_ENABLE_LATCH)
    {
    retVal = TRUE;
    }

    return retVal;
    }

    void IsWriteInProgress(void)
    {
    volatile unsigned char temp = 0;
    do
    {
    temp = FlashStatusRead();
    }while(temp & WRITE_IN_PROGRESS);
    }

    unsigned char FlashStatusRead(void)
    {
    volatile char writeFlash[2] = {0};
    volatile char readFlash[2] = {0};
    unsigned int buffLength = 0;

    writeFlash[0] = SPI_FLASH_STATUS_RX;
    writeFlash[1] = 0;

    buffLength = 2;

    /* Configure the PaRAM registers in EDMA for Transmission.*/
    SpiTxEdmaParamSet(EDMA3_CHA_SPI1_TX, EDMA3_CHA_SPI1_TX, writeFlash, buffLength);

    /* Registering Callback Function for Transmission. */
    cb_Fxn[EDMA3_CHA_SPI1_TX] = &callback;

    /* Configure the PaRAM registers in EDMA for Reception. */
    SpiRxEdmaParamSet(EDMA3_CHA_SPI1_RX, EDMA3_CHA_SPI1_RX, readFlash, buffLength, TRUE);

    /* Registering Callback Function for Reception. */
    cb_Fxn[EDMA3_CHA_SPI1_RX] = &callback;

    /* Assert the CSHOLD line corresponding to the SPI Flash. */
    CSHoldAssert();

    /* Enable SPI controller to generate DMA events */
    SPIIntEnable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);

    /* Wait until both the flags are set to 1 in the callback function. */
    while((0 == flagTx) || (0 == flagRx));

    flagTx = 0;
    flagRx = 0;

    /* Deassert the CSHOLD line corresponding to the SPI Flash. */
    CSHoldDeassert();

    return ((unsigned char)readFlash[1]);
    }

    void callback(unsigned int tccNum, unsigned int status)
    {
    if(tccNum == 19)
    {
    flagTx = 1;
    /* Disable SPI-EDMA Communication. */
    SPIIntDisable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);
    }
    else if(tccNum == 18)
    {
    flagRx = 1;
    /* Disable SPI-EDMA Communication. */
    SPIIntDisable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);
    }
    }

    void Edma3ComplHandlerIsr(void)
    {
    volatile unsigned int pendingIrqs;
    volatile unsigned int isIPR = 0;

    volatile unsigned int indexl;
    volatile unsigned int Cnt = 0;
    indexl = 1;

    IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);

    isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);
    if(isIPR)
    {
    while ((Cnt < EDMA3CC_COMPL_HANDLER_RETRY_COUNT)&& (indexl != 0))
    {
    indexl = 0;
    pendingIrqs = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);
    while (pendingIrqs)
    {
    if((pendingIrqs & 1) == TRUE)
    {
    /**
    * If the user has not given any callback function
    * while requesting the TCC, its TCC specific bit
    * in the IPR register will NOT be cleared.
    */
    /* Here write to ICR to clear the corresponding IPR bits. */
    EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, indexl);
    (*cb_Fxn[indexl])(indexl, EDMA3_XFER_COMPLETE);
    }
    ++indexl;
    pendingIrqs >>= 1;
    }
    Cnt++;
    }
    }

    }
  • 断点到Edma3ComplHandlerIsr能进去吗?IPR[tcc]有没有置位?像是没有触发EDMA传输完成中断。
  • 您好,我尝试了一下,断点在那无法进入Edma3ComplHandlerIsr。
    但当我不在GPIO中断里执行ReadFromFlash(ReadFlash),将其在主函数里执行这句话就可以进入Edma3ComplHandlerIsr。
    请问这种情况您有什么建议去解决吗?
  • 示波器看一下spi有没有数据发送出去。