PSoC4 SPI master RX interrupt setting with API

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

cross mob
YoIs_1298666
Level 5
Level 5
250 sign-ins 100 replies posted 100 sign-ins

Hello,

I am trying the SPI master RX interrupt setting with API.

At first, RX interrupt is not enabled.

pastedImage_0.pngpastedImage_3.png

Then, in the main  I would like to enable "RX FIFO full(SPIMH_INTR_RX_FULL)" interrupt after sending the Opcode + 15-bit Address data like below.

pastedImage_2.png

I could recieve Data when "RX_NOT_EMPTY(SPIMH_INTR_RX_NOT_EMPTY)" was set. but in case of "RX FIFO full" I won't recieve.

Opcode and Address were sent and the interrupt was occurred. But there is no data in the RX FIFO. Maybe the data receive setting was not allowed.

What is wrong?

------------------------------  main.c  ------------------------------

    Pin_FRAMCS_Write(0);

    // Send F-RAM Read Command

    SPIMH_SpiUartWriteTxData(FRAM_SRAM_READ_CMD);

    // For densities greater than or equal to 1MBit, send 3 byte address

    if(FRAM_SPI_spi_density >= SPI_1MBit)

    {

        SPIMH_SpiUartWriteTxData(MSB_ADDR_BYTE(addr));

    }

    // Send 2 address bytes

    SPIMH_SpiUartWriteTxData(ISB_ADDR_BYTE(addr));

    SPIMH_SpiUartWriteTxData(LSB_ADDR_BYTE(addr));

     // Wait for the transmission to complete

    while(0 != (SPIMH_SpiUartGetTxBufferSize() | SPIMH_SpiIsBusBusy()))

    {

    }

    // Clear the receive buffer

    SPIMH_SpiUartClearRxBuffer();

    SPIMH_ClearRxInterruptSource(SPIMH_INTR_RX_FULL);

    

    SPIMH_SetRxInterrupt(SPIMH_INTR_RX_FULL);

    SPIMH_SetRxInterruptMode(SPIMH_INTR_RX_FULL);

   

    // Read data bytes from F-RAM

    i = 0;

    while(i != total_data_count)

    {

    // Send dummy byte to receive data

        if((SPIMH_TX_FIFO_STATUS_REG & 0x0F)<6)

        {

            SPIMH_SpiUartWriteTxData(dummy_data);    //  receive clock generation by using dummy data write

            i++;

           

        }

    }

    while(g_spi_rx_cnt != total_data_count)

    {

    }

    while(0 != SPIMH_SpiIsBusBusy())

    {}

    // De-select F-RAM device

    Pin_FRAMCS_Write(1);

Best regards,

Yocchi

0 Likes
8 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I cannot see an interrupt handler in your code snippet nor a ist_SPI_RX_StartEx(InterruptHandler).

I would recommend to set the SPI Byte mode and increase the buffers to 16.

When still got stuck, can you please post your complete project so that we all can have a look at all of your settings. To do so, use

Creator->File->Create Workspace Bundle (minimal)

and attach the resulting file.

Bob

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

Hello Bob,

I attached the project file.

I prepared both "SPIMH_INTR_RX_NOT_EMPTY" and "SPIMH_INTR_RX_FIFO_LEVEL" interrupt instead of "SPIMH_INTR_RX_FULL".

The project are not necessarily "SPIMH_INTR_RX_FULL".

"SPIMH_INTR_RX_NOT_EMPTY" and "SPIMH_INTR_RX_FIFO_LEVEL" are same behavior because SPIMH_SetRxFifoLevel  is set to 1.

"SPIMH_INTR_RX_NOT_EMPTY" runs well but "SPIMH_INTR_RX_FIFO_LEVEL" does not run well.

If you set "#define rx_not_empty" in FRAM_SPI.h, "SPIMH_INTR_RX_NOT_EMPTY" interrupt is set. On the other hand, if you comment out it "SPIMH_INTR_RX_FIFO_LEVEL"  interrupt is set.

the codes is changed in FRAM_SPI.c below. and I think that SPIMH_SetRxInterrupt and SPIMH_SetRxInterruptMode are allowed interrupt.

#if defined(rx_not_empty)

    SPIMH_SetRxInterrupt(SPIMH_INTR_RX_NOT_EMPTY);              //##

    SPIMH_SetRxInterruptMode(SPIMH_INTR_RX_NOT_EMPTY);     //##

#else

    SPIMH_SetRxFifoLevel (rx_fifo_level);

    SPIMH_SetRxInterrupt(SPIMH_INTR_RX_FIFO_LEVEL);             //##

    SPIMH_SetRxInterruptMode(SPIMH_INTR_RX_FIFO_LEVEL);    //##

    temp = SPIMH_GetRxInterruptSource();

    temp = SPIMH_SpiUartGetRxBufferSize();

