我有一个关于SPI和DMA的问题,也许有人可以帮助我BI
ti有2个PIC32 MX795F512L用SPI互相连接。在SPI i上发送64个字节的包,并且我用DMA来发送和接收。问题是在15。20分钟之后,主机停止在SPI上发送数据(它不CR)。ASH,因为其他进程仍在运行),我将在这里发布我使用DMA和SPI(主)的代码:我使用FIFO将帧放入,将帧加载到FIFO:在主循环中(我选择在主干中做这个,而不是从ISR中执行,以避免它同时运行两次):我使用UART发送帧指针,我看到的是在15到20分钟后,SPILoADFrice仍然在计数,但是SPIProcFrame不是(当我注释SeaStFF行和UART5WrdLead时,我看到它停止),我用逻辑分析仪检查,我再也看不到SPI数据。我做了什么错事?是DmaChnEnable(DMAYChhanel1);DmaChnStartTxfer(DMAZhanNeL2,DMAWAWITITY NOT,0);不是重新启动DMA控制器的方法吗?
以上来自于百度翻译
以下为原文
I have an issue with SPI and DMA, maybe someone can help me a bit
I have 2 PIC 32MX795F512L connected to each other with SPI.
Over the SPI I send packages of 64 bytes each and I use DMA to send and receive.
The problem is that after 15..20 minutes the Master stops sending data over SPI (it does not crash, because other processes are still running)
I'll post here the code I use
Init of DMA and SPI (Master):
SpiChnOpen(SPI_CHANNEL1, SPI_CON_MODE8|SPI_CON_ON|SPI_OPEN_MSTEN, 64);
DmaChnClrEvFlags(DMA_CHANNEL1, DMA_EV_ALL_EVNTS);
DmaChnClrEvFlags(DMA_CHANNEL2, DMA_EV_ALL_EVNTS);
DmaChnOpen(DMA_CHANNEL1, DMA_CHN_PRI2, DMA_OPEN_DEFAULT);
DmaChnOpen(DMA_CHANNEL2, DMA_CHN_PRI3, DMA_OPEN_DEFAULT);
DmaChnSetEventControl(DMA_CHANNEL1, DMA_EV_START_IRQ_EN|DMA_EV_START_IRQ(_SPI1_RX_IRQ));
DmaChnSetEventControl(DMA_CHANNEL2, DMA_EV_START_IRQ_EN|DMA_EV_START_IRQ(_SPI1_TX_IRQ));
DmaChnSetTxfer(DMA_CHANNEL1, (void*)&SPI1BUF, (UINT8*)&SPiRxData, 1, SpiPacketSize, 1);
DmaChnSetTxfer(DMA_CHANNEL2, (UINT8*)&SPiTxData, (void*)&SPI1BUF, SpiPacketSize, 1, 1);
DmaChnSetEvEnableFlags(DMA_CHANNEL2, DMA_EV_ERR); // enable the transfer done interrupt, when all buffer transferred
INTSetVectorPriority(INT_VECTOR_DMA(DMA_CHANNEL2), INT_PRIORITY_LEVEL_5); // set INT controller priority
INTSetVectorSubPriority(INT_VECTOR_DMA(DMA_CHANNEL2), INT_SUB_PRIORITY_LEVEL_3); // set INT controller sub-priority
INTEnable(INT_SOURCE_DMA(DMA_CHANNEL2), INT_ENABLED); // enable the chn interrupt in the INT controller
DmaChnSetEvEnableFlags(DMA_CHANNEL1, DMA_EV_BLOCK_DONE); // enable the transfer done interrupt, when all buffer transferred
INTSetVectorPriority(INT_VECTOR_DMA(DMA_CHANNEL1), INT_PRIORITY_LEVEL_5); // set INT controller priority
INTSetVectorSubPriority(INT_VECTOR_DMA(DMA_CHANNEL1), INT_SUB_PRIORITY_LEVEL_3); // set INT controller sub-priority
INTEnable(INT_SOURCE_DMA(DMA_CHANNEL1), INT_ENABLED); // enable the chn interrupt in the INT controller
I use a FIFO for putting the frames into, loading a frame to FIFO:
void SPILoadFrame(UINT8 *FrPointer)
{
// TEST Clear the overflow (in case we have one)
SPI1STATCLR=0x40; // clear the Overflow
SPIAppSendPointer++;
if (SPIAppSendPointer >= FrambufferSize) {
SPIAppSendPointer = 0;
}
memcpy((UINT8*)&FramebufferTx[SPIAppSendPointer],FrPointer,SpiPacketSize);
// For test send pointer over uart
sprintf(txt,"%u ",SPIAppSendPointer);
Uart5WriteString(txt);
}
In the main loop (I choosed to do this in main and not from the ISR to avoid it wil be run twice at the same time):
void SPIProcFrame(void)
{
UINT8 pntr=SPIDMASendPointer;
SPIProcFrameRunning = 1;
SPI1STATCLR=0x40; // Test: Clear overflow if we have one
if (!DCH1CONbits.CHBUSY) {
// See if we have a frame ready to load
if (SPIDMASendPointer != SPIAppSendPointer) {
// we need to load the next frame
pntr++;
if (pntr >= FrambufferSize) {
pntr = 0;
}
// next is not really necessary because we checked DMA1 channel = receive
if (!SPI1STATbits.SPITBE) {
while (!SPI1STATbits.SPITBE); // wait until we send everything out
//delay_us(1); // wait a bit longer to process
}
memcpy((UINT8*)&SPiTxData,(UINT8*)&FramebufferTx[pntr],SpiPacketSize);
SPIDMASendPointer=pntr;
//sprintf(txt,"%u ",SPIDMASendPointer);
//Uart5WriteString(txt);
// now restart the DMA sender
DmaChnEnable(DMA_CHANNEL1);
DmaChnStartTxfer(DMA_CHANNEL2, DMA_WAIT_NOT, 0);
}
}
}
I used the uart to send the frame pointer, what I saw is after 15 to 20 minutes SPILoadFrame is still counting but SPIProcFrame is not (when I comment out the sprintf line and Uart5writeline I see it stops)
I checked with logic analyser and I do not see any SPI data anymore.
What do I do wrong? is
DmaChnEnable(DMA_CHANNEL1);
DmaChnStartTxfer(DMA_CHANNEL2, DMA_WAIT_NOT, 0);
not the way to restart the DMA controller?