/** * * This is the Receive handler function for examples 1 and 2. * It will increment a shared counter, receive and validate the frame. * * @param RxRingPtr is a pointer to the DMA ring instance. * * @return None. * * @note None. * ******************************************************************************/ static void RxIntrHandler(XLlDma_BdRing * RxRingPtr) { u32 IrqStatus; /* Read pending interrupts */ IrqStatus = XLlDma_mBdRingGetIrq(RxRingPtr); /* Acknowledge pending interrupts */ XLlDma_mBdRingAckIrq(RxRingPtr, IrqStatus); /* If error interrupt is asserted, raise error flag, reset the * hardware to recover from the error, and return with no further * processing. */ if ((IrqStatus & XLLDMA_IRQ_ALL_ERR_MASK)) { DeviceErrors++; TemacUtilErrorTrap ("LlDma: Error: IrqStatus & XLLDMA_IRQ_ALL_ERR_MASK"); XLlDma_Reset(&DmaInstance); return; } /* * If Reception done interrupt is asserted, call RX call back function * to handle the processed BDs and then raise the according flag. */ if ((IrqStatus & (XLLDMA_IRQ_DELAY_MASK | XLLDMA_IRQ_COALESCE_MASK))) { RxCallBack(RxRingPtr); } }
/** * Reset both TX and RX channels of a DMA engine. * * Any DMA transaction in progress aborts immediately. The DMA engine is in * stop state after the reset. * * @param InstancePtr is a pointer to the DMA engine instance to be worked on. * * @return None. * * @note * - If the hardware is not working properly, this function will enter * infinite loop and never return. * - After the reset, the Normal mode is enabled, and the overflow error * for both TX/RX channels are disabled. * - After the reset, the DMA engine is no longer in pausing state, if * the DMA engine is paused before the reset operation. * - After the reset, the coalescing count value and the delay timeout * value are both set to 1 for TX and RX channels. * - After the reset, all interrupts are disabled. * ******************************************************************************/ void XLlDma_Reset(XLlDma * InstancePtr) { u32 IrqStatus; XLlDma_BdRing *TxRingPtr, *RxRingPtr; TxRingPtr = &XLlDma_mGetTxRing(InstancePtr); RxRingPtr = &XLlDma_mGetRxRing(InstancePtr); /* Save the locations of current BDs both rings are working on * before the reset so later we can resume the rings smoothly. */ XLlDma_mBdRingSnapShotCurrBd(TxRingPtr); XLlDma_mBdRingSnapShotCurrBd(RxRingPtr); /* Start reset process then wait for completion */ XLlDma_mSetCr(InstancePtr, XLLDMA_DMACR_SW_RESET_MASK); /* Loop until the reset is done */ while ((XLlDma_mGetCr(InstancePtr) & XLLDMA_DMACR_SW_RESET_MASK)) { } /* Disable all interrupts after issue software reset */ XLlDma_mBdRingIntDisable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK); XLlDma_mBdRingIntDisable(RxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK); /* Clear Interrupt registers of both channels, as the software reset * does not clear any register values. Not doing so will cause * interrupts asserted after the software reset if there is any * interrupt left over before. */ IrqStatus = XLlDma_mBdRingGetIrq(TxRingPtr); XLlDma_mBdRingAckIrq(TxRingPtr, IrqStatus); IrqStatus = XLlDma_mBdRingGetIrq(RxRingPtr); XLlDma_mBdRingAckIrq(RxRingPtr, IrqStatus); /* Enable Normal mode, and disable overflow errors for both channels */ XLlDma_mSetCr(InstancePtr, XLLDMA_DMACR_TAIL_PTR_EN_MASK | XLLDMA_DMACR_RX_OVERFLOW_ERR_DIS_MASK | XLLDMA_DMACR_TX_OVERFLOW_ERR_DIS_MASK); /* Set TX/RX Channel coalescing setting */ XLlDma_BdRingSetCoalesce(TxRingPtr, 1, 1); XLlDma_BdRingSetCoalesce(RxRingPtr, 1, 1); TxRingPtr->RunState = XST_DMA_SG_IS_STOPPED; RxRingPtr->RunState = XST_DMA_SG_IS_STOPPED; }