Painfully slow SPI on STM32F405

Post here first, or if you can't find a relevant section!
tyguy2
Posts: 5
Joined: Thu Jul 30, 2020 7:11 pm

Re: Painfully slow SPI on STM32F405

Post by tyguy2 »

Bakisha wrote: Fri Jul 31, 2020 11:59 pm I finally found solution. After dive into CMSIS definitions of the core, and testing it on logic analyzer with STM32F401CC (84MHz) , i found that error was on my part, because in my case, i had CE not going high after transfer (i had some more stuff execution) , and in this case CE will go high while hardware is still sending last byte. So, here is a macro for sending a byte:

Code: Select all

void  SPI_TRANSFER (uint8_t x)  {
  // SPI.transfer(x);  // send byte
  SPI1->DR = (x) ;
  while ((SPI1->SR &  SPI_SR_BSY ) | (SPI1->SR & (!SPI_SR_TXE)) ) {}; // wait until - Transmit buffer NOT Empty - Busy flag  SET
}
But, i was correct that gaps between bytes normal SPI.transfer was around 2uS.
Also, i found that 17uS was just for SPI.beginTransaction and SPI.endTransaction
Also, digitalWrite is around 0.5uS

Here is sketch that used to get maximum speed :

Code: Select all

#include <SPI.h>
#define CS PA4
int i = 0;
void setup() {
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(50000000, MSBFIRST, SPI_MODE0));
}
void loop() {
  i++;

  if (i > 1023) {
    i = 0;
  }

  dac8Write(1, i);
}

void dac8Write(byte channel, int input) {
  //Warning: Channel must be less than 7!
  //0011 Command - Write to and Update DAC
  //0xxx Address - Binary address of DAC's 1-8
  //xxxxxxxxxx   - 10 bit analog value
  channel = 0x30 | channel;
  input = input << 6;
  // Send as command, address, then 10 bit value

  digitalWrite(CS, LOW);
  SPI_TRANSFER(channel);
  SPI_TRANSFER(highByte(input));
  SPI_TRANSFER(lowByte(input));
  digitalWrite(CS, HIGH);

}
void  SPI_TRANSFER (uint8_t x)  { // 0.3uS overhead between bytes when optimized // 3.25 uS unoptimized
  // SPI.transfer(x);  // send byte
  SPI1->DR = (x) ;
  while ((SPI1->SR &  SPI_SR_BSY ) | (SPI1->SR & (!SPI_SR_TXE)) ) {}; // wait until - Transmit buffer NOT Empty - Busy flag  SET
}
And here is screenshot of logic analyzer of that sketch (ignore CLK and MOSI, 24MHz samplerate is to slow for 42MHz spi clock, but is enough for CE time) :
Clipboard010.jpg
I hope that is only device on SPI1 bus, or things might get complicated.
Unfortunately I checked this and it did not work. I looked on my scope and I'm not getting any data on the SPI lines. I'm using SPI1, which is PB3 - PB5, correct?
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: Painfully slow SPI on STM32F405

Post by Bakisha »

tyguy2 wrote: Sat Aug 01, 2020 12:38 am
Unfortunately I checked this and it did not work. I looked on my scope and I'm not getting any data on the SPI lines. I'm using SPI1, which is PB3 - PB5, correct?
From https://github.com/stm32duino/Arduino_C ... L216-L264 i guessed default SPI1 is on PA5/PA6/PA7.

PB3,PB4 and PB5 are alternate pins.

Try this sketch:

Code: Select all

//*** SPI ***

const PinMap PinMap_SPI_MOSI[] = {
  //{PA_7,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  {PB_5,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  //{PB_5,  SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {PB_15, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PC_3,  SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PC_12, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {NC,    NP,    0}
};

const PinMap PinMap_SPI_MISO[] = {
  //{PA_6,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  {PB_4,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  //{PB_4,  SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {PB_14, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PC_2,  SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PC_11, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {NC,    NP,    0}
};

const PinMap PinMap_SPI_SCLK[] = {
  //{PA_5,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  {PB_3,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  {PB_3,  SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {PB_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PB_13, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PC_10, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {NC,    NP,    0}
};


const PinMap PinMap_SPI_SSEL[] = {
  {PA_4,  SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  //  {PA_4,  SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  //  {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
  {PA_15, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
  {PB_9,  SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
  {NC,    NP,    0}
};

#include <SPI.h>



#define CS PA4
int i = 0;
void setup() {
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  SPI.setMOSI(PB5);
  SPI.setMISO(PB4);
  SPI.setSCLK(PB3);
  SPI.begin();
  SPI.beginTransaction(SPISettings(50000000, MSBFIRST, SPI_MODE0));
}
void loop() {
  i++;

  if (i > 1023) {
    i = 0;
  }

  dac8Write(1, i);
}

void dac8Write(byte channel, int input) {
  //Warning: Channel must be less than 7!
  //0011 Command - Write to and Update DAC
  //0xxx Address - Binary address of DAC's 1-8
  //xxxxxxxxxx   - 10 bit analog value
  channel = 0x30 | channel;
  input = input << 6;
  // Send as command, address, then 10 bit value

  digitalWrite(CS, LOW);
  SPI_TRANSFER(channel);
  SPI_TRANSFER(highByte(input));
  SPI_TRANSFER(lowByte(input));
  digitalWrite(CS, HIGH);

}
void  SPI_TRANSFER (uint8_t x)  { // 0.3uS overhead between bytes when optimized // 3.25 uS unoptimized
  // SPI.transfer(x);  // send byte
  SPI1->DR = (x) ;
  while ((SPI1->SR &  SPI_SR_BSY ) | (SPI1->SR & (!SPI_SR_TXE)) ) {}; // wait until - Transmit buffer NOT Empty - Busy flag  SET
}
It worked with alternate pins on my STM32F401CC
Post Reply

Return to “General discussion”