TI中文支持网
TI专业的中文技术问题搜集分享网站

TMS320C6748: 请问下,使用EDMA3 spi出现传输数据错误,发现传输数据都变0了,不知道哪里有存在问题?

Part Number:TMS320C6748Other Parts Discussed in Thread:SYSBIOS

请问下,使用EDMA3 spi出现传输数据错误,发现传输数据都变0了,不知道哪里有存在问题?

EDMA3初始化:
void Init(void)
{
// 使能 EDMA3CC_0
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);

// 使能 EDMA3TC_0
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
EDMA3Init(SOC_EDMA30CC_0_REGS, EVT_QUEUE_NUM);

/* Request DMA Channel and TCC for SPI0 Transmit*/
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA, \
EDMA3_CHA_SPI0_TX, EDMA3_CHA_SPI0_TX, EVT_QUEUE_NUM);

/* Request DMA Channel and TCC for SPI0 Receive*/
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA, \
EDMA3_CHA_SPI0_RX, EDMA3_CHA_SPI0_RX, EVT_QUEUE_NUM);

/* Request DMA Channel and TCC for SPI1 Transmit*/
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA, \
EDMA3_CHA_SPI1_TX, EDMA3_CHA_SPI1_TX, EVT_QUEUE_NUM);

/* Request DMA Channel and TCC for SPI1 Receive*/
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA, \
EDMA3_CHA_SPI1_RX, EDMA3_CHA_SPI1_RX, EVT_QUEUE_NUM);
}

void Spi1TxParamSet(unsigned int tccNum, unsigned int chNum,
volatile char *buffer, unsigned int buffLength)
{
EDMA3CCPaRAMEntry paramSet;
unsigned char *p = (unsigned char *)&paramSet;
unsigned int i = 0;

/* Clean-up the contents of structure variable. */
for (i = 0; i < sizeof(paramSet); i++)
{
p[i] = 0;
}
/* Fill the PaRAM Set with transfer specific information. */

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

/* destAddr holds address of SPIDAT1 register. */
paramSet.destAddr = (unsigned int) (SOC_SPI_1_REGS + SPI_SPIDAT1);

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

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

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

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

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

/* Linking transfers in EDMA3 are not used. */
paramSet.linkAddr = (unsigned short)0xFFFF;
paramSet.bCntReload = (unsigned short)0;

paramSet.opt = 0x00000000;

/* SAM field in OPT is set to zero since source is memory and memory
pointer needs to be incremented. DAM field in OPT is set to zero
since destination is not a FIFO. */
//paramSet.opt |= (EDMA3CC_OPT_DAM ); // 目的地址模式设置为固定地址模式

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

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

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

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

void Spi1RxParamSet(unsigned int tccNum, unsigned int chNum,
volatile char *buffer, unsigned int length,
unsigned int destBidxFlag)
{
EDMA3CCPaRAMEntry paramSet;
unsigned char *p = (unsigned char *)&paramSet;
unsigned int i = 0;

/* Clean-up the contents of structure variable. */
for (i = 0; i < sizeof(paramSet); i++)
{
p[i] = 0;
}

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

/* srcAddr holds address of SPI Rx FIFO. */
paramSet.srcAddr = (unsigned int) (SOC_SPI_1_REGS + SPI_SPIBUF);

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

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

/* bCnt holds the number of such arrays to be transferred. */
paramSet.bCnt = (unsigned short) length;

/* cCnt holds the number of frames of aCnt*bBcnt bytes to be transferred. */
paramSet.cCnt = (unsigned short) 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 = (unsigned short)0xFFFF;
paramSet.bCntReload = 0;

paramSet.opt = 0x00000000;

//paramSet.opt |= (EDMA3CC_OPT_SAM ); // 源地址模式设置为固定地址模式

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

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

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

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

中断设置如下:
void SpiHwi(void)
{
EventCombiner_dispatchPlug(SYS_INT_EDMA3_0_CC0_INT1, &ComplHandlerIsr, 1, TRUE);
EventCombiner_dispatchPlug(SYS_INT_EDMA3_0_CC0_ERRINT, &CCErrHandlerIsr, 1, TRUE);
}配置回调函数如下:
void SpiCallBack(unsigned int tccNum, unsigned int status)
{
if(tccNum == EDMA3_CHA_SPI1_TX)
{
flagTx = 1;
if( Semaphore_getCount( g_spiEdmaSem1 ) == 0)
{
Semaphore_post(g_spiEdmaSem1);
}
/* Disable SPI-EDMA Communication. */
SPIIntDisable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);
}
else if(tccNum == EDMA3_CHA_SPI1_RX)
{
flagRx = 1;
if( Semaphore_getCount( g_spiEdmaSem2 ) == 0)
{
Semaphore_post(g_spiEdmaSem2);
}
/* Disable SPI-EDMA Communication. */
SPIIntDisable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);
}
}

