- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
i have some trouble with SGDMA and TSE. I guess the problem is in the callback function(_ISR_HanderRX) of the RX-SGDMA. Ok let's explain this stuff a little bit: After first init of the RX-SGDMA the _ISR_HandlerRX function should be called when the descriptor chain is completed. In the ISR_HandlerRX function the Interrupt should be cleared and the tcp/ip stack shall be informed that a new packed has arrived. Then the tcp/ip stack will call the _ReadPacket function and after running this code, the RX-SGDMA shall be reseted for the next turn. Problem is, the counters in these functions show me, that the _ISR_HandlerRX functions is called way more often than the _ResetRX function, can anyone explain me why this is happening, i thought that i stopped the interrupt in the ISR_HandlerRx function??? Here is the Code, also appended as txt-file. Thx Christian
static void _ISR_HandlerRX(void * context, u_long intnum)
{
aCounter++; //testcounter a
// Interrupt clearen und Run-Bit zurücksetzen
IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE, ALTERA_AVALON_SGDMA_CONTROL_CLEAR_INTERRUPT_MSK & ~ALTERA_AVALON_SGDMA_CONTROL_RUN_MSK);
// inform TCP/IP stack about new packet
IP_OnRx();
bCounter++; //testcounter b
}
static int _ReadPacket(unsigned Unit, U8 *pDest, unsigned NumBytes)
{
volatile UInt32 ulPacketLengthFromSgdmaRX = 0x00,
i = 0x00;
volatile UChar8 * pRxBuff = NULL;
cCounter++; //testcounter c
ulPacketLengthFromSgdmaRX = pSgdmaDescriptor.actual_bytes_transferred;
if(IORD_ALTERA_TSEMAC_RX_CMD_STAT(TSE_MAC_BASE) & ALTERA_TSEMAC_RX_CMD_STAT_RXSHIFT16_MSK && ulRxPacketSize > 0)
ulPacketLengthFromSgdmaRX -= 2; // when the shift option is used, the length read from the status word is 2 bytes larger than the real frame size, adjust counter!
if(NumBytes == ulPacketLengthFromSgdmaRX)
{
/* test for errors */
if (((pSgdmaDescriptor.status)
& ( ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_CRC_MSK | // crc error
ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_PARITY_MSK | // parity error
ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_OVERFLOW_MSK | // overflow error
ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_SYNC_MSK | // sync error
ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_UEOP_MSK | // end of package error
ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_MEOP_MSK | // end of package error
ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_MSOP_MSK )) // start of package error
== 0)
{
pRxBuff = pUncachedPtrRx + 2; // pointer to the first field, where the data begins
while(NumBytes) // copy all data
{
pDest = *pRxBuff++;
i++;
NumBytes--;
}
}
}
dCounter++; //testcounter d
_ResetRx();
return 0;
}
static int _ResetRx(void)
{
volatile alt_u32 timeout=0,
ulSgdmaCtrl = 0x00;
eCounter++; //testcounter e
/*SGDMA RX Softwarereset*/
IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE,ALTERA_AVALON_SGDMA_CONTROL_SOFTWARERESET_MSK);
IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE,0);
memset((void*) cRxBufferTmp, 0x00, BUFF_SIZE);
memset((void*) &pSgdmaDescriptor , 0x00, sizeof(alt_sgdma_descriptor));
//pUncachedPtrRx = alt_remap_uncached((void*)cRxBufferTmp, BUFF_SIZE);
/* rx-sgdma descriptor konstruieren */
alt_avalon_sgdma_construct_stream_to_mem_desc ((alt_sgdma_descriptor *) &pSgdmaDescriptor , // descriptor I want to work with
(alt_sgdma_descriptor *) &pSgdmaDescriptor , // pointer to "next"
(UInt32 *)pUncachedPtrRx, // starting write_address
0, // read until EOP
0); // don't write to constant address
/* register callback for rx-sgdma */
alt_avalon_sgdma_register_callback ((alt_sgdma_dev *) pRxSgdmaDev,
(alt_avalon_sgdma_callback) &_ISR_HandlerRX, /* callbackfunction for the interrupt */
(ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK), /* interrupt if chain completed */
NULL);
/* Make sure SGDMA controller is not busy from a former command */
while ((IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_RX_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK))
{
if(timeout++ == ALTERA_TSE_SGDMA_BUSY_TIME_OUT_CNT)
return ENP_RESOURCE; // avoid being stuck here
}
IOWR_ALTERA_AVALON_SGDMA_STATUS(SGDMA_RX_BASE, 0xff); //clear status register (look at documentation of sgdma status reg)
/* SGDMA operation invoked for RX (non-blocking call) */
if(alt_avalon_sgdma_do_async_transfer((alt_sgdma_dev *) pRxSgdmaDev, (alt_sgdma_descriptor *) &pSgdmaDescriptor ) != 0)
return -1;
ulSgdmaCtrl = IORD_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE); // read SGDMA Ctrl Register
IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE, ulSgdmaCtrl | ALTERA_TSE_SGDMA_INTR_MASK); //write SGDMA Ctrl Regs
fCounter++; //testcounter f
return 0;
}
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't see the second descriptor being set up anywhere. Is the "OWNED_BY_HW" bit cleared in the second descriptor so it is not processed?
If it is set, the DMA controller is probably already processing the second descriptor when you clear the run bit and executing a random transfer then throwing another interrupt.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I've never used the SGDMA before but one thing I noticed while taking a quick look at the code: In _resetrx you are trying to reset the SGDMA by writing ALTERA_AVALON_SGDMA_CONTROL_SOFTWARERESET_MSK once. But I think it must be done twice. Doesn't it?! I guess that's not solving your problem but maybe it's causing trouble too. Regards ADDITION: Do you really need the software reset? Quoting the embedded ip user guide:--- Quote Start --- Executing a software reset when a DMA transfer is active may result in permanent bus lockup until the next system reset. Hence, Altera recommends that you use the software reset as your last resort. --- Quote End ---
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The Own-By Bit of the second descriptor is cleared, so that shouldn't be the problem.
I also deleted the Software-Reset of the SGDMA. I thought so too, that the SW-Reset isn't necessary. I also think we found the problem within the TCP/IP Stack. I'll try to set up a second descriptor chain for RX, seems also that one Rx Chain limited the speed extremly. So let's hope for the best. I'll report if my new idea works.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page