/** * * Resets the SPI device by writing to the Software Reset register. Reset must * only be called after the driver has been initialized. The configuration of the * device after reset is the same as its configuration after initialization. * Refer to the XSpi_Initialize function for more details. This is a hard reset * of the device. Any data transfer that is in progress is aborted. * * The upper layer software is responsible for re-configuring (if necessary) * and restarting the SPI device after the reset. * * @param InstancePtr is a pointer to the XSpi instance to be worked on. * * @return None. * * @note None. * ******************************************************************************/ void XSpi_Reset(XSpi *InstancePtr) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Abort any transfer that is in progress. */ XSpi_Abort(InstancePtr); /* * Reset any values that are not reset by the hardware reset such that * the software state matches the hardware device. */ InstancePtr->IsStarted = 0; InstancePtr->SlaveSelectReg = InstancePtr->SlaveSelectMask; /* * Reset the device. */ XSpi_WriteReg(InstancePtr->BaseAddr, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK); }
/* * * Runs an internal loopback test on the SPI device. This is done as a master * with a enough data to fill the FIFOs if FIFOs are present. If the device is * configured as a slave-only, this function returns successfully even though * no loopback test is performed. * * This function does not restore the device context after performing the test * as it assumes the device will be reset after the call. * * @param InstancePtr is a pointer to the XSpi instance to be worked on. * * @return * - XST_SUCCESS if loopback was performed successfully or not * performed at all if device is slave-only. * - XST_LOOPBACK_ERROR if loopback failed. * * @note None. * ******************************************************************************/ static int LoopbackTest(XSpi *InstancePtr) { u32 StatusReg; u32 ControlReg; u32 Index; u32 Data; u32 RxData; u32 NumSent = 0; u32 NumRecvd = 0; u8 DataWidth; /* * Cannot run as a slave-only because we need to be master in order to * initiate a transfer. Still return success, though. */ if (InstancePtr->SlaveOnly) { return XST_SUCCESS; } /* * Setup the control register to enable master mode and the loopback so * that data can be sent and received. */ ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_LOOPBACK_MASK | XSP_CR_MASTER_MODE_MASK); /* * We do not need interrupts for this loopback test. */ XSpi_IntrGlobalDisable(InstancePtr); DataWidth = InstancePtr->DataWidth; /* * Send data up to the maximum size of the transmit register, which is * one byte without FIFOs. We send data 4 times just to exercise the * device through more than one iteration. */ for (Index = 0; Index < 4; Index++) { Data = 0; /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = XSP_WORD_TESTBYTE; } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data + Index); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK); /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ do { StatusReg = XSpi_IntrGetStatus(InstancePtr); } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * Receive and verify the data just transmitted. */ StatusReg = XSpi_GetStatusReg(InstancePtr); while ((StatusReg & XSP_SR_RX_EMPTY_MASK) == 0) { RxData = XSpi_ReadReg(InstancePtr->BaseAddr, XSP_DRR_OFFSET); if (DataWidth == XSP_DATAWIDTH_BYTE) { if((u8)RxData != Index) { return XST_LOOPBACK_ERROR; } } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { if((u16)RxData != (u16)(Index + XSP_HALF_WORD_TESTBYTE)) { return XST_LOOPBACK_ERROR; } } else if (DataWidth == XSP_DATAWIDTH_WORD) { if(RxData != (u32)(Index + XSP_WORD_TESTBYTE)) { return XST_LOOPBACK_ERROR; } } NumRecvd += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); } /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); } /* * One final check to make sure the total number of bytes sent equals * the total number of bytes received. */ if (NumSent != NumRecvd) { return XST_LOOPBACK_ERROR; } return XST_SUCCESS; }
/* * Change LO frequency in integer mode * frequency must be multiple of 40 (MHz) */ int trf3795changeFreqInt(XSpi *InstancePtr, u32 freq) { u32 StatusReg; u32 ControlReg; u32 Index; u32 Delay; u32 Data; u32 NumSent = 0; u32 NumRecvd = 0; u32 RxData[] = {0,0,0}; u32 reg1Val, reg2Val, reg6Val; u8 DataWidth; u8 j; int ctr; u8 loDivSel, loDiv; u8 pllDiv; u8 pllDivSel; u8 prscSel; u16 rDiv; u16 nInt; // Calculate parameter and register values freq = freq/2; // Output frequency is doubled if(freq>2400) { loDiv = 1; loDivSel = 0; } else if(freq>1200) { loDiv = 2; loDivSel = 1; } else if(freq>600) { loDiv = 4; loDivSel = 2; } else if(freq>300) { loDiv = 8; loDivSel = 3; } pllDiv = (u8)ceil((double)loDiv*freq/3000.0); //xil_printf("Pll Div %d\r\n", pllDiv); rDiv = 1; nInt = (u16)(loDiv*freq*rDiv/(10*pllDiv)); if(pllDiv==1) pllDivSel = 0; else if(pllDiv==2) pllDivSel = 1; else if(pllDiv==4) pllDivSel = 2; else { xil_printf("Invalid PLL_DIV!\r\n"); return XST_FAILURE; } if(nInt>=72) prscSel = 1; else prscSel = 0; //xil_printf("NInt %d\r\n", nInt); //xil_printf("prscSel %d\r\n", prscSel); //xil_printf("loDiv %d\r\n", loDiv); reg1Val = XSP_REG1_WRITE_CF + (rDiv<<5); reg2Val = XSP_REG2_WRITE_CF + (nInt<<5) + (pllDivSel<<21) + (prscSel<<23); reg6Val = XSP_REG6_WRITE_CF + (loDivSel<<23); u32 write_trf_register[] = {reg1Val,reg6Val,reg2Val}; u32 reg_list = {1,2,6}; //xil_printf("reg1: %x", reg1Val); //xil_printf("reg2: %x", reg2Val); //xil_printf("reg6: %x", reg6Val); /* * Setup the control reogister to enable master mode and * to send least significant bit 1st */ ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_MASTER_MODE_MASK | XSP_CR_LSB_FIRST); //xil_printf("ctrl reg setup done\r\n"); /* * Set the slave select zero bit to active - low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); /* * We do not need interrupts for now */ XSpi_IntrGlobalDisable(InstancePtr); DataWidth = InstancePtr->DataWidth; /*****************************************************************************/ /* * perform a write to a TRF3765 register */ for (Index = 0; Index < 3; Index++) { // for loop write to three registers Data = 0; xil_printf("start transfer %d\r\n", Index); /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); //xil_printf("got status reg\r\n"); // while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { // no loop, do just a single transfer for now if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = write_trf_register[Index]; // choose the register index 0 to 7 ************ //xil_printf("selected register \r\n"); } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); //xil_printf("wrote data \r\n"); NumSent += (DataWidth >> 3); //xil_printf("Numsent %d\r\n", NumSent); StatusReg = XSpi_GetStatusReg(InstancePtr); //xil_printf("status reg %d \r\n", StatusReg); // } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK); /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ //xil_printf("start for loop\r\n"); //xil_printf("status reg %d\r\n", XSpi_IntrGetStatus(InstancePtr)); ctr = 0; do { StatusReg = XSpi_IntrGetStatus(InstancePtr); if(ctr > SPI_TIMEOUT) break; ctr++; } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); //xil_printf("done with while loop \r\n"); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * To create a latch enable pulse and extra read clock pulse, * set the slave select one SS(1) bit low */ XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFD); // creates read pulse and clock for (Delay = 0; Delay < 10; Delay++) // more delay makes wider pulses {} XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes read pulse and clock /* * To create a latch enable pulse, * set the slave select one SS(0) bit low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); // drives the latch enable // for (Delay = 0; Delay < 10; Delay++) // more delay makes pulse wider // {} // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes the latch enable /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); //xil_printf("Done transfer %d\r\n", Index); } XSpi_Reset(InstancePtr); return XST_SUCCESS; }
/* * Enables the fractional mode of the LO * LO must be initialized first */ int trf3795EnableInt(XSpi *InstancePtr) { u32 StatusReg; u32 ControlReg; u32 Index; u32 Delay; u32 Data; u32 NumSent = 0; u32 NumRecvd = 0; u32 RxData[] = {0,0,0}; u8 DataWidth; u8 j; int ctr; u32 write_trf_register[] = {XSP_REG0_WRITE,XSP_REG1_WRITE,XSP_REG2_WRITE,XSP_REG3_WRITE, XSP_REG4_WRITE,XSP_REG5_WRITE,XSP_REG6_WRITE,XSP_REG7_WRITE}; /* * Setup the control reogister to enable master mode and * to send least significant bit 1st */ ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_MASTER_MODE_MASK | XSP_CR_LSB_FIRST); /* * Set the slave select zero bit to active - low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); /* * We do not need interrupts for now */ XSpi_IntrGlobalDisable(InstancePtr); DataWidth = InstancePtr->DataWidth; /*****************************************************************************/ /* * perform a write to a TRF3765 register */ for (Index = 0; Index < 8; Index++) { // for loop write to all eight registers Data = 0; /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); // while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { // no loop, do just a single transfer for now if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = write_trf_register[Index]; // choose the register index 0 to 7 ************ } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); // } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK); /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ do { StatusReg = XSpi_IntrGetStatus(InstancePtr); if(ctr > SPI_TIMEOUT) break; ctr++; } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * To create a latch enable pulse and extra read clock pulse, * set the slave select one SS(1) bit low */ XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFD); // creates read pulse and clock for (Delay = 0; Delay < 10; Delay++) // more delay makes wider pulses {} XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes read pulse and clock /* * To create a latch enable pulse, * set the slave select one SS(0) bit low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); // drives the latch enable // for (Delay = 0; Delay < 10; Delay++) // more delay makes pulse wider // {} // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes the latch enable /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); } XSpi_Reset(InstancePtr); return XST_SUCCESS; }
/* Write to and read back the RF board TRF3795 * * ******************************************************************************/ static int trf3795WriteAndRead(XSpi *InstancePtr) { u32 StatusReg; u32 ControlReg; u32 Index; u32 Delay; u32 Data; u32 NumSent = 0; u32 NumRecvd = 0; u32 RxData[] = {0,0,0}; u8 DataWidth; u8 j; int ctr = 0; u32 write_trf_register[] = {XSP_REG0_WRITE,XSP_REG1_WRITE,XSP_REG2_WRITE_ENC,XSP_REG3_WRITE, XSP_REG4_WRITE,XSP_REG5_WRITE,XSP_REG6_WRITE, XSP_REG7_WRITE}; u32 read_trf_register[] = {XSP_REG0_READBACK,XSP_REG1_READBACK,XSP_REG2_READBACK,XSP_REG3_READBACK, XSP_REG4_READBACK,XSP_REG5_READBACK,XSP_REG6_READBACK,XSP_REG7_READBACK,XSP_REG7_READBACK}; /* * Setup the control register to enable master mode and * to send least significant bit 1st */ ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_MASTER_MODE_MASK | XSP_CR_LSB_FIRST); /* * Set the slave select zero bit to active - low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); /* * We do not need interrupts for now */ XSpi_IntrGlobalDisable(InstancePtr); DataWidth = InstancePtr->DataWidth; /*****************************************************************************/ /* * perform a write to a TRF3765 register */ for (Index = 0; Index < 8; Index++) { // for loop write to all eight registers Data = 0; /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); // while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { // no loop, do just a single transfer for now if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = write_trf_register[Index]; // choose the register index 0 to 7 ************ } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); // } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK); /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ //xil_printf("status reg %d \r\n", StatusReg); //xil_printf("intr status reg %d \r\n", XSpi_IntrGetStatus(InstancePtr)); ctr = 0; do { StatusReg = XSpi_IntrGetStatus(InstancePtr); if(ctr > SPI_TIMEOUT) break; ctr++; } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * To create a latch enable pulse and extra read clock pulse, * set the slave select one SS(1) bit low */ XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFD); // creates read pulse and clock for (Delay = 0; Delay < 10; Delay++) // more delay makes wider pulses {} XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes read pulse and clock /* * To create a latch enable pulse, * set the slave select one SS(0) bit low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); // drives the latch enable // for (Delay = 0; Delay < 10; Delay++) // more delay makes pulse wider // {} // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes the latch enable /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); // } // end of the for loop /*****************************************************************************/ /* * To Read-back from the Internal Register Banks, Register 0 must be programmed * with a specific command that sets the TRF3765 into read-back mode and * specifies the register to be read */ // for (Index = 0; Index < 1; Index++) { // Data = 0; /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); // while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { // do just a single transfer for now if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = read_trf_register[Index]; // index of the register to readback here ********************* } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); // } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK); // | XSP_CR_CLK_PHASE_MASK); /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ ctr = 0; do { StatusReg = XSpi_IntrGetStatus(InstancePtr); if(ctr > SPI_TIMEOUT) break; ctr++; } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); for (Delay = 0; Delay < 10; Delay++) // add delay {} /* * To create a latch enable pulse and extra read clock pulse, * set the slave select one SS(1) bit low */ XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFD); // creates read pulse and clock for (Delay = 0; Delay < 10; Delay++) // more delay makes wider pulses {} XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes read pulse and clock for (Delay = 0; Delay < 10; Delay++) // add delay {} /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); // } // end of the for loop /* ************* Now read-back the specific register ********************************* */ // for (Index = 0; Index < 1; Index++) { // Data = 0; /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); // while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { // do just a single transfer for now if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = XSP_ZERO_WRITE; // just leave the data bits at zero during read-back } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data + Index); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); // } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK | XSP_CR_CLK_PHASE_MASK); // clock data in on the second edge (falling) /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ ctr = 0; do { StatusReg = XSpi_IntrGetStatus(InstancePtr); if(ctr > SPI_TIMEOUT) break; ctr++; } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * Receive and verify the data just transmitted. */ StatusReg = XSpi_GetStatusReg(InstancePtr); while ((StatusReg & XSP_SR_RX_EMPTY_MASK) == 0) { for (j = 0; j < 3; j++) { RxData[j] = XSpi_ReadReg(InstancePtr->BaseAddr, XSP_DRR_OFFSET); NumRecvd += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); } xil_printf("\r%08x\n\r", RxData[2]); } /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); } // end of the for loop /* * One final check to make sure the total number of bytes sent equals * the total number of bytes received. */ // if (NumSent != NumRecvd) { // return XST_LOOPBACK_ERROR; // } xil_printf("\n\rTRF3765 Register Access Done\n\r"); return XST_SUCCESS; }
int trf3795ReadBackRegs(XSpi *InstancePtr) { u32 StatusReg; u32 ControlReg; u32 Index; u32 Delay; u32 Data; u32 NumSent = 0; u32 NumRecvd = 0; u32 RxData[] = {0,0,0}; u8 DataWidth; u8 j; u32 read_trf_register[] = {XSP_REG0_READBACK,XSP_REG1_READBACK,XSP_REG2_READBACK,XSP_REG3_READBACK, XSP_REG4_READBACK,XSP_REG5_READBACK,XSP_REG6_READBACK,XSP_REG7_READBACK}; ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_MASTER_MODE_MASK | XSP_CR_LSB_FIRST); xil_printf("ctrl reg setup done\r\n"); /* * Set the slave select zero bit to active - low */ // XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFE); /* * We do not need interrupts for now */ XSpi_IntrGlobalDisable(InstancePtr); DataWidth = InstancePtr->DataWidth; StatusReg = XSpi_GetStatusReg(InstancePtr); for(Index=0; Index<8; Index++) { if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = read_trf_register[Index]; // index of the register to readback here ********************* } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK); // | XSP_CR_CLK_PHASE_MASK); /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ //xil_printf("enter first tx while loop \r\n"); do { StatusReg = XSpi_IntrGetStatus(InstancePtr); } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); for (Delay = 0; Delay < 10; Delay++) // add delay {} /* * To create a latch enable pulse and extra read clock pulse, * set the slave select one SS(1) bit low */ XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFD); // creates read pulse and clock for (Delay = 0; Delay < 10; Delay++) // more delay makes wider pulses {} XSpi_SetSlaveSelectReg(InstancePtr, 0xFFFF); // removes read pulse and clock for (Delay = 0; Delay < 10; Delay++) // add delay {} /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); // } // end of the for loop /* ************* Now read-back the specific register ********************************* */ // for (Index = 0; Index < 1; Index++) { // Data = 0; /* * Fill the transmit register. */ StatusReg = XSpi_GetStatusReg(InstancePtr); // while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) { // do just a single transfer for now if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = 0; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = XSP_HALF_WORD_TESTBYTE; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = XSP_ZERO_WRITE; // just leave the data bits at zero during read-back } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data + Index); NumSent += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); // } /* * Start the transfer by not inhibiting the transmitter and * enabling the device. */ ControlReg = XSpi_GetControlReg(InstancePtr) & (~XSP_CR_TRANS_INHIBIT_MASK); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_ENABLE_MASK | XSP_CR_CLK_PHASE_MASK); // clock data in on the second edge (falling) /* * Wait for the transfer to be done by polling the transmit * empty status bit. */ //xil_printf("Enter tx empty while loop\r\n"); do { StatusReg = XSpi_IntrGetStatus(InstancePtr); } while ((StatusReg & XSP_INTR_TX_EMPTY_MASK) == 0); XSpi_IntrClear(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * Receive and verify the data just transmitted. */ StatusReg = XSpi_GetStatusReg(InstancePtr); //xil_printf("Enter rx empty while loop\r\n"); while ((StatusReg & XSP_SR_RX_EMPTY_MASK) == 0) { for (j = 0; j < 3; j++) { RxData[j] = XSpi_ReadReg(InstancePtr->BaseAddr, XSP_DRR_OFFSET); NumRecvd += (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); } xil_printf("\r%08x\n\r", RxData[2]); } /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter and disabling the device. */ ControlReg |= XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr , ControlReg & ~ XSP_CR_ENABLE_MASK); } // end of the for loop xil_printf("\n\rTRF3765 Register Access Done\n\r"); return XST_SUCCESS; }
/** * * This function does a simple loopback test within an SPI device. * * @param BaseAddress is the BaseAddress of the SPI device * * @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful * * @note None * *******************************************************************************/ int XSpi_LowLevelExample(u32 BaseAddress) { u32 Control; int NumBytesSent = 0; int NumBytesRcvd = 0; u32 Count; /* * Set up the device in loopback mode and enable master mode. */ Control = XSpi_ReadReg(BaseAddress, XSP_CR_OFFSET); Control |= (XSP_CR_LOOPBACK_MASK | XSP_CR_MASTER_MODE_MASK); XSpi_WriteReg(BaseAddress, XSP_CR_OFFSET, Control); /* * Initialize the buffer with some data. */ for (Count = 0; Count < BUFFER_SIZE; Count++) { Buffer[Count] = Count; } /* * Fill up the transmitter with data, assuming the receiver can hold * the same amount of data. */ while ((XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) & XSP_SR_TX_FULL_MASK) == 0) { XSpi_WriteReg((BaseAddress), XSP_DTR_OFFSET, Buffer[NumBytesSent++]); } /* * Enable the device. */ Control = XSpi_ReadReg(BaseAddress, XSP_CR_OFFSET); Control |= XSP_CR_ENABLE_MASK; Control &= ~XSP_CR_TRANS_INHIBIT_MASK; XSpi_WriteReg(BaseAddress, XSP_CR_OFFSET, Control); /* * Initialize the buffer with zeroes so that it can be used to receive * data. */ for (Count = 0; Count < BUFFER_SIZE; Count++) { Buffer[Count] = 0x0; } /* * Wait for the transmit FIFO to transition to empty before checking * the receive FIFO, this prevents a fast processor from seeing the * receive FIFO as empty */ while (!(XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) & XSP_SR_TX_EMPTY_MASK)); /* * Transmitter is full, now receive the data just looped back until * the receiver is empty. */ while ((XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) & XSP_SR_RX_EMPTY_MASK) == 0) { Buffer[NumBytesRcvd++] = XSpi_ReadReg((BaseAddress), XSP_DRR_OFFSET); } /* * If no data was sent or the data that was sent was not received, * then return an error */ if ((NumBytesSent != NumBytesRcvd) || (NumBytesSent == 0)) { return XST_FAILURE; } return XST_SUCCESS; }
/** * * Transfers the specified data on the SPI bus. If the SPI device is configured * to be a master, this function initiates bus communication and sends/receives * the data to/from the selected SPI slave. If the SPI device is configured to * be a slave, this function prepares the data to be sent/received when selected * by a master. For every byte sent, a byte is received. * * This function/driver operates in interrupt mode and polled mode. * - In interrupt mode this function is non-blocking and the transfer is * initiated by this function and completed by the interrupt service routine. * - In polled mode this function is blocking and the control exits this * function only after all the requested data is transferred. * * 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> * XSpi_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount) * The caller wishes to send and receive, and provides two different * buffers for send and receive. * * XSpi_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. * * XSpi_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. * * XSpi_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> * In interrupt mode, though this function takes a buffer as an argument, the * driver can only transfer a limited number of bytes at time. It transfers only * one byte at a time if there are no FIFOs, or it can transfer the number of * bytes up to the size of the FIFO if FIFOs exist. * - In interrupt mode a call to this function only starts the transfer, the * subsequent transfer 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. * - In polled mode this function is blocking and the control exits this * function only after all the requested data is transferred. * * As a master, the SetSlaveSelect function must be called prior to this * function. * * @param InstancePtr is a pointer to the XSpi instance to be worked on. * @param SendBufPtr is a pointer to a buffer of data which is to be sent. * This buffer must not be NULL. * @param RecvBufPtr is a pointer to a buffer which will be filled with * received data. This argument can be NULL if the caller does not * wish to receive data. * @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 * driver for transfer. Otherwise, returns: * - XST_DEVICE_IS_STOPPED if the device must be started before * transferring data. * - XST_DEVICE_BUSY indicates that a data transfer is already in * progress. This is determined by the driver. * - XST_SPI_NO_SLAVE indicates the device is configured as a * master and a slave has not yet been selected. * * @notes * * 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. * ******************************************************************************/ int XSpi_Transfer(XSpi *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, unsigned int ByteCount) { u32 ControlReg; u32 GlobalIntrReg; u32 StatusReg; u32 Data = 0; u8 DataWidth; /* * 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); if (InstancePtr->IsStarted != XIL_COMPONENT_IS_STARTED) { return XST_DEVICE_IS_STOPPED; } /* * Make sure there is not a transfer already in progress. No need to * worry about a critical section here. Even if the Isr changes the bus * flag just after we read it, a busy error is returned and the caller * can retry when it gets the status handler callback indicating the * transfer is done. */ if (InstancePtr->IsBusy) { return XST_DEVICE_BUSY; } /* * Save the Global Interrupt Enable Register. */ GlobalIntrReg = XSpi_IsIntrGlobalEnabled(InstancePtr); /* * Enter a critical section from here to the end of the function since * state is modified, an interrupt is enabled, and the control register * is modified (r/m/w). */ XSpi_IntrGlobalDisable(InstancePtr); ControlReg = XSpi_GetControlReg(InstancePtr); /* * If configured as a master, be sure there is a slave select bit set * in the slave select register. If no slaves have been selected, the * value of the register will equal the mask. When the device is in * loopback mode, however, no slave selects need be set. */ if (ControlReg & XSP_CR_MASTER_MODE_MASK) { if ((ControlReg & XSP_CR_LOOPBACK_MASK) == 0) { if (InstancePtr->SlaveSelectReg == InstancePtr->SlaveSelectMask) { if (GlobalIntrReg == TRUE) { /* Interrupt Mode of operation */ XSpi_IntrGlobalEnable(InstancePtr); } return XST_SPI_NO_SLAVE; } } } /* * Set the slave select register to select the device on the SPI before * starting the transfer of data. */ XSpi_SetSlaveSelectReg(InstancePtr, InstancePtr->SlaveSelectReg); /* * Set the busy flag, which will be cleared when the transfer * is completely done. */ InstancePtr->IsBusy = TRUE; /* * Set up buffer pointers. */ InstancePtr->SendBufferPtr = SendBufPtr; InstancePtr->RecvBufferPtr = RecvBufPtr; InstancePtr->RequestedBytes = ByteCount; InstancePtr->RemainingBytes = ByteCount; DataWidth = InstancePtr->DataWidth; /* * Fill the DTR/FIFO with as many bytes as it will take (or as many as * we have to send). We use the tx full status bit to know if the device * can take more data. By doing this, the driver does not need to know * the size of the FIFO or that there even is a FIFO. The downside is * that the status register must be read each loop iteration. */ StatusReg = XSpi_GetStatusReg(InstancePtr); while (((StatusReg & XSP_SR_TX_FULL_MASK) == 0) && (InstancePtr->RemainingBytes > 0)) { if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ Data = *InstancePtr->SendBufferPtr; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word (16 bit). */ Data = *(u16 *)InstancePtr->SendBufferPtr; } else if (DataWidth == XSP_DATAWIDTH_WORD){ /* * Data Transfer Width is Word (32 bit). */ Data = *(u32 *)InstancePtr->SendBufferPtr; } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); InstancePtr->SendBufferPtr += (DataWidth >> 3); InstancePtr->RemainingBytes -= (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); } /* * Start the transfer by no longer inhibiting the transmitter and * enabling the device. For a master, this will in fact start the * transfer, but for a slave it only prepares the device for a transfer * that must be initiated by a master. */ ControlReg = XSpi_GetControlReg(InstancePtr); ControlReg &= ~XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr, ControlReg); /* * If the interrupts are enabled as indicated by Global Interrupt * Enable Register, then enable the transmit empty interrupt to operate * in Interrupt mode of operation. */ if (GlobalIntrReg == TRUE) { /* Interrupt Mode of operation */ /* * Enable the transmit empty interrupt, which we use to * determine progress on the transmission. */ XSpi_IntrEnable(InstancePtr, XSP_INTR_TX_EMPTY_MASK); /* * End critical section. */ XSpi_IntrGlobalEnable(InstancePtr); } else { /* Polled mode of operation */ /* * If interrupts are not enabled, poll the status register to * Transmit/Receive SPI data. */ while(ByteCount > 0) { /* * Wait for the transfer to be done by polling the * Transmit empty status bit */ do { StatusReg = XSpi_GetStatusReg(InstancePtr); } while ((StatusReg & XSP_SR_TX_EMPTY_MASK) == 0); /* * A transmit has just completed. Process received data * and check for more data to transmit. Always inhibit * the transmitter while the transmit register/FIFO is * being filled, or make sure it is stopped if we're * done. */ ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_TRANS_INHIBIT_MASK); /* * 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). */ StatusReg = XSpi_GetStatusReg(InstancePtr); while ((StatusReg & XSP_SR_RX_EMPTY_MASK) == 0) { Data = XSpi_ReadReg(InstancePtr->BaseAddr, XSP_DRR_OFFSET); if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte (8 bit). */ if(InstancePtr->RecvBufferPtr != NULL) { *InstancePtr->RecvBufferPtr++ = (u8)Data; } } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half Word * (16 bit). */ if (InstancePtr->RecvBufferPtr != NULL){ *(u16 *)InstancePtr->RecvBufferPtr = (u16)Data; InstancePtr->RecvBufferPtr += 2; } } else if (DataWidth == XSP_DATAWIDTH_WORD) { /* * Data Transfer Width is Word (32 bit). */ if (InstancePtr->RecvBufferPtr != NULL){ *(u32 *)InstancePtr->RecvBufferPtr = Data; InstancePtr->RecvBufferPtr += 4; } } InstancePtr->Stats.BytesTransferred += (DataWidth >> 3); ByteCount -= (DataWidth >> 3); StatusReg = XSpi_GetStatusReg(InstancePtr); } if (InstancePtr->RemainingBytes > 0) { /* * Fill the DTR/FIFO with as many bytes as it * will take (or as many as we have to send). * We use the Tx full status bit to know if the * device can take more data. * By doing this, the driver does not need to * know the size of the FIFO or that there even * is a FIFO. * The downside is that the status must be read * each loop iteration. */ StatusReg = XSpi_GetStatusReg(InstancePtr); while(((StatusReg & XSP_SR_TX_FULL_MASK)== 0) && (InstancePtr->RemainingBytes > 0)) { if (DataWidth == XSP_DATAWIDTH_BYTE) { /* * Data Transfer Width is Byte * (8 bit). */ Data = *InstancePtr-> SendBufferPtr; } else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) { /* * Data Transfer Width is Half * Word (16 bit). */ Data = *(u16 *)InstancePtr-> SendBufferPtr; } else if (DataWidth == XSP_DATAWIDTH_WORD) { /* * Data Transfer Width is Word * (32 bit). */ Data = *(u32 *)InstancePtr-> SendBufferPtr; } XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET, Data); InstancePtr->SendBufferPtr += (DataWidth >> 3); InstancePtr->RemainingBytes -= (DataWidth >> 3); StatusReg = XSpi_GetStatusReg( InstancePtr); } /* * Start the transfer by not inhibiting the * transmitter any longer. */ ControlReg = XSpi_GetControlReg(InstancePtr); ControlReg &= ~XSP_CR_TRANS_INHIBIT_MASK; XSpi_SetControlReg(InstancePtr, ControlReg); } } /* * Stop the transfer (hold off automatic sending) by inhibiting * the transmitter. */ ControlReg = XSpi_GetControlReg(InstancePtr); XSpi_SetControlReg(InstancePtr, ControlReg | XSP_CR_TRANS_INHIBIT_MASK); /* * Select the slave on the SPI bus when the transfer is * complete, this is necessary for some SPI devices, * such as serial EEPROMs work correctly as chip enable * may be connected to slave select */ XSpi_SetSlaveSelectReg(InstancePtr, InstancePtr->SlaveSelectMask); InstancePtr->IsBusy = FALSE; }