#endif

I am using CY8CKIT-044 and CY15FRAMKIT-001.

0 Likes

Hello Bob,

I had a mistake in CY_ISR(isr_SPI_RX_CustomInterrupt).

and I am trying "SPIMH_INTR_RX_FIFO_LEVEL" interrupt.

Please correct it below.

#if defined(rx_not_empty)

    SPIMH_ClearRxInterruptSource(SPIMH_INTR_RX_NOT_EMPTY);

#else

    SPIMH_ClearRxInterruptSource(SPIMH_INTR_RX_FIFO_LEVEL);

#endif

Best regards,

Yocchi

0 Likes

Hi,

I can finally  run well with the RX FIFO Level.

I would like to confirm two settinigs.

Are they right?

1. Should I set the RX FIFO Level to 0 If I want to generate an interrupt when receiving 1 byte

    (RX data bits = 8 in the configuration of SPI) data?

2. May I set SPIMH_SetRxInterruptMode() function to enable and disable the RX FIFO Level interrupt?

    [when enabling the RX FIFO Level interrupt]

      SPIMH_SetRxInterruptMode(SPIMH_INTR_RX_FIFO_LEVEL);

    [when disabling the RX FIFO Level interrupt]

      SPIMH_SetRxInterruptMode(SPIMH_INTR_RX_BLOCKED);

Best regards,

Yocchi

0 Likes

Hi,

I measured both "in case of enabling RX FIFO level interrupt with SPI master configuration" and "in case of enabling RX FIFO level interrupt after writing the memory address with API" the execution time. It was improved from 171.68us to 111.77us.

in case of enabling RX FIFO level interrupt with SPI master configuration

pastedImage_0.png

in case of enabling RX FIFO level interrupt after address write with API

pastedImage_0.png

Best regards,

Yocchi

0 Likes

Hi,

I noticed that it takes up to 2 SCLK clocks between TX FIFO empty and slave select assertion.

Please see the SCB Component Datasheet in the description of uint32 SCB_SpiIsBusBusy(void).

And refer to Re: SPI using PSoC 4 SCB 4.0 .

  SPI Master does not assign slave select line immediately after the first word is written

  into TX FIFO. It takes up to 2 SCLK clocks to assign slave select. Until this happens the

  bus considered not busy.

Well, If we send the data after opcode and address with the burst mode, we can not check "while (SPI_SpiUartGetRxBufferSize() == 0) { } "

like  Re: SPI using PSoC 4 SCB 4.0.

In case of enabling RX FIFO level interrupt with SPI master configuration, we can check the

counts that received dummy send data in RX interrupt handler. but wasting time.

In case of polling, I think that we can wait up to 2 SCLK clocks like below.

/* Workaround because taking up to 2 SCLK clocks to assign slave select after writing TX FIFO */

#define txfifo2busbusy (uint16)((((((uint32)SPIMH_SCBCLK_DIV_REG & SPIMH_SCBCLK_DIV_INT_MASK) >> SPIMH_SCBCLK_DIV_INT_SHIFT)+1)*1000000*(2)*SPIMH_SPI_OVS_FACTOR/CYDEV_BCLK__HFCLK__MHZ+999999)/1000000)

uint8 FRAM_SPI_BurstWrite ( uint32 addr, uint8 *data_write_ptr, uint32 total_data_count )

{

             ...

        /* Send data byte */

        SPIMH_SpiUartWriteTxData((uint8)(data_write_ptr));   

    }

   

    while(0 != SPIMH_SpiUartGetTxBufferSize())

    {}

    /* Workaround because taking up to 2 SCLK clocks to assign slave select after writing TX FIFO */

    CyDelayUs(txfifo2busbusy);

   

    while(0 != SPIMH_SpiIsBusBusy())

    {}

   

    /* De-select the F-RAM device */

    Pin_FRAMCS_Write(1);

    /* return the communication status */

    return SPI_COM_SUCCESS;

}

But I think that these conditions must be kept.

   1. only Motorola and National Semiconductor sub-modes

   2. TX buffer size is less than the TX FIFO depth(not use Software Buffer)

   3. Don't use clock from terminal in SCB configuration

Best regards,

Yocchi

0 Likes

Hi,

I measured each access time.

    access time =

    Slave Select (SS) enable => WREN => WRITE => WRDI => READ => Slave Select (SS) disable

pastedImage_0.png

In case of all polling

in case of enabling RX FIFO level interrupt after address write with APIpastedImage_2.png

in case of enabling RX FIFO level interrupt with SPI master configuration

pastedImage_5.png

Best regards,

Yocchi

0 Likes

Hi,

I am sorry that I forgot to attach the waveform of the polling.

In case of all polling

pastedImage_0.png

Best regards,

Yocchi

0 Likes