📄 xqspips.c
字号:
/* Get the complete command (flash inst + address/data) */ Data = 0; XQspiPs_GetWriteData(InstancePtr, &Data, CurrInst->InstSize); /* Write the command to the FIFO */ XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, CurrInst->TxOffset, Data); } /* * Fill the Tx FIFO with as many bytes as it takes (or as many as * we have to send). */ while ((InstancePtr->RemainingBytes > 0) && ((XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET) & XQSPIPS_IXR_TXFULL_MASK) == 0)) { if (InstancePtr->RemainingBytes < 4) { XQspiPs_GetWriteData(InstancePtr, &Data, InstancePtr->RemainingBytes); } else { XQspiPs_GetWriteData(InstancePtr, &Data, 4); } XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_TXD_00_OFFSET, Data); } /* * Enable QSPI interrupts (connecting to the interrupt controller and * enabling interrupts should have been done by the caller). */ XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_IER_OFFSET, XQSPIPS_IXR_DFLT_MASK); /* * If, in Manual Start mode, Start the transfer. */ if ((ControlReg & (XQSPIPS_CR_MSTREN_MASK | XQSPIPS_CR_MANSTRTEN_MASK)) == (XQSPIPS_CR_MSTREN_MASK | XQSPIPS_CR_MANSTRTEN_MASK)) { ControlReg |= XQSPIPS_CR_MANSTRT_MASK; XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, ControlReg); } return XST_SUCCESS;}/*****************************************************************************//*** Transfers specified data on the QSPI 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>* XQspiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)* The caller wishes to send and receive, and provides two different* buffers for send and receive.** XQspiPs_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.** XQspiPs_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.** XQspiPs_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 XQspiPs instance.* @param SendBufPtr is a pointer to a data buffer that needs to be* transmitted. 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.* @param IsInst specifies whether the first byte(s) in the transmit* buffer is a serial flash instruction.* @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 QSPI bus at the same time.*******************************************************************************/int XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, unsigned ByteCount, int IsInst){ u32 StatusReg; u32 ControlReg; u8 Instruction; u32 Data; unsigned int Index; XQspiPsInstFormat *CurrInst; /* * The RecvBufPtr argument can be NULL. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(SendBufPtr != NULL); Xil_AssertNonvoid(ByteCount > 0); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(IsInst <= XQSPIPS_IS_INST); /* * Check whether there is another transfer in progress. Not thread-safe. */ if (InstancePtr->IsBusy) { return XST_DEVICE_BUSY; } /* * 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 the slave select lines are "Forced" or under manual control, * set the slave selects now, before beginning the transfer. */ ControlReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET); if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)){ ControlReg &= ~XQSPIPS_CR_SSCTRL_MASK; ControlReg |= InstancePtr->SlaveSelect; XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, ControlReg); } /* * Enable the device. */ XQspiPs_Enable(InstancePtr->Config.BaseAddress); if (IsInst == 1) { Instruction = *InstancePtr->SendBufferPtr; for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { if (Instruction == FlashInst[Index].OpCode) { break; } } if (Index == ARRAY_SIZE(FlashInst)) { /* Instruction not supported */ return XST_FAILURE; } CurrInst = &FlashInst[Index]; /* Get the complete command (flash inst + address/data) */ Data = 0; XQspiPs_GetWriteData(InstancePtr, &Data, CurrInst->InstSize); /* Write the command to the FIFO */ XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, CurrInst->TxOffset, Data); } while((InstancePtr->RemainingBytes > 0) || (InstancePtr->RequestedBytes > 0)) { /* * Fill the DTR/FIFO with as many bytes as it will take (or as * many as we have to send). */ while ((InstancePtr->RemainingBytes > 0) && ((XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET) & XQSPIPS_IXR_TXFULL_MASK) == 0)) { if (InstancePtr->RemainingBytes < 4) { XQspiPs_GetWriteData(InstancePtr, &Data, InstancePtr->RemainingBytes); } else { XQspiPs_GetWriteData(InstancePtr, &Data, 4); } XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_TXD_00_OFFSET, Data); } /* * If, in Manual Start mode, start the transfer. */ if ((ControlReg & (XQSPIPS_CR_MSTREN_MASK | XQSPIPS_CR_MANSTRTEN_MASK)) == (XQSPIPS_CR_MSTREN_MASK | XQSPIPS_CR_MANSTRTEN_MASK)) { ControlReg |= XQSPIPS_CR_MANSTRT_MASK; XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, ControlReg); } /* * Wait for the transfer to finish by polling Tx fifo status. */ do { StatusReg = XQspiPs_ReadReg( InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET); } while ((StatusReg & 0x04) == 0); /* * 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. We get all the data * available by reading the status register to determine * when the Receive register/FIFO is empty. 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 ((StatusReg & XQSPIPS_IXR_RXNEMPTY_MASK) != 0) { u32 Data; Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_RXD_OFFSET); if (InstancePtr->RequestedBytes < 4) { XQspiPs_GetReadData(InstancePtr, Data, InstancePtr->RequestedBytes); } else { XQspiPs_GetReadData(InstancePtr, Data, 4); } StatusReg = XQspiPs_ReadReg( InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET); } } /* * If the Slave select lines are being manually controlled, disable * them because the transfer is complete. */ if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)) { ControlReg |= XQSPIPS_CR_SSCTRL_MASK; XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, ControlReg); } InstancePtr->IsBusy = FALSE; /* * Disable the device. */ XQspiPs_Disable(InstancePtr->Config.BaseAddress); return XST_SUCCESS;}/*****************************************************************************//**** Read the flash in Linear QSPI mode.** @param InstancePtr is a pointer to the XQspiPs instance.* @param RecvBufPtr is a pointer to a buffer for received data.* @param Address is the starting address within the flash from* from where data needs to be read.* @param ByteCount contains the number of bytes to receive.** @return None.** @note** This function assumes that QSPI device in Linear mode. If the device is in* normal mode unexpected errors will occur.*******************************************************************************/void XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, u32 Address, unsigned ByteCount){ memcpy((void*)RecvBufPtr, (const void*)(XPAR_XQSPIPS_0_LINEAR_BASEADDR + Address), (size_t)ByteCount);}/*****************************************************************************//**** Selects the slave with which the master communicates.** The user is not allowed to select the slave while a transfer is in progress.* If no transfer is in progress, the user can select a new slave, which* implicitly deselects the current slave.** @param InstancePtr is a pointer to the XQspiPs instance.* @param SlaveSel is the chip select line which needs to be asserted.* A value of 0 asserts the first chip select line. Only one slave* can be selected at a time.** @return* - XST_SUCCESS if the slave is selected or deselected* successfully.* - XST_DEVICE_BUSY if a transfer is in progress, slave cannot be* changed.** @note** This function only sets the slave which will be selected when a transfer* occurs. The slave is not selected when the QSPI is idle. The slave select* has no affect when the device is configured as a slave.*******************************************************************************/int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr, u8 SlaveSel){ u32 ControlReg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(SlaveSel <= XQSPIPS_CR_SSCTRL_MAXIMUM); /* * Do not allow the slave select to change while a transfer is in * progress. Not thread-safe. */ if (InstancePtr->IsBusy) { return XST_DEVICE_BUSY; } InstancePtr->SlaveSelect = (((~(0x0001 << SlaveSel)) << XQSPIPS_CR_SSCTRL_SHIFT) & XQSPIPS_CR_SSCTRL_MASK); ControlReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET); /* * Select the slaves */ ControlReg &= ~XQSPIPS_CR_SSCTRL_MASK; ControlReg |= InstancePtr->SlaveSelect; XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, ControlReg); return XST_SUCCESS;}/*****************************************************************************//**** Gets the current slave select setting for the QSPI device.** @param InstancePtr is a pointer to the XQspiPs instance.** @return The value of the SPI_ss_outN bits in the control register, if* the slave selects are in manual control, or,* The value of SlaveSelect, in XQspiPs instance.** @note None.*******************************************************************************/u8 XQspiPs_GetSlaveSelect(XQspiPs *InstancePtr){ u32 ControlReg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); ControlReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET); if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)) { ControlReg &= XQSPIPS_CR_SSCTRL_MASK; ControlReg >>= XQSPIPS_CR_SSCTRL_SHIFT; } else { ControlReg = InstancePtr->SlaveSelect; } return ((u8) ControlReg);}/*****************************************************************************//**** Sets the status callback function, the status handler, which the driver
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -