SCB SPI transmit and receive buffer size

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
BiM_4640481
Level 4
Level 4
25 replies posted 25 sign-ins 10 replies posted

Hello,

In my project I have Toshiba flash connected to PSOC6-43012 via SPI. To read device id of flash, i have 2 transmit 2 bytes command. And device id to be received is 3 bytes. If I use size of transmit buffer as 2 bytes, I am not getting the device id. And if I use the size of transmit buffer equal to that of receive buffer, 3 in this case , we are getting extra bytes in the beginning (extra 0's). I am using low level API's Cy_SCB_SPI_WriteArray() and Cy_SCB_SPI_ReadArray()

Is it mandatory that size of transmit and receive buffer should be equal? Also, can you please tell us the reason behind the extra bytes we are getting?

Thanks,

Binsy M S

0 Likes
1 Solution
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi @BiM_4640481 ,

The issue in your code is you are not waiting till the write transaction is complete before reading the Rx FIFO. Remember that, your CPU is running at 100 Mhz (typically) and the SPI is running at 1 to 8 Mhz (typically). So you need to wait for the transfer to complete by polling the Cy_SCB_SPI_GetSlaveMasterStatus()and check if this CY_SCB_SPI_MASTER_DONE   is set. Only then you can proceed towards reading the RX FIFO.

for example,

 Cy_SCB_SPI_WriteArray(SCB6, txBuffer, sizeof(txBuffer));

 while(Cy_SCB_SPI_GetSlaveMasterStatus() & CY_SCB_SPI_MASTER_DONE == 0);

 /* Write transaction complete, Read the device id*/
 Cy_SCB_SPI_ReadArray(SCB6, rxBuffer, 3);

Looking at the device datasheet, I see the following waveform for reading the device ID:

BragadeeshV_0-1621489761296.png

This aligns to my understanding before. You need to first send two bytes (0x9F, 0xFF) to the slave. You will receive two bytes in MISO. This is don't care and hence you should discard this. After this, you need to send three dummy bytes to the slave ,( assume 0xFF, 0xFF , 0xFF) and then you will receive three bytes which will contain device ID.

example:

uint8_t read_device_id()
{
    uint8_t command_byte[2] = {0x9F, 0xFF} /* 1nd byte: Command; 2nd byte: Dummy byte*/
    uint8_t dummy_packet[3] = {0xFF, 0xFF, 0xFF}; /* Dummy bytes */
    uint8_t rx_buffer[3] = {0};

    Cy_SCB_SPI_WriteArray(SCB6, command_byte, sizeof(command_byte));

    /* Wait till write transaction is complete */
    while (0UL == (Cy_SCB_SPI_GetSlaveMasterStatus(SCB6) & CY_SCB_SPI_MASTER_DONE));
 
    /* The packet that is received while sending command byte can be discarded according to the datasheet */
    Cy_SCB_SPI_ClearRxFifo(SCB6);

    /* Now to receive 3 bytes, you need to send 3 dummy bytes */
    Cy_SCB_SPI_WriteArray(SCB6, dummy_packet, sizeof(dummy_packet));

    /* Wait till write transaction is complete */
    while (0UL == (Cy_SCB_SPI_GetSlaveMasterStatus(SCB6) & CY_SCB_SPI_MASTER_DONE));

    /* Read 3 bytes */
    Cy_SCB_SPI_ReadArray(SCB6, rx_buffer, 3);

    return rx_buffer[1]; /* As per datasheet, 2nd byte contains device ID */
}

Please let us know if this works for you.

Regards,
Bragadeesh

View solution in original post

4 Replies
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi @BiM_4640481 ,

Can you share with us the datasheet of the device you are interfacing with? 

In SPI Communication, the size of the transmit buffer and the receiver buffer will always be the same. For every byte pushed out of the MOSI, there will be a byte received in the MISO line. 

Please let me know if my understanding of your transaction is correct. You need to a send two bytes command to the SPI slave. At the end of this transaction, you would have received two bytes in the RX FIFO. These two bytes doesn't contain the device ID. Now, after this, to receive the 3 bytes (device ID), you need to transmit 3 dummy bytes (this is the requirement of SPI communication). 

In PSoC 6 SPI, writing to the TX FIFO will cause the CS line to go low and the SCLK will be toggled. The CS line will remain low as long as there are bytes in the TX FIFO. The CS line is automatically de-asserted once TX FIFO becomes empty. Therefore, to receive bytes from slave, you need to load dummy bytes in the TX FIFO (no of dummy elements = no of bytes you want to receive), so that CS line is asserted and the SCLK is provided to the slave so that MISO can be pushed out of the slave.

Please let us know if this works for you.

Regards,
Bragadeesh
0 Likes
lock attach
Attachments are accessible only for community members.

Hello Bragadeesh,

Thanks a lot for your detailed reply.

I am attaching the datasheet here

This is how we are sending the data:

Following is for chip select(P11_1) and flash hold pin(P12_3)

Cy_GPIO_Pin_FastInit(P11_1_PORT, P11_1_NUM, CY_GPIO_DM_STRONG_IN_OFF, 1UL, HSIOM_SEL_GPIO);
Cy_GPIO_Write(P11_1_PORT, P11_1_NUM, 0);
Cy_GPIO_Pin_FastInit(P12_3_PORT, P12_3_NUM, CY_GPIO_DM_STRONG_IN_OFF, 1UL, HSIOM_SEL_GPIO); //Flash_Hold
Cy_GPIO_Write(P12_3_PORT, P12_3_NUM, 1);

uint8_t txBuffer[3];
uint8_t rxBuffer[3];

txBuffer[0] = 0x9F;
txBuffer[1] = 0xFF;   //dummy byte
txBuffer[2] = 0xFF;  // dummy byte

while(1)

{

int ret = Cy_SCB_SPI_WriteArray(SCB6, txBuffer, sizeof(txBuffer));
BOOT_LOG_INF("Cy_SCB_SPI_Write returned : %d\n", ret);

/* Read the device id*/
Cy_SCB_SPI_ReadArray(SCB6, rxBuffer, 3);

}

When we read it this way, we are getting first three bytes as 0, 0, 0

And when we run this in a loop for next transmit and receive, we are getting the device id.

Also, we are driving chip select pin as GPIO (P11_1) and controlling it in software.

 

Thanks,

Binsy M S

0 Likes
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi @BiM_4640481 ,

The issue in your code is you are not waiting till the write transaction is complete before reading the Rx FIFO. Remember that, your CPU is running at 100 Mhz (typically) and the SPI is running at 1 to 8 Mhz (typically). So you need to wait for the transfer to complete by polling the Cy_SCB_SPI_GetSlaveMasterStatus()and check if this CY_SCB_SPI_MASTER_DONE   is set. Only then you can proceed towards reading the RX FIFO.

for example,

 Cy_SCB_SPI_WriteArray(SCB6, txBuffer, sizeof(txBuffer));

 while(Cy_SCB_SPI_GetSlaveMasterStatus() & CY_SCB_SPI_MASTER_DONE == 0);

 /* Write transaction complete, Read the device id*/
 Cy_SCB_SPI_ReadArray(SCB6, rxBuffer, 3);

Looking at the device datasheet, I see the following waveform for reading the device ID:

BragadeeshV_0-1621489761296.png

This aligns to my understanding before. You need to first send two bytes (0x9F, 0xFF) to the slave. You will receive two bytes in MISO. This is don't care and hence you should discard this. After this, you need to send three dummy bytes to the slave ,( assume 0xFF, 0xFF , 0xFF) and then you will receive three bytes which will contain device ID.

example:

uint8_t read_device_id()
{
    uint8_t command_byte[2] = {0x9F, 0xFF} /* 1nd byte: Command; 2nd byte: Dummy byte*/
    uint8_t dummy_packet[3] = {0xFF, 0xFF, 0xFF}; /* Dummy bytes */
    uint8_t rx_buffer[3] = {0};

    Cy_SCB_SPI_WriteArray(SCB6, command_byte, sizeof(command_byte));

    /* Wait till write transaction is complete */
    while (0UL == (Cy_SCB_SPI_GetSlaveMasterStatus(SCB6) & CY_SCB_SPI_MASTER_DONE));
 
    /* The packet that is received while sending command byte can be discarded according to the datasheet */
    Cy_SCB_SPI_ClearRxFifo(SCB6);

    /* Now to receive 3 bytes, you need to send 3 dummy bytes */
    Cy_SCB_SPI_WriteArray(SCB6, dummy_packet, sizeof(dummy_packet));

    /* Wait till write transaction is complete */
    while (0UL == (Cy_SCB_SPI_GetSlaveMasterStatus(SCB6) & CY_SCB_SPI_MASTER_DONE));

    /* Read 3 bytes */
    Cy_SCB_SPI_ReadArray(SCB6, rx_buffer, 3);

    return rx_buffer[1]; /* As per datasheet, 2nd byte contains device ID */
}

Please let us know if this works for you.

Regards,
Bragadeesh

Thank you so much for the detailed reply with solution. It solved the issue