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 **********************************/
/*
* 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 ********************************/
/*
* 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);
}
}
Question
Nystflame
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
Link to comment
Share on other sites
4 answers to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.