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

SPI Clock BUG

Hi: I use the demo code (nRF51_SDK_9.0.0_2e23562-NORDIC\nRF51_SDK_9.0.0_2e23562\examples\peripheral\spi_master) find a BUG(?) : when i use 1M clock , 1byte translate use about 10us, the delay between 2 byte is OK, when i use 4M clock , 1byte translate still use about 10us, the delay tbetween 2 byte is about 8us,image description

/@brief Macro for initializing SPI master by default values. / 
#define SPI_MASTER_INIT_DEFAULT \ 
{ \ SPI_FREQUENCY_FREQUENCY_M1, /< Serial clock frequency 1 Mbps. */ \     
    SPI_PIN_DISCONNECTED, /< SCK pin DISCONNECTED. */ \ 
    SPI_PIN_DISCONNECTED, /< MISO pin DISCONNECTED. */ \ 
    SPI_PIN_DISCONNECTED, /< MOSI pin DISCONNECTED. */ \ 
    SPI_PIN_DISCONNECTED, /< Slave select pin DISCONNECTED. */ \ 
    APP_IRQ_PRIORITY_LOW, /< Interrupt priority LOW. */ \ 
    SPI_CONFIG_ORDER_LsbFirst, /< Bits order LSB. */ \ 
    SPI_CONFIG_CPOL_ActiveHigh, /< Serial clock polarity ACTIVEHIGH. */ \ SPI_CONFIG_CPHA_Leading, /< Serial clock phase LEADING. */ \ 
    0 /*< Don't disable all IRQs. */ \     
};
  • Hi

    This is due to overhead in the spi_master.c driver. Sadly there is no easyDMA in the master SPI on the nRF51 so in the driver an interrupt is called after every transmitted byte. The interrupt routine is responsible for handling incoming bytes and load new bytes to the transmit register which takes time. The SPI is double buffered meaning that the second byte can be written to the TXD register immediately after the first one. In other words, the SPI driver is not using the interrupt handler to load the second byte so there is almost no overhead. The following bytes however, are loaded into the TXD register using the interrupt handler creating an overhead.

    I did some experiments and it looks like you actually won't get any higher throughput by increasing the frequency above 1MHz if you use the driver in the SDK:

    image description

    You can probably make your own interrupt routine though, customized for your own needs that will work faster than the one in the SDK.

  • We discussed this a while ago in devzone.nordicsemi.com/.../ plus some others. I have about 3MHz running, Clem said he got 4MHz. That required not using the SPI Master driver but writing our own which, when it gets an interrupt, keeps filling the TX buffer as fast as it can until it runs out of characters or manages to fill the buffer, at which point it waits for another interrupt.

Related