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

Any ideas on how to decrease SPI overhead time?

With the maximum SPI speed of 8 Mbps, I was expecting to be able to send 2 bytes in just a little over 2 us, but it takes a lot longer. It appears that the mandatory event wait time between bytes (to avoid overwriting the first one) is about 4 us and, if I include the time it takes to toggle the slave device CE line on and off, the total transmission time is about 10 us. This gives me a throughput of only about 1.6 Mbps.

Is there any way to speed that up? I'm even using some "INLINE" instructions (see below):

NRF_GPIO->OUTCLR = CE_BIT_POS;

dac_spi_base_address->TXD = (uint32_t)(tx_data[0]);

while (dac_spi_base_address->EVENTS_READY == 0U) { } dac_spi_base_address->EVENTS_READY = 0U; rx_data[0] = (uint8_t)dac_spi_base_address->RXD;

dac_spi_base_address->TXD = (uint32_t)(tx_data[1]);

while ((dac_spi_base_address->EVENTS_READY == 0U) /&& (counter < DAC_TIMEOUT_COUNTER)/) { } dac_spi_base_address->EVENTS_READY = 0U; rx_data[1] = (uint8_t)dac_spi_base_address->RXD;

NRF_GPIO->OUTSET = CE_BIT_POS;

Thank you for any ideas!

Gil

Parents
  • I was able to decrease the time from 10 us to 3 us by:

    1. Doing some assignments ahead of time: register uint8_t rxData; register uint16_t * ptr = &(Data[0]); // 2 bytes register uint32_t* RxReg = (uint32_t*)&(dac_spi_base_address->RXD); register uint32_t* TxReg = (uint32_t*)&(dac_spi_base_address->TXD);

    2. Removing the RXD read between the bytes (the one after the second byte is still needed)

    3. Removing the while(event) between the bytes, and replacing the one after the second byte with a NOP delay sequence function.

    Final code:

    // Enable slave (slave select active low)

    NRF_GPIO->OUTCLR = SYNC_BIT_POS;

    // Write upper byte

    *TxReg = ((*ptr) >> 8);

    // Read Rx register (this one is not needed) // rxData = *RxReg;

    // Write lower byte

    *TxReg = ((uint8_t)(*ptr));

    // Read Rx register

    rxData = *RxReg;

    // Just a bunch of NOPs to wait for the byte transmittal

    dac_delay_100s_of_ns();

    // Disable slave (slave select active low)

    NRF_GPIO->OUTSET = SYNC_BIT_POS;

Reply
  • I was able to decrease the time from 10 us to 3 us by:

    1. Doing some assignments ahead of time: register uint8_t rxData; register uint16_t * ptr = &(Data[0]); // 2 bytes register uint32_t* RxReg = (uint32_t*)&(dac_spi_base_address->RXD); register uint32_t* TxReg = (uint32_t*)&(dac_spi_base_address->TXD);

    2. Removing the RXD read between the bytes (the one after the second byte is still needed)

    3. Removing the while(event) between the bytes, and replacing the one after the second byte with a NOP delay sequence function.

    Final code:

    // Enable slave (slave select active low)

    NRF_GPIO->OUTCLR = SYNC_BIT_POS;

    // Write upper byte

    *TxReg = ((*ptr) >> 8);

    // Read Rx register (this one is not needed) // rxData = *RxReg;

    // Write lower byte

    *TxReg = ((uint8_t)(*ptr));

    // Read Rx register

    rxData = *RxReg;

    // Just a bunch of NOPs to wait for the byte transmittal

    dac_delay_100s_of_ns();

    // Disable slave (slave select active low)

    NRF_GPIO->OUTSET = SYNC_BIT_POS;

Children
No Data
Related