程序设计使用SPI_EDMA,通过GPIO中断来判断何时来读,但现在情况是进入了GPIO中断以后,SPI读FLASH一直死在 while((0 == flagTx) || (0 == flagRx));,感觉是EDMA的callback中断函数没有响应,请问这是什么情况?有什么解决办法吗?
Nancy Wang:
请问芯片型号是什么?
user6340167:
回复 Nancy Wang:
您好,我使用的是OMAPL138。
Nancy Wang:
回复 user6340167:
SPI_EDMA是参考的哪里的程序?是否有做哪些修改?
user6340167:
回复 Nancy Wang:
您好,这是我参考官方例程修改后的程序,运行每次都会卡在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"// 通用输入输出口宏及设备抽象层函数声明
voidEdma3ComplHandlerIsr(void);
void(*cb_Fxn[EDMA3_NUM_TCC]) (unsigned int tcc,unsigned int status);
voidcallback(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] = 9GPIO0[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);
//初始化EDMAEDMA3Initialize();
//初始化SPISPIInitialize();
//请求EDMA通道RequestEDMA3Channels();
//使能SPISPIEnable(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++;}}}
Nancy Wang:
回复 user6340167:
断点到Edma3ComplHandlerIsr能进去吗?IPR[tcc]有没有置位?像是没有触发EDMA传输完成中断。
user6340167:
回复 Nancy Wang:
您好,我尝试了一下,断点在那无法进入Edma3ComplHandlerIsr。
但当我不在GPIO中断里执行ReadFromFlash(ReadFlash),将其在主函数里执行这句话就可以进入Edma3ComplHandlerIsr。
请问这种情况您有什么建议去解决吗?
Nancy Wang:
回复 user6340167:
示波器看一下spi有没有数据发送出去。