示例#1
0
/**
*
* This function sets the options for the SPI device driver. The options control
* how the device behaves relative to the SPI bus. The device must be idle
* rather than busy transferring data before setting these device options.
*
* @param	InstancePtr is a pointer to the XSpiPs instance.
* @param	Options contains the specified options to be set. This is a bit
*		mask where a 1 means to turn the option on, and a 0 means to
*		turn the option off. One or more bit values may be contained in
*		the mask. See the bit definitions named XSPIPS_*_OPTIONS in the
*		file xspips.h.
*
* @return
*		- XST_SUCCESS if options are successfully set.
*		- XST_DEVICE_BUSY if the device is currently transferring data.
*		The transfer must complete or be aborted before setting options.
*
* @note
* This function is not thread-safe.
*
******************************************************************************/
s32 XSpiPs_SetOptions(XSpiPs *InstancePtr, u32 Options)
{
	u32 ConfigReg;
	u32 Index;
	u32 CurrentConfigReg;
	s32 Status;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Do not allow the slave select to change while a transfer is in
	 * progress. Not thread-safe.
	 */
	if (InstancePtr->IsBusy == TRUE) {
		Status = (s32)XST_DEVICE_BUSY;
	} else {

		ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
					 XSPIPS_CR_OFFSET);

		CurrentConfigReg = ConfigReg;

		/*
		 * Loop through the options table, turning the option on or off
		 * depending on whether the bit is set in the incoming options flag.
		 */
		for (Index = 0U; Index < XSPIPS_NUM_OPTIONS; Index++) {
			if ((Options & OptionsTable[Index].Option) != (u32)0U) {
				/* Turn it on */
				ConfigReg |= OptionsTable[Index].Mask;
			}
			else {
				/* Turn it off */
				ConfigReg &= ~(OptionsTable[Index].Mask);
			}
		}


		/*
		 * If CPOL-CPHA bits are toggled from previous state,
		 * disable before writing the configuration register and then enable.
		 */
		if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) !=
			(ConfigReg & XSPIPS_CR_CPOL_MASK)) ||
			((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) !=
			(ConfigReg & XSPIPS_CR_CPHA_MASK)) ) {
				XSpiPs_Disable(InstancePtr);
			}

		/*
		 * Now write the Config register. Leave it to the upper layers
		 * to restart the device.
		 */
		XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
					XSPIPS_CR_OFFSET, ConfigReg);

		/*
		 * Enable
		 */
		if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) !=
			(ConfigReg & XSPIPS_CR_CPOL_MASK)) ||
			((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) !=
			(ConfigReg & XSPIPS_CR_CPHA_MASK)) ) {
				XSpiPs_Enable(InstancePtr);
			}

		Status = (s32)XST_SUCCESS;
	}
	return Status;
}
示例#2
0
/**
*
* Transfers specified data on the SPI bus. If the SPI device is configured as
* a master, this function initiates bus communication and sends/receives the
* data to/from the selected SPI slave. If the SPI device is configured as a
* slave, this function prepares the buffers to be sent/received when selected
* by a master. For every byte sent, a byte is received. This function should
* be used to perform interrupt based transfers.
*
* 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_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
*	The caller wishes to send and receive, and provides two different
*	buffers for send and receive.
*
*   XSpiPs_Transfer(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_Transfer(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_Transfer(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>
* Although this function takes entire buffers as arguments, the driver can only
* transfer a limited number of bytes at a time, limited by the size of the
* FIFO. A call to this function only starts the transfer, then subsequent
* transfers of the data is performed by the interrupt service routine until
* the entire buffer has been transferred. The status callback function is
* called when the entire buffer has been sent/received.
*
* This function is non-blocking. As a master, the SetSlaveSelect function must
* be called prior to this function.
*
* @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_Transfer(XSpiPs *InstancePtr, u8 *SendBufPtr,
                    u8 *RecvBufPtr, u32 ByteCount)
{
    u32 ConfigReg;
    u8 TransCount = 0U;
    s32 StatusTransfer;

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

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

        /*
         * Set the busy flag, which will be cleared in the ISR 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) != FALSE) {
            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);

        /*
         * Clear all the interrrupts.
         */
        XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_SR_OFFSET,
                        XSPIPS_IXR_WR_TO_CLR_MASK);

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

        /*
         * Enable interrupts (connecting to the interrupt controller and
         * enabling interrupts should have been done by the caller).
         */
        XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
                        XSPIPS_IER_OFFSET, XSPIPS_IXR_DFLT_MASK);

        /*
         * 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);
        }
        StatusTransfer = (s32)XST_SUCCESS;
    }
    return StatusTransfer;
}
示例#3
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;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in Slave mode. This function reads data from a SPI Master
* and will echo it back to the Master.
*
* @param	SpiDeviceId is the Instance Id of SPI in the system.
*
* @return
*		- XST_SUCCESS if successful
*		- XST_FAILURE if not successful
*
* @note		None
*
*
*****************************************************************************/
int SpiPsSlavePolledExample(u16 SpiDeviceId)
{
	int Status;
	u8 *BufferPtr;
	XSpiPs_Config *SpiConfig;

	/*
	 * Initialize the SPI driver so that it's ready to use
	 */
	SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
	if (NULL == SpiConfig) {
		return XST_FAILURE;
	}

	Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig,
					SpiConfig->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * The SPI device is a slave by default and the clock phase
	 * have to be set according to its master. In this example, CPOL is set
	 * to quiescent high and CPHA is set to 1.
	 */
	Status = XSpiPs_SetOptions((&SpiInstance), (XSPIPS_CR_CPHA_MASK) | \
			(XSPIPS_CR_CPOL_MASK));
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));

	/*
	 * Set the Rx FIFO Threshold to the Max Data
	 */
	XSpiPs_SetRXWatermark((&SpiInstance),MAX_DATA);

	/*
	 * Enable the device.
	 */
	XSpiPs_Enable((&SpiInstance));

	/*
	 * Read the contents of the Receive buffer
	 * Master is expected to send MAX_DATA number of bytes
	 */
	SpiSlaveRead(MAX_DATA);

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and the same back
	 */
	BufferPtr = ReadBuffer;

	/*
	 * Send the data received back to Master
	 * Master is expected to send MAX_DATA number of dummy bytes for
	 * the slave to be able to echo previously received data.
	 */
	SpiSlaveWrite(BufferPtr, MAX_DATA);

	/*
	 * Disable the device.
	 */
	XSpiPs_Disable((&SpiInstance));

	return XST_SUCCESS;
}