Zephyr SPI on nRF52 - spi_transceive_dt() delay between bytes.

Hi, I am wondering if anyone with SPI expertise can answer this Q, I'm using an nRF52840 with spi_transceive_dt()

In my devicetree I've configured SPIM on SPI3 to talk to a sensor at 10MHz.

I am simply doing a register read to a sensor device. So calling spi_transceive_dt() with 1 Tx byte and 2 Rx bytes (the sensor requires 1 dummy byte for each read). It responds correctly with 0x00, 0x24 and I get the data fine.

I am wondering why is there is big ~14us gap between bytes. From the red line I have highlighted, you can see SCK is just flat, waiting during this time, until it starts to clock again and we see the next byte from the slave (0x00), and then the same gap until the next byte (0x24).

I am wondering if this is to do with the MCU or some inefficiency in the SPI driver somewhere in the stack of nRFX drivers to Zephyr SPI API?

Parents Reply Children
  • I have a finding and a solution.

    When the tx-buffer and rx-buffer not same size, it still works but we see the clock stopping.

    no clock stop

    static int bmp388_reg_read_spi(const union bmp388_bus *bus,
                       uint8_t regaddr, uint8_t *buf, int size)
    {
        int ret;
        uint8_t addr[size + 2];
        uint8_t rxdata[size + 2];
    
        memset(&addr,0x00,ARRAY_SIZE(addr));
    
        const struct spi_buf tx_buf = {
            .buf = &addr,
            .len = ARRAY_SIZE(addr),
        };
        const struct spi_buf_set tx = {
            .buffers = &tx_buf,
            .count = 1
        };
    
        struct spi_buf rx_buf;
        const struct spi_buf_set rx = {
            .buffers = &rx_buf,
            .count = 1,
        };
    
        addr[0] = (regaddr) | 0x80;
        rx_buf.buf = &rxdata;
        rx_buf.len = ARRAY_SIZE(rxdata);
    
        ret = spi_transceive_dt(&bus->spi, &tx, &rx);
        if (ret) {
            LOG_DBG("spi_transceive FAIL %d\n", ret);
            return ret;
        }
    
        memcpy(buf, (uint8_t *)&rxdata[2], size);
    
        return 0;
    }
    

    clock stop

    static int bmp388_reg_read_spi(const union bmp388_bus *bus,
                       uint8_t regaddr, uint8_t *buf, int size)
    {
        int ret;
        uint8_t addr[3] = { 0 };
        uint8_t rxdata[size + 2];
    
    

    You can see the '0' pushed when tx and rx same size.
    but gap and ff if not. So something happen under the hood if the core need to handle the lager receive buffer.

  • Hi Christopher, 
    I think the reason you are seeing that is because how the nrfx_spim was designed. It will take 2 transactions to read and write if the size of the buffer TX and RX are not the same. 
    The first transaction will be executed for smaller buffer and the second transaction will clock the rest of the bytes for the rest of the larger buffer. I think it has something to do with the DMA access here. If it does one single large transaction it will overflow the smaller buffer when doing DMA access. 

Related