/** * * This example uses polled mode to queue up multiple frames in the packet * FIFOs before sending them in a single burst. Receive packets are handled in * a similar way. * * @param None. * * @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. * * @note None. * ******************************************************************************/ int TemacMultipleFramesPolledExample(void) { u32 FramesToLoopback; u32 PayloadSize; u32 TxFrameLength; u32 RxFrameLength; u32 FifoFreeBytes; u32 Index; /* * Start the TEMAC device */ XLlTemac_Start(&TemacInstance); /* * Setup the number of frames to loopback (FramesToLoopback) and the size * of the frame (PayloadSize) to loopback. The default settings should * work for every case. Modifying the settings can cause problems, see * discussion below: * * If PayloadSize is set small and FramesToLoopback high, then it is * possible to cause the transmit status FIFO to overflow. * * If PayloadSize is set large and FramesToLoopback high, then it is * possible to cause the transmit packet FIFO to overflow. * * Either of these scenarios may be worth trying out to observe how the * driver reacts. The exact values to cause these types of errors * will vary due to the sizes of the FIFOs selected at hardware build * time. But the following settings should create problems for all * FIFO sizes: * * Transmit status FIFO overflow * PayloadSize = 1 * FramesToLoopback = 1000 * * Transmit packet FIFO overflow * PayloadSize = 1500 * FramesToLoopback = 16 * * These values should always work without error * PayloadSize = 100 * FramesToLoopback = 5 */ PayloadSize = 100; FramesToLoopback = 5; /* * Calculate Tx frame length (not including FCS) */ TxFrameLength = XTE_HDR_SIZE + PayloadSize; /* * Setup the packet to be transmitted */ TemacUtilFrameHdrFormatMAC(&TxFrame, TemacMAC); TemacUtilFrameHdrFormatType(&TxFrame, PayloadSize); TemacUtilFrameSetPayloadData(&TxFrame, PayloadSize); /****************/ /* Send packets */ /****************/ /* * Since we may be interested to see what happens when FIFOs overflow, don't * check for room in the transmit packet FIFO prior to writing to it. */ /* * Write frame data to FIFO * Fifo core only allows loading and sending one frame at a time. */ for (Index = 0; Index < FramesToLoopback; Index++) { /* Make sure there is room in the FIFO */ do { FifoFreeBytes = XLlFifo_TxVacancy(&FifoInstance); } while (FifoFreeBytes < TxFrameLength); XLlFifo_Write(&FifoInstance, TxFrame, TxFrameLength); XLlFifo_TxSetLen(&FifoInstance, TxFrameLength); switch (TemacPollForTxStatus()) { case XST_SUCCESS: /* Got a sucessfull transmit status */ break; case XST_NO_DATA: /* Timed out */ TemacUtilErrorTrap("Tx timeout"); return XST_FAILURE; break; default: /* Some other error */ TemacResetDevice(); return XST_FAILURE; } } /**********************/ /* Receive the packet */ /**********************/ /* * Wait for the packets to arrive * The Fifo core only allows us to pull out one frame at a time. */ for (Index = 0; Index < FramesToLoopback; Index++) { /* * Wait for packet Rx */ switch (TemacPollForRxStatus()) { case XST_SUCCESS: /* Got a successfull receive status */ break; case XST_NO_DATA: /* Timed out */ TemacUtilErrorTrap("Rx timeout"); return XST_FAILURE; break; default: /* Some other error */ TemacResetDevice(); return XST_FAILURE; } while(XLlFifo_RxOccupancy(&FifoInstance)) { /* * A packet has arrived, get its length */ RxFrameLength = XLlFifo_RxGetLen(&FifoInstance); /* * Verify the received frame length */ if ((RxFrameLength) != TxFrameLength) { TemacUtilErrorTrap("Receive length incorrect"); return XST_FAILURE; } /* * Read the received packet data */ XLlFifo_Read(&FifoInstance, &RxFrame, RxFrameLength); if (TemacUtilFrameVerify(&TxFrame, &RxFrame) != 0) { TemacUtilErrorTrap("Receive Data Mismatch"); return XST_FAILURE; } } } /* * Stop device */ XLlTemac_Stop(&TemacInstance); return XST_SUCCESS; }
/** * * This function demonstrates the usage of the TEMAC by sending and receiving * a single frame in SGDMA interrupt mode. * The source packet will be described by two descriptors. It will be received * into a buffer described by a single descriptor. * * @param TemacInstancePtr is a pointer to the instance of the Temac * component. * * @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. * * @note None. * ******************************************************************************/ int TemacSgDmaIntrSingleFrameExample(XLlTemac * TemacInstancePtr, XLlDma * DmaInstancePtr) { int Status; u32 TxFrameLength; int PayloadSize = 1000; XLlDma_BdRing *RxRingPtr = &XLlDma_GetRxRing(DmaInstancePtr); XLlDma_BdRing *TxRingPtr = &XLlDma_GetTxRing(DmaInstancePtr); XLlDma_Bd *Bd1Ptr; XLlDma_Bd *Bd2Ptr; /* * Clear variables shared with callbacks */ FramesRx = 0; FramesTx = 0; DeviceErrors = 0; /* * Calculate the frame length (not including FCS) */ TxFrameLength = XTE_HDR_SIZE + PayloadSize; /* * Setup packet to be transmitted */ TemacUtilFrameHdrFormatMAC(&TxFrame, TemacMAC); TemacUtilFrameHdrFormatType(&TxFrame, PayloadSize); TemacUtilFrameSetPayloadData(&TxFrame, PayloadSize); /* * Flush the TX frame before giving it to DMA TX channel to transmit, * in case D-Caching is turned on. */ XCACHE_FLUSH_DCACHE_RANGE(&TxFrame, TxFrameLength); /* * Clear out receive packet memory area */ TemacUtilFrameMemClear(&RxFrame); /* * Invalidate the RX frame before giving it to DMA RX channel to * receive data, in case D-Caching is turned on. */ XCACHE_INVALIDATE_DCACHE_RANGE(&RxFrame, TxFrameLength); /* * Start the LLTEMAC device and enable the ERROR interrupt */ XLlTemac_Start(TemacInstancePtr); XLlTemac_IntEnable(TemacInstancePtr, XTE_INT_RECV_ERROR_MASK); /* * Allocate 1 RxBD. Note that TEMAC utilizes an in-place allocation * scheme. The returned Bd1Ptr will point to a free BD in the memory * segment setup with the call to XLlTemac_SgSetSpace() */ Status = XLlDma_BdRingAlloc(RxRingPtr, 1, &Bd1Ptr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error allocating RxBD"); return XST_FAILURE; } /* * Setup the BD. The BD template used in the call to XLlTemac_SgSetSpace() * set the "last" field of all RxBDs. Therefore we are not required to * issue a XLlDma_Bd_mSetLast(Bd1Ptr) here. */ XLlDma_BdSetBufAddr(Bd1Ptr, &RxFrame); XLlDma_BdSetLength(Bd1Ptr, sizeof(RxFrame)); XLlDma_BdSetStsCtrl(Bd1Ptr, XLLDMA_BD_STSCTRL_SOP_MASK | XLLDMA_BD_STSCTRL_EOP_MASK); /* * Enqueue to HW */ Status = XLlDma_BdRingToHw(RxRingPtr, 1, Bd1Ptr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error committing RxBD to HW"); return XST_FAILURE; } /* * Enable DMA RX interrupt. * * Interrupt coalescing parameters are left at their default settings * which is to interrupt the processor after every frame has been * processed by the DMA engine. */ XLlDma_BdRingIntEnable(RxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK); /* * Start DMA RX channel. Now it's ready to receive data. */ Status = XLlDma_BdRingStart(RxRingPtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Allocate, setup, and enqueue 2 TxBDs. The first BD will describe * the first 32 bytes of TxFrame and the second BD will describe the * rest of the frame. * * The function below will allocate two adjacent BDs with Bd1Ptr being * set as the lead BD. */ Status = XLlDma_BdRingAlloc(TxRingPtr, 2, &Bd1Ptr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error allocating TxBD"); return XST_FAILURE; } /* * Setup TxBD #1 */ XLlDma_BdSetBufAddr(Bd1Ptr, &TxFrame); XLlDma_BdSetLength(Bd1Ptr, 32); XLlDma_BdSetStsCtrl(Bd1Ptr, XLLDMA_BD_STSCTRL_SOP_MASK); /* * Setup TxBD #2 */ Bd2Ptr = XLlDma_BdRingNext(TxRingPtr, Bd1Ptr); XLlDma_BdSetBufAddr(Bd2Ptr, (u32) (&TxFrame) + 32); XLlDma_BdSetLength(Bd2Ptr, TxFrameLength - 32); XLlDma_BdSetStsCtrl(Bd2Ptr, XLLDMA_BD_STSCTRL_EOP_MASK); /* * Enqueue to HW */ Status = XLlDma_BdRingToHw(TxRingPtr, 2, Bd1Ptr); if (Status != XST_SUCCESS) { /* * Undo BD allocation and exit */ XLlDma_BdRingUnAlloc(TxRingPtr, 2, Bd1Ptr); TemacUtilErrorTrap("Error committing TxBD to HW"); return XST_FAILURE; } /* * Enable DMA transmit interrupts */ XLlDma_BdRingIntEnable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK); /* * Start DMA TX channel. Transmission starts at once. */ Status = XLlDma_BdRingStart(TxRingPtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait for transmission to complete */ while (!FramesTx); /* * Now that the frame has been sent, post process our TxBDs. * Since we have only submitted 2 to HW, then there should be only 2 ready * for post processing. */ if (XLlDma_BdRingFromHw(TxRingPtr, 2, &Bd1Ptr) == 0) { TemacUtilErrorTrap("TxBDs were not ready for post processing"); return XST_FAILURE; } /* * Examine the TxBDs. * * There isn't much to do. The only thing to check would be DMA exception * bits. But this would also be caught in the error handler. So we just * return these BDs to the free list */ Status = XLlDma_BdRingFree(TxRingPtr, 2, Bd1Ptr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error freeing up TxBDs"); return XST_FAILURE; } /* * Wait for Rx indication */ while (!FramesRx); printf("Transmitted Packet!\r\n"); printf("\r\n"); /* * Now that the frame has been received, post process our RxBD. * Since we have only submitted 1 to HW, then there should be only 1 ready * for post processing. */ if (XLlDma_BdRingFromHw(RxRingPtr, 1, &Bd1Ptr) == 0) { TemacUtilErrorTrap("RxBD was not ready for post processing"); return XST_FAILURE; } /* * There is no device status to check. If there was a DMA error, it * should have been reported to the error handler. Check the receive * length against the transmitted length, then verify the data. * * Note in LLTEMAC case, USR4_OFFSET word in the RX BD is used to store * the real length of the received packet */ if ((XLlDma_BdRead(Bd1Ptr, XLLDMA_BD_USR4_OFFSET) & 0x3FFF) != TxFrameLength) { TemacUtilErrorTrap("Length mismatch"); return XST_FAILURE; } if (TemacUtilFrameVerify(&TxFrame, &RxFrame) != 0) { TemacUtilErrorTrap("Data mismatch"); return XST_FAILURE; } /* * Return the RxBD back to the channel for later allocation. Free the * exact number we just post processed. */ Status = XLlDma_BdRingFree(RxRingPtr, 1, Bd1Ptr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error freeing up TxBDs"); return XST_FAILURE; } /* * Finished this example. If everything worked correctly, all TxBDs and * RxBDs should be free for allocation. Stop the device. */ XLlTemac_Stop(TemacInstancePtr); return XST_SUCCESS; }
/** * * This function demonstrates the usage of the TEMAC by sending and receiving * a single frame in polled mode. * * @param None. * * @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. * * @note None. * ******************************************************************************/ int TemacSingleFramePolledExample(void) { u32 FifoFreeBytes; int PayloadSize = 100; u32 TxFrameLength; u32 RxFrameLength; /* * Start the TEMAC device */ XLlTemac_Start(&TemacInstance); /* * Setup the packet to be transmitted */ TemacUtilFrameHdrFormatMAC(&TxFrame, TemacMAC); TemacUtilFrameHdrFormatType(&TxFrame, PayloadSize); TemacUtilFrameSetPayloadData(&TxFrame, PayloadSize); /* * Clear out the receive packet memory area */ TemacUtilFrameMemClear(&RxFrame); /* * Calculate frame length (not including FCS) */ TxFrameLength = XTE_HDR_SIZE + PayloadSize; /*******************/ /* Send the packet */ /*******************/ /* * Wait for enough room in FIFO to become available */ do { FifoFreeBytes = XLlFifo_TxVacancy(&FifoInstance); } while (FifoFreeBytes < TxFrameLength); /* * Write the frame data to FIFO */ XLlFifo_Write(&FifoInstance, TxFrame, TxFrameLength); /* * Initiate transmit */ XLlFifo_TxSetLen(&FifoInstance, TxFrameLength); /* * Wait for status of the transmitted packet */ switch (TemacPollForTxStatus()) { case XST_SUCCESS: /* Got a sucessfull transmit status */ break; case XST_NO_DATA: /* Timed out */ TemacUtilErrorTrap("Tx timeout"); return XST_FAILURE; default: /* Some other error */ return XST_FAILURE; } /**********************/ /* Receive the packet */ /**********************/ /* * Wait for packet Rx */ switch (TemacPollForRxStatus()) { case XST_SUCCESS: /* Got a sucessfull receive status */ break; case XST_NO_DATA: /* Timed out */ TemacUtilErrorTrap("Rx timeout"); return XST_FAILURE; default: /* Some other error */ return XST_FAILURE; } while(XLlFifo_RxOccupancy(&FifoInstance)) { /* * A packet as arrived, get its length */ RxFrameLength = XLlFifo_RxGetLen(&FifoInstance); /* * Read the received packet data */ XLlFifo_Read(&FifoInstance, &RxFrame, RxFrameLength); /* * Verify the received frame length */ if ((RxFrameLength) != TxFrameLength) { TemacUtilErrorTrap("Receive length incorrect"); return XST_FAILURE; } /* * Validate frame data */ if (TemacUtilFrameVerify(&TxFrame, &RxFrame) != 0) { TemacUtilErrorTrap("Receive Data mismatch"); return XST_FAILURE; } } /* * Stop device */ XLlTemac_Stop(&TemacInstance); return XST_SUCCESS; }