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

SPI inter-byte duration

Hello, I've been working on porting a bit-banged control of a peripheral to use nRF51 SPI--which is just SPI rather than SPIM (therefore no DMA). Observe the SPICLK waveform when I choose 4 MHz: image description

The byte itself is emitted at 4 MHz. But the huge inter-byte distance remains constant down to about 1 MHz CLK speed. I guess that's just how it is with SPI (not SPIM). In the waveform above, one can see that the maximum effective SPI speed is roughly 14 us / 1 B => 570 KHz, which is only slightly faster than the maximum effective SPI speed when I bit-bang using GPIO on an STM32L1 (Cortex M3) ~ 400 KHz. It nearly negates the arguments for using the SPI peripheral over bit-bang (except for some battery savings by using WFE).

I doubt there is anything I can do to improve the situation, but thought I'd check with experts just in case. Thanks for reading.

Parents
  • Thank you for the reply Wojtek and Hung, you were right: I was taking much too long in my checking for the nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY). There is still some ~4 us until I see the EVENT_READY flag in the register, but the effective BW is now up to 1.23 MHz (when using the 4 MHz SPI speed). BTW, why can't I call sd_app_evt_wait() (which just calls WFE) while waiting for NRF_SPI_EVENT_READY? I find this to be true even while waiting for NRF_UART0->EVENTS_TXDRDY (in another context) as well. Shouldn't these events wake up the nRF that is sleeping on WFE?

  • I think POWER_CLOCK_IRQn is the IRQ I was looking for. Anyway, I can't seem to get the nRF to return from sd_app_evt_wait() using the technique you describe. Can you please point out anything obviously wrong I am doing below:

    In init():

        NRF_UART0->ENABLE          = UART_ENABLE_ENABLE_Enabled;
        NRF_UART0->INTENSET = UART_INTENSET_TXDRDY_Msk;//required to wake up from WFE
        NRF_UART0->TASKS_STARTTX   = 1;
        NRF_UART0->TASKS_STARTRX   = 1;
        SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
    
    void put_byte(uint8_t b) {
        NRF_UART0->TXD = b;
        while (!NRF_UART0->EVENTS_TXDRDY) {
            sd_app_evt_wait();
        }
        NRF_UART0->EVENTS_TXDRDY = 0;
        NVIC_ClearPendingIRQ(UART0_IRQn);
    }
    
Reply
  • I think POWER_CLOCK_IRQn is the IRQ I was looking for. Anyway, I can't seem to get the nRF to return from sd_app_evt_wait() using the technique you describe. Can you please point out anything obviously wrong I am doing below:

    In init():

        NRF_UART0->ENABLE          = UART_ENABLE_ENABLE_Enabled;
        NRF_UART0->INTENSET = UART_INTENSET_TXDRDY_Msk;//required to wake up from WFE
        NRF_UART0->TASKS_STARTTX   = 1;
        NRF_UART0->TASKS_STARTRX   = 1;
        SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
    
    void put_byte(uint8_t b) {
        NRF_UART0->TXD = b;
        while (!NRF_UART0->EVENTS_TXDRDY) {
            sd_app_evt_wait();
        }
        NRF_UART0->EVENTS_TXDRDY = 0;
        NVIC_ClearPendingIRQ(UART0_IRQn);
    }
    
Children
No Data
Related