Jump to content
  • 0

arty microblaze quad spi


Nystflame

Question

Hello,

I'm having some issues with multiple (16bit) transactions while holding slave select low. I'm using the example master polling spi code from the xilinx SDK, and have manual slave select working where it holds the SS line low while performing the multiple transactions, and once finish it goes high again.  My issue is that i'm trying to make a simple slave which can write to a register continuously if it receives a write command from the master, and then if a read command is sent from the master, the slave will send back whatever is in the designated register requested by the master.  Is the data transmit register also a double buffer? My main objectve is to receive the read command, and start transferring the data on the next group of SCK pulses but right now it seems to be delayed by two transactions.

 

The image attached shows more of what i'm trying to accomplish. the high bit of the 16 bits is a read/write(1 is write, 0 is read) command, and the lower bits are a register address. so the final result of the first 3 transactions should result in register 5 having the value (0x8009), which it does, but when the next transfer happens, the 0x0005 command should be indicating a read of register 5 and output on the miso line 0x8009 on the 2nd transaction (i.e. when MOSI is 0x0007 i want MISO to have 0x8009).

Also this is my current code:


/***************************** Include Files **********************************/

#include "xparameters.h"
#include "xstatus.h"
#include "xspi_l.h"
#include "xil_printf.h"

/************************** Constant Definitions ******************************/

/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define SPI_BASEADDR        XPAR_SPI_0_BASEADDR

/**************************** Type Definitions ********************************/


/***************** Macros (Inline Functions) Definitions **********************/


/************************** Function Prototypes *******************************/


/************************** Variable Definitions ******************************/


/*
 *  This is the size of the buffer to be transmitted/received in this example.
 */
#define BUFFER_SIZE             16

/*
 * The buffer used for Transmission/Reception of the SPI test data
 */
u16 Buffer[BUFFER_SIZE];

/*
 * This buffer is used to simulate a register bank.
 */
u16 regBank[64];

/******************************************************************************/
/**
* This function is the main function of the SPI Low Level example.
*
* @param    None
*
* @return    XST_SUCCESS to indicate success, else XST_FAILURE to indicate
*        Failure.
*
* @note        None
*
*******************************************************************************/
int main(void)
{
    //int transferCounter = 0;
    u32 BaseAddress = SPI_BASEADDR;
    u16 addressMask = 0;
    u32 StatusReg = 0;
    u32 NumBytesRcvd = 0;
    u32 NumBytesSent = 0;
    u8 addressFlag = 0;
    u16 tester = 0;
    //Enable GIER
    XSpi_WriteReg(BaseAddress, XSP_DGIER_OFFSET, 0x0/*XSP_GINTR_ENABLE_MASK*/);
    for(int i = 0; i < 65; i++){
        regBank = 0xBEEF;
    }
    for(int i = 0; i < BUFFER_SIZE; i++){
        Buffer = 0x0;
    }
    //Configure IPIER
    XSpi_WriteReg(BaseAddress, XSP_IIER_OFFSET, 0x0 /*XSP_INTR_SLAVE_MODE_MASK | XSP_INTR_RX_OVERRUN_MASK | XSP_INTR_RX_FULL_MASK | XSP_INTR_TX_UNDERRUN_MASK | XSP_INTR_TX_EMPTY_MASK | XSP_INTR_SLAVE_MODE_FAULT_MASK | XSP_INTR_MODE_FAULT_MASK*/);

    //Configure SPICR
    XSpi_WriteReg(BaseAddress, XSP_CR_OFFSET, XSP_CR_ENABLE_MASK);
    //Write data to the SPI DTR
    XSpi_WriteReg(BaseAddress, XSP_DTR_OFFSET, 0xDEAD);
    xil_printf("setup registers hi\r\n");

    while(1){
        if(NumBytesRcvd == 4){
            for(int i = 0; i < BUFFER_SIZE; i++){
                xil_printf("buffer: 0x%x        regBank: 0x%x  addressmask: %d\r\n", Buffer, regBank , addressMask);
            }
        }
        NumBytesSent = 0;
        NumBytesRcvd = 0;
        addressMask = 0;
        if((XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) & XSP_SR_SLAVE_MODE_MASK) == 0){
            /*
             * 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++]);
            }
            /*
             * 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(Buffer[0] & 0x8000){
                addressMask = Buffer[0] & 0x00FF;
                regBank[addressMask] = Buffer[0];
            }else{
                addressMask = Buffer[0] & 0x00FF;
                XSpi_WriteReg((BaseAddress), XSP_DTR_OFFSET, regBank[addressMask]);
            }
        }
    }
    for(int i = 0; i < BUFFER_SIZE; i++){
        xil_printf("buffer: 0x%x        regBank: 0x%x  addressmask: %d\r\n", Buffer, regBank , addressMask);
    }
}

Greatly appreciate the help!

Nystflame

Capture.PNG

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

Hi @Nystflame,

I am not readily seeing an issue with your sdk code. To clarify, in your project you are using the quad spi IP core in master mode? If so, we have multiple IP cores that use the quad spi IP here. I would suggest to look at the list of spi pmods on the pmod table here to see which IP cores we have available that use spi. Then i would suggest to look at our driver file as a reference for how we send/receive data.

cheers,

Jon

Link to comment
Share on other sites

1 hour ago, jpeyron said:

Hi @Nystflame,

I am readily seeing an issue with your sdk code. To clarify, in your project you are using the quad spi IP core in master mode? If so, we have multiple IP cores that use the quad spi IP here. I would suggest to look at the list of spi pmods on the pmod table here to see which IP cores we have available that use spi. Then i would suggest to look at our driver file as a reference for how we send/receive data.

cheers,

Jon

@jpeyron ,

I have since followed the steps outlined in the quad spi reference guide, and have had better success with transfers. Also, the core is configured in slave mode.  I do have one main question now though.. Is the data transmit register double buffered? It doesn't say that it is in the IP quad spi reference guide, it only says the receive register is double buffered... It seems though that the transmit register loads two of the 16 bit half words that i'm trying to transfer.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...