This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Strange behaviour SPI_MASTER peripheral

Dear Nordic developers,

SPI_MASTER peripheral behaves in a way, that I cannot understand from manual is it normal or no.

I have implemented something similar to loopback example. After initialization I'm writing first byte to the TXD register and immediately after the first one second byte. (as it has double buffer). As I expect, I'm getting two READY events. In a first READY event I'm reading RXD register two times and I get expected two values already in a first READY event.

I was thinking that I should get first byte in a first READY event and the second byte in a second READY event. My simplified code is bellow.

void SPI0_TWI0_IRQHandler(void)
{
    if ((NRF_SPI0->EVENTS_READY == 1) && (NRF_SPI0->INTENSET & SPI_INTENSET_READY_Msk))
    {
        NRF_SPI0->EVENTS_READY = 0;
        if (first_ready_event)
        {
           rx_data[0] = (uint8_t)spi_base->RXD;
           rx_data[1] = (uint8_t)spi_base->RXD;
        }
     if (second_ready_event)
     // do nothing
    }
}


 int main()
 {
    while(true)
    {
       master_spi->TXD =cnt;
       master_spi->TXD =cnt + 1;
       nrf_delay_us(100);
    }
  }

I'd really appreciate if someone could help me and clarify all this.

Thanks and regards, Harut

Parents
  • Hi harutakop,

    Sorry for the late reply.

    The behaviour you see is normal because you are pushing two bytes into TX buffer so fast. So when the first byte is received after transmitting master_spi->TXD =cnt; the ISR starts executing and before you start reading the RXD buffer, the second byte is also transmitted master_spi->TXD =cnt + 1; and equivalent byte received. If you change you code little you will be able to see two READY events

    void SPI0_TWI0_IRQHandler(void)
    {
        if ((NRF_SPI0->EVENTS_READY == 1) && (NRF_SPI0->INTENSET & SPI_INTENSET_READY_Msk))
        {
            NRF_SPI0->EVENTS_READY = 0;
            if (first_ready_event)
            {
               rx_data[0] = (uint8_t)spi_base->RXD; // as soon as you do this RXD-1 value is pushed into RXD and this will cause the READY event again
            }
         if (second_ready_event)
         {
               rx_data[1] = (uint8_t)spi_base->RXD;
         }
        }
    }
    
    
     int main()
     {
        while(true)
        {
           master_spi->TXD =cnt;
           master_spi->TXD =cnt + 1;
           nrf_delay_us(100);
        }
      }
    

    To summarize, what you are seeing is normal because you are pushing two bytes so fast in double buffered SPITX that it is able to serialize them. It might actually JUST finished transmitted the second byte before you read the first byte in ISR. This will not work if you do this

     int main()
     {
        while(true)
        {
           master_spi->TXD =cnt;
           master_spi->TXD =cnt + 1;
           master_spi->TXD =cnt + 2;
           nrf_delay_us(100);
        }
      }
    
  • Hi Aryan, Thanks a lot for your response. You are right. I have tested with Oscilloscope and I can see that second ready event is coming earlier than I'm reading second byte after first byte.

    I tried out all this, because I have very tight timing requirements. I need to receive two bytes every 100 us and I want if possible to skip the first READY event and go to ISR to every second READY event and read two bytes together. Is there possibility to do that?

Reply
  • Hi Aryan, Thanks a lot for your response. You are right. I have tested with Oscilloscope and I can see that second ready event is coming earlier than I'm reading second byte after first byte.

    I tried out all this, because I have very tight timing requirements. I need to receive two bytes every 100 us and I want if possible to skip the first READY event and go to ISR to every second READY event and read two bytes together. Is there possibility to do that?

Children
No Data
Related