Exemple #1
0
/**
*
* Aborts a transfer in progress by disabling the device and resetting the FIFOs
* if present. The byte counts are cleared, the busy flag is cleared, and mode
* fault is cleared.
*
* @param	InstancePtr is a pointer to the XSpiPs instance.
*
* @return	None.
*
* @note
*
* This function does a read/modify/write of the Config register. The user of
* this function needs to take care of critical sections.
*
******************************************************************************/
void XSpiPs_Abort(XSpiPs *InstancePtr)
{

    u8 Temp;
    u32 Check;
    XSpiPs_Disable(InstancePtr);

    /*
     * Clear the RX FIFO and drop any data.
     */
    Check = (XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
                            XSPIPS_SR_OFFSET) & XSPIPS_IXR_RXNEMPTY_MASK);
    while (Check != (u32)0U) {
        Temp = (u8)XSpiPs_RecvByte(InstancePtr->Config.BaseAddress);
        if(Temp != (u8)0U) {
        }
        Check = (XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
                                XSPIPS_SR_OFFSET) & XSPIPS_IXR_RXNEMPTY_MASK);
    }

    /*
     * Clear mode fault condition.
     */
    XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
                    XSPIPS_SR_OFFSET,
                    XSPIPS_IXR_MODF_MASK);

    InstancePtr->RemainingBytes = 0U;
    InstancePtr->RequestedBytes = 0U;
    InstancePtr->IsBusy = FALSE;
}
/**
*
* Aborts a transfer in progress by disabling the device and resetting the FIFOs
* if present. The byte counts are cleared, the busy flag is cleared, and mode
* fault is cleared.
*
* @param	InstancePtr is a pointer to the XSpiPs instance.
*
* @return	None.
*
* @note
*
* This function does a read/modify/write of the Config register. The user of
* this function needs to take care of critical sections.
*
******************************************************************************/
void XSpiPs_Abort(XSpiPs *InstancePtr)
{

	XSpiPs_Disable(InstancePtr);

	/*
	 * Clear the RX FIFO and drop any data.
	 */
	while ((XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
		 XSPIPS_SR_OFFSET) & XSPIPS_IXR_RXNEMPTY_MASK) ==
		XSPIPS_IXR_RXNEMPTY_MASK) {
		(void) XSpiPs_RecvByte(InstancePtr->Config.BaseAddress);
	}

	/*
	 * Clear mode fault condition.
	 */
	XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
			XSPIPS_SR_OFFSET,
			XSPIPS_IXR_MODF_MASK);

	InstancePtr->RemainingBytes = 0;
	InstancePtr->RequestedBytes = 0;
	InstancePtr->IsBusy = FALSE;
}
Exemple #3
0
/**
*
* The interrupt handler for SPI interrupts. This function must be connected
* by the user to an interrupt controller.
*
* The interrupts that are handled are:
*
* - Mode Fault Error. This interrupt is generated if this device is selected
*   as a slave when it is configured as a master. The driver aborts any data
*   transfer that is in progress by resetting FIFOs (if present) and resetting
*   its buffer pointers. The upper layer software is informed of the error.
*
* - Data Transmit Register (FIFO) Empty. This interrupt is generated when the
*   transmit register or FIFO is empty. The driver uses this interrupt during a
*   transmission to continually send/receive data until the transfer is done.
*
* - Data Transmit Register (FIFO) Underflow. This interrupt is generated when
*   the SPI device, when configured as a slave, attempts to read an empty
*   DTR/FIFO.  An empty DTR/FIFO usually means that software is not giving the
*   device data in a timely manner. No action is taken by the driver other than
*   to inform the upper layer software of the error.
*
* - Data Receive Register (FIFO) Overflow. This interrupt is generated when the
*   SPI device attempts to write a received byte to an already full DRR/FIFO.
*   A full DRR/FIFO usually means software is not emptying the data in a timely
*   manner.  No action is taken by the driver other than to inform the upper
*   layer software of the error.
*
* - Slave Mode Fault Error. This interrupt is generated if a slave device is
*   selected as a slave while it is disabled. No action is taken by the driver
*   other than to inform the upper layer software of the error.
*
* @param	InstancePtr is a pointer to the XSpiPs instance.
*
* @return	None.
*
* @note
*
* The slave select register is being set to deselect the slave when a transfer
* is complete.  This is being done regardless of whether it is a slave or a
* master since the hardware does not drive the slave select as a slave.
*
******************************************************************************/
void XSpiPs_InterruptHandler(XSpiPs *InstancePtr)
{
    XSpiPs *SpiPtr = InstancePtr;
    u32 IntrStatus;
    u32 ConfigReg;
    u32 BytesDone; /* Number of bytes done so far. */

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(SpiPtr->IsReady == XIL_COMPONENT_IS_READY);

    /*
     * Immediately clear the interrupts in case the ISR causes another
     * interrupt to be generated. If we clear at the end of the ISR,
     * we may miss newly generated interrupts.
     * Disable the TXOW interrupt because we transmit from within the ISR,
     * which could potentially cause another TX_OW interrupt.
     */
    IntrStatus =
        XSpiPs_ReadReg(SpiPtr->Config.BaseAddress, XSPIPS_SR_OFFSET);
    XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, XSPIPS_SR_OFFSET,
                    (IntrStatus & XSPIPS_IXR_WR_TO_CLR_MASK));
    XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, XSPIPS_IDR_OFFSET,
                    XSPIPS_IXR_TXOW_MASK);

    /*
     * Check for mode fault error. We want to check for this error first,
     * before checking for progress of a transfer, since this error needs
     * to abort any operation in progress.
     */
    if ((u32)XSPIPS_IXR_MODF_MASK == (u32)(IntrStatus & XSPIPS_IXR_MODF_MASK)) {
        BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;

        /*
         * Abort any operation currently in progress. This includes
         * clearing the mode fault condition by reading the status
         * register. Note that the status register should be read after
         * the abort, since reading the status register clears the mode
         * fault condition and would cause the device to restart any
         * transfer that may be in progress.
         */
        XSpiPs_Abort(SpiPtr);

        SpiPtr->StatusHandler(SpiPtr->StatusRef, XST_SPI_MODE_FAULT,
                              BytesDone);

        return; /* Do not continue servicing other interrupts. */
    }


    if ((IntrStatus & XSPIPS_IXR_TXOW_MASK) != 0U) {
        u8 TempData;
        u32 TransCount;
        /*
         * A transmit has just completed. Process received data and
         * check for more data to transmit.
         * First get the data received as a result of the transmit that
         * just completed.  Always get the received data, but only fill
         * the receive buffer if it is not null (it can be null when
         * the device does not care to receive data).
         * Initialize the TransCount based on the requested bytes.
         * Loop on receive FIFO based on TransCount.
         */
        TransCount = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;

        while (TransCount != 0U) {
            TempData = (u8)XSpiPs_RecvByte(SpiPtr->Config.BaseAddress);
            if (SpiPtr->RecvBufferPtr != NULL) {
                *SpiPtr->RecvBufferPtr = TempData;
                SpiPtr->RecvBufferPtr += 1;
            }
            SpiPtr->RequestedBytes--;
            --TransCount;
        }

        /*
         * Fill the TXFIFO until data exists, otherwise fill upto
         * FIFO depth.
         */
        while ((SpiPtr->RemainingBytes > 0U) &&
                (TransCount < XSPIPS_FIFO_DEPTH)) {
            XSpiPs_SendByte(SpiPtr->Config.BaseAddress,
                            *SpiPtr->SendBufferPtr);
            SpiPtr->SendBufferPtr += 1;
            SpiPtr->RemainingBytes--;
            ++TransCount;
        }

        if ((SpiPtr->RemainingBytes == 0U) &&
                (SpiPtr->RequestedBytes == 0U)) {
            /*
             * No more data to send. Disable the interrupt and
             * inform the upper layer software that the transfer
             * is done. The interrupt will be re-enabled when
             * another transfer is initiated.
             */
            XSpiPs_WriteReg(SpiPtr->Config.BaseAddress,
                            XSPIPS_IDR_OFFSET, XSPIPS_IXR_DFLT_MASK);

            /*
             * Disable slave select lines as the transfer
             * is complete.
             */
            if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) {
                ConfigReg = XSpiPs_ReadReg(
                                SpiPtr->Config.BaseAddress,
                                XSPIPS_CR_OFFSET);
                ConfigReg |= XSPIPS_CR_SSCTRL_MASK;
                XSpiPs_WriteReg(
                    SpiPtr->Config.BaseAddress,
                    XSPIPS_CR_OFFSET, ConfigReg);
            }

            /*
             * Clear the busy flag.
             */
            SpiPtr->IsBusy = FALSE;

            /*
             * Disable the device.
             */
            XSpiPs_Disable(SpiPtr);

            /*
             * Inform the Transfer done to upper layers.
             */
            SpiPtr->StatusHandler(SpiPtr->StatusRef,
                                  XST_SPI_TRANSFER_DONE,
                                  SpiPtr->RequestedBytes);
        } else {
            /*
             * Enable the TXOW interrupt.
             */
            XSpiPs_WriteReg(SpiPtr->Config.BaseAddress,
                            XSPIPS_IER_OFFSET, XSPIPS_IXR_TXOW_MASK);
            /*
             * Start the transfer by not inhibiting the transmitter
             * any longer.
             */
            if ((XSpiPs_IsManualStart(SpiPtr) == TRUE)
                    && (XSpiPs_IsMaster(SpiPtr) == TRUE)) {
                ConfigReg = XSpiPs_ReadReg(
                                SpiPtr->Config.BaseAddress,
                                XSPIPS_CR_OFFSET);
                ConfigReg |= XSPIPS_CR_MANSTRT_MASK;
                XSpiPs_WriteReg(
                    SpiPtr->Config.BaseAddress,
                    XSPIPS_CR_OFFSET, ConfigReg);
            }
        }
    }

    /*
     * Check for overflow and underflow errors.
     */
    if ((IntrStatus & XSPIPS_IXR_RXOVR_MASK) != 0U) {
        BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;
        SpiPtr->IsBusy = FALSE;

        /*
         * The Slave select lines are being manually controlled.
         * Disable them because the transfer is complete.
         */
        if (XSpiPs_IsManualChipSelect(SpiPtr) == TRUE) {
            ConfigReg = XSpiPs_ReadReg(
                            SpiPtr->Config.BaseAddress,
                            XSPIPS_CR_OFFSET);
            ConfigReg |= XSPIPS_CR_SSCTRL_MASK;
            XSpiPs_WriteReg(
                SpiPtr->Config.BaseAddress,
                XSPIPS_CR_OFFSET, ConfigReg);
        }

        SpiPtr->StatusHandler(SpiPtr->StatusRef,
                              XST_SPI_RECEIVE_OVERRUN, BytesDone);
    }

    if ((IntrStatus & XSPIPS_IXR_TXUF_MASK) != 0U) {
        BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes;

        SpiPtr->IsBusy = FALSE;
        /*
         * The Slave select lines are being manually controlled.
         * Disable them because the transfer is complete.
         */
        if (XSpiPs_IsManualChipSelect(SpiPtr) == TRUE) {
            ConfigReg = XSpiPs_ReadReg(
                            SpiPtr->Config.BaseAddress,
                            XSPIPS_CR_OFFSET);
            ConfigReg |= XSPIPS_CR_SSCTRL_MASK;
            XSpiPs_WriteReg(
                SpiPtr->Config.BaseAddress,
                XSPIPS_CR_OFFSET, ConfigReg);
        }

        SpiPtr->StatusHandler(SpiPtr->StatusRef,
                              XST_SPI_TRANSMIT_UNDERRUN, BytesDone);
    }

}
Exemple #4
0
/**
* Transfers specified data on the SPI bus in polled mode.
*
* The caller has the option of providing two different buffers for send and
* receive, or one buffer for both send and receive, or no buffer for receive.
* The receive buffer must be at least as big as the send buffer to prevent
* unwanted memory writes. This implies that the byte count passed in as an
* argument must be the smaller of the two buffers if they differ in size.
* Here are some sample usages:
* <pre>
*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
*	The caller wishes to send and receive, and provides two different
*	buffers for send and receive.
*
*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, NULL, ByteCount)
*	The caller wishes only to send and does not care about the received
*	data. The driver ignores the received data in this case.
*
*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, SendBuf, ByteCount)
*	The caller wishes to send and receive, but provides the same buffer
*	for doing both. The driver sends the data and overwrites the send
*	buffer with received data as it transfers the data.
*
*   XSpiPs_PolledTransfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
*	The caller wishes to only receive and does not care about sending
*	data.  In this case, the caller must still provide a send buffer, but
*	it can be the same as the receive buffer if the caller does not care
*	what it sends.  The device must send N bytes of data if it wishes to
*	receive N bytes of data.
*
* </pre>
*
* @param	InstancePtr is a pointer to the XSpiPs instance.
* @param	SendBufPtr is a pointer to a buffer of data for sending.
*		This buffer must not be NULL.
* @param	RecvBufPtr is a pointer to a buffer for received data.
*		This argument can be NULL if do not care about receiving.
* @param	ByteCount contains the number of bytes to send/receive.
*		The number of bytes received always equals the number of bytes
*		sent.

* @return
*		- XST_SUCCESS if the buffers are successfully handed off to the
*		device for transfer.
*		- XST_DEVICE_BUSY indicates that a data transfer is already in
*		progress. This is determined by the driver.
*
* @note
*
* This function is not thread-safe.  The higher layer software must ensure that
* no two threads are transferring data on the SPI bus at the same time.
*
******************************************************************************/
s32 XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr,
                          u8 *RecvBufPtr, u32 ByteCount)
{
    u32 StatusReg;
    u32 ConfigReg;
    u32 TransCount;
    u32 CheckTransfer;
    s32 Status_Polled;
    u8 TempData;

    /*
     * The RecvBufPtr argument can be NULL.
     */
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(SendBufPtr != NULL);
    Xil_AssertNonvoid(ByteCount > 0U);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    /*
     * Check whether there is another transfer in progress. Not thread-safe.
     */
    if (InstancePtr->IsBusy == TRUE) {
        Status_Polled = (s32)XST_DEVICE_BUSY;
    } else {

        /*
         * Set the busy flag, which will be cleared when the transfer is
         * entirely done.
         */
        InstancePtr->IsBusy = TRUE;

        /*
         * Set up buffer pointers.
         */
        InstancePtr->SendBufferPtr = SendBufPtr;
        InstancePtr->RecvBufferPtr = RecvBufPtr;

        InstancePtr->RequestedBytes = ByteCount;
        InstancePtr->RemainingBytes = ByteCount;

        /*
         * If manual chip select mode, initialize the slave select value.
         */
        if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) {
            ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
                                       XSPIPS_CR_OFFSET);
            /*
             * Set the slave select value.
             */
            ConfigReg &= (u32)(~XSPIPS_CR_SSCTRL_MASK);
            ConfigReg |= InstancePtr->SlaveSelect;
            XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
                            XSPIPS_CR_OFFSET, ConfigReg);
        }

        /*
         * Enable the device.
         */
        XSpiPs_Enable(InstancePtr);

        while((InstancePtr->RemainingBytes > (u32)0U) ||
                (InstancePtr->RequestedBytes > (u32)0U)) {
            TransCount = 0U;
            /*
             * Fill the TXFIFO with as many bytes as it will take (or as
             * many as we have to send).
             */
            while ((InstancePtr->RemainingBytes > (u32)0U) &&
                    ((u32)TransCount < (u32)XSPIPS_FIFO_DEPTH)) {
                XSpiPs_SendByte(InstancePtr->Config.BaseAddress,
                                *InstancePtr->SendBufferPtr);
                InstancePtr->SendBufferPtr += 1;
                InstancePtr->RemainingBytes--;
                ++TransCount;
            }

            /*
             * If master mode and manual start mode, issue manual start
             * command to start the transfer.
             */
            if ((XSpiPs_IsManualStart(InstancePtr) == TRUE)
                    && (XSpiPs_IsMaster(InstancePtr) == TRUE)) {
                ConfigReg = XSpiPs_ReadReg(
                                InstancePtr->Config.BaseAddress,
                                XSPIPS_CR_OFFSET);
                ConfigReg |= XSPIPS_CR_MANSTRT_MASK;
                XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
                                XSPIPS_CR_OFFSET, ConfigReg);
            }

            /*
             * Wait for the transfer to finish by polling Tx fifo status.
             */
            CheckTransfer = (u32)0U;
            while (CheckTransfer == 0U) {
                StatusReg = XSpiPs_ReadReg(
                                InstancePtr->Config.BaseAddress,
                                XSPIPS_SR_OFFSET);
                if ( (StatusReg & XSPIPS_IXR_MODF_MASK) != 0U) {
                    /*
                     * Clear the mode fail bit
                     */
                    XSpiPs_WriteReg(
                        InstancePtr->Config.BaseAddress,
                        XSPIPS_SR_OFFSET,
                        XSPIPS_IXR_MODF_MASK);
                    return (s32)XST_SEND_ERROR;
                }
                CheckTransfer = (StatusReg &
                                 XSPIPS_IXR_TXOW_MASK);
            }

            /*
             * A transmit has just completed. Process received data and
             * check for more data to transmit.
             * First get the data received as a result of the transmit
             * that just completed. Receive data based on the
             * count obtained while filling tx fifo. Always get the
             * received data, but only fill the receive buffer if it
             * points to something (the upper layer software may not
             * care to receive data).
             */
            while (TransCount != (u32)0U) {
                TempData = (u8)XSpiPs_RecvByte(
                               InstancePtr->Config.BaseAddress);
                if (InstancePtr->RecvBufferPtr != NULL) {
                    *(InstancePtr->RecvBufferPtr) = TempData;
                    InstancePtr->RecvBufferPtr += 1;
                }
                InstancePtr->RequestedBytes--;
                --TransCount;
            }
        }

        /*
         * Clear the slave selects now, before terminating the transfer.
         */
        if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) {
            ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
                                       XSPIPS_CR_OFFSET);
            ConfigReg |= XSPIPS_CR_SSCTRL_MASK;
            XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
                            XSPIPS_CR_OFFSET, ConfigReg);
        }

        /*
         * Clear the busy flag.
         */
        InstancePtr->IsBusy = FALSE;

        /*
         * Disable the device.
         */
        XSpiPs_Disable(InstancePtr);
        Status_Polled = (s32)XST_SUCCESS;
    }
    return Status_Polled;
}