中断服务程序如下:
void ComplHandlerIsr(UArg arg)
{
volatile unsigned int pendingIrqs;
volatile unsigned int isIPR = 0;

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

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++;
}
}
}

void CCErrHandlerIsr(UArg arg)
{

volatile unsigned int pendingIrqs;
unsigned int Cnt = 0u;
unsigned int index;
unsigned int evtqueNum = 0; // 事件队列数目

pendingIrqs = 0u;
index = 1u;

if((EDMA3GetErrIntrStatus(SOC_EDMA30CC_0_REGS) != 0 )
|| (EDMA3QdmaGetErrIntrStatus(SOC_EDMA30CC_0_REGS) != 0)
|| (EDMA3GetCCErrStatus(SOC_EDMA30CC_0_REGS) != 0))
{
//GPIOPinWrite(SOC_GPIO_0_REGS , 3 , GPIO_PIN_HIGH);
// 循环 EDMA3CC_ERR_HANDLER_RETRY_COUNT 次
// 直到没有等待中的中断时终止
while ((Cnt < EDMA3CC_ERR_HANDLER_RETRY_COUNT) && (index != 0u))
{
// 获取ERR中断错误状态
index = 0u;
pendingIrqs = EDMA3GetErrIntrStatus(SOC_EDMA30CC_0_REGS);

while (pendingIrqs)
{
// 执行所有等待中的中断
if(TRUE == (pendingIrqs & 1u))
{
// 清除 SER
EDMA3ClrMissEvt(SOC_EDMA30CC_0_REGS, index);
}
++index;
pendingIrqs >>= 1u;
}
// 获取qdma err中断错误状态
index = 0u;
pendingIrqs = EDMA3QdmaGetErrIntrStatus(SOC_EDMA30CC_0_REGS);

while (pendingIrqs)
{
// 执行所有等待中的中断
if(TRUE == (pendingIrqs & 1u))
{
// 清除 SER
EDMA3QdmaClrMissEvt(SOC_EDMA30CC_0_REGS, index);
}
++index;
pendingIrqs >>= 1u;
}

// 获取通道 err错误状态
index = 0u;
pendingIrqs = EDMA3GetCCErrStatus(SOC_EDMA30CC_0_REGS);

if (pendingIrqs != 0u)
{
// 执行所有等待中的 CC 错误中断
// 事件队列 队列入口错误
for (evtqueNum = 0u; evtqueNum < SOC_EDMA3_NUM_EVQUE; evtqueNum++)
{
if((pendingIrqs & (1u << evtqueNum)) != 0u)
{
// 清除错误中断
EDMA3ClrCCErr(SOC_EDMA30CC_0_REGS, (1u << evtqueNum));
}
}

// 传输完成错误
if ((pendingIrqs & (1 << EDMA3CC_CCERR_TCCERR_SHIFT)) != 0u)
{
EDMA3ClrCCErr(SOC_EDMA30CC_0_REGS, (0x01u << EDMA3CC_CCERR_TCCERR_SHIFT));
}

++index;
}

Cnt++;
}
}
}

spi 初始化如下:
void Spi1Init(void)
{
unsigned char cs = 0x00;
unsigned char dcs = 0x01;
unsigned int val = SIMO_SOMI_CLK;

// CS HIGH
SPI1_CS1_HIGH();
SPI1_CS2_HIGH();

DevSpi_PowerClockSet();

DevSpi_PinMuxSet();

#if USE_SPI1

SPIReset(SOC_SPI_1_REGS);

SPIOutOfReset(SOC_SPI_1_REGS);

SPIModeConfigure(SOC_SPI_1_REGS, SPI_MASTER_MODE);

SPIClkConfigure(SOC_SPI_1_REGS, SPI_MODULE_CLK, SPI1_COM_CLK, SPI_DATA_FORMAT0);

SPIPinControl(SOC_SPI_1_REGS, 0, 0, &val);

SPIDefaultCSSet(SOC_SPI_1_REGS, dcs);

// 配置 SPI 数据格式
DevSpi1_DataFormatConfig(SPI_DATA_FORMAT0);

// 配置 SPI 数据格式及片选信号
SPIDat1Config(SOC_SPI_1_REGS, SPI_DATA_FORMAT0, cs);

// 使能 SPI
SPIEnable(SOC_SPI_1_REGS);
#endif
}

spi test函数如下:
void DevSpi_test(unsigned int tx_length)
{
// unsigned char temp[10];
unsigned int cnt =0;
volatile char dummy;
volatile char TxData[100];

for (cnt = 0; cnt < tx_length*2 ; ++cnt)
{
TxData[cnt] = cnt;
}

Spi1TxParamSet(EDMA3_CHA_SPI1_TX, EDMA3_CHA_SPI1_TX, TxData, tx_length);

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

/* Configure the PaRAM registers in EDMA for Reception.*/
Spi1RxParamSet(EDMA3_CHA_SPI1_RX, EDMA3_CHA_SPI1_RX,&dummy, tx_length, FALSE);

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

/* Assert the CSHOLD line corresponding to the SPI Flash. */
SPI1_CS1_LOW();
// SPIDat1Config(SOC_SPI_1_REGS, SPI_DATA_FORMAT_USER, 0x01);

/* 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)); //替换为信号量等待
Semaphore_pend(g_spiEdmaSem1, 10);
Semaphore_pend(g_spiEdmaSem2, 10);

SPIIntDisable(SOC_SPI_1_REGS, SPI_DMA_REQUEST_ENA_INT);

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

}

Shine:

请先尝试一下EDMA是否能搬移片内RAM,如果可以,再把源地址改为SPI接口。另外, 没有用EDMA的话,SPI口能正确读写么?

,

Titan S:

好的,我这边尝试下。没有用EDMA,SPI口是能正确读写。由于实时要求,spi替换为EDMA的方式。

,

Shine:

好的,有问题再回复这个帖子。

,

Titan S:

尝试过了,将源地址修改为了全局数组变量(destData[100]),源地址idx修改为递增,没能搬移成功。

//paramSet.destAddr = (unsigned int) (SOC_SPI_1_REGS + SPI_SPIDAT1);

paramSet.destAddr = destData; paramSet.destBIdx = 1;

,

Shine:

starterware里有SPI+EDMA例程C:\ti\C6748_StarterWare_1_20_04_01\examples\lcdkC6748\spi_edma,可以参考一下。https://software-dl.ti.com/dsps/dsps_public_sw/c6000/starterware/01_20_04_01/index_FDS.html

,

Titan S:

谢谢回复。

已参考过了对应starterware里有SPI+EDMA例程,步骤是对的。因为使用的是sysbios,移植过去后,就出问题。

starterware使用的while()等待,我替换成了信号量。触发都是正常的,连CLK都有输出了,数据没能搬移输出。

赞(0)
未经允许不得转载:TI中文支持网 » TMS320C6748: 请问下,使用EDMA3 spi出现传输数据错误,发现传输数据都变0了,不知道哪里有存在问题?
分享到: 更多 (0)

© 2024 TI中文支持网   网站地图 鲁ICP备2022002796号-1