SPI transfer function appears to block

I’m trying to use the SPI transfer function to perform non-blocking SPI transactions on an NUCLEO-F303K8 (STM32F303K8) board but the function appears to be blocking. I started with the bare-metal profile and my SPI instance is a member of a class. The following code snippet is how I’m using it:

//SPI init
        SPI mySpi(MOSI, NC, SCK, NC) //don't need MISO
        mySpi.format(8);
        mySpi.frequency(8000000);
.
.
.
.
.
//usage later in function
        gpio_write(&test_pin,1);      
        mySpi.transfer(&TxBits, sizeof(TxBits), &RxBits, 0, event_callback_t(this, &myClass::SPI_Complete), SPI_EVENT_COMPLETE);
        gpio_write(&test_pin,0);
        I2C_Transaction();
  1. The transfer is blocking, as shown below, the gpio pin stays high the entire transaction, where it should go low at some time near the start of the SPI data. The I2C transaction should also occur during the SPI transaction.

  2. As a double whammy, not only is it blocking, there is a lot of downtime between byte transmissions. One byte takes 1us, and there is nearly 3us between bytes. A normal SPI write call (blocking) only has 500ns between bytes.

I hope I’m missing something, any help is appreciated!


Ah yes, I’ve ran into this problem before. The issue is, STMicro’s Mbed port does not do DMA, like, at all. Asynchronous SPI and I2C transfers are implemented with interrupts. So, if your clock frequency is above a certain value (a few MHz), the processor simply is constantly doing interrupts to supply new bytes to the SPI peripheral, and never gets a chance to execute any more code. “Asynchronous” SPI on these devices is really only usable with clock frequencies of less than 1MHz or so.

I do think it’s kinda false advertising tbh… there have been a few attempts at DMA implementations for STM32 devices here and there, but they never really came to fruition to my knowledge.