Bug in SPI-library or in example sketch?

Working libraries, libraries being ported and related hardware
Post Reply
STM32ardui
Posts: 45
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Bug in SPI-library or in example sketch?

Post by STM32ardui »

My system:
Windows 10
ArduinoIDE 2.3.2
Arduino core for STM32 MCUs 2.7.1


There is a test-sketch named SPI_loop.ino inside examples
https://github.com/stm32duino/STM32Exam ... I_loop.ino


The code from line 50 to 53 is:

Code: Select all

 SPI.begin(CS_PIN);

  for (uint8_t received = 0; received < TEST_LOOP_NB; received++) {
    SPI.transfer(CS_PIN, buffer_tx, buffer_rx, BUF_SIZE, SPI_LAST);
Compiler throws errors.

So I compare with library
https://github.com/stm32duino/Arduino_C ... es/SPI/src

In SPI.h line 125:

Code: Select all

void begin(void);
So begin() can't take a parameter. I don't see an additional version (function overloading?) with parameter.

Also from line 134 in SPI.h:

Code: Select all

/* Transfer functions: must be called after initialization of the SPI
     * instance with begin() or beginTransaction().
     */
    uint8_t transfer(uint8_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
    uint16_t transfer16(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
    void transfer(void *buf, size_t count, bool skipReceive = SPI_TRANSMITRECEIVE);

    /* Expand SPI API
     * https://github.com/arduino/ArduinoCore-API/discussions/189
     */
    void transfer(const void *tx_buf, void *rx_buf, size_t count);
doesn't fit to the code in SPI_loop.ino.

And inside README.md for SPI library there is close to the end also an example, where begin() has a parameter:

Code: Select all

SPI.setMISO(PC_4); // using pin name PY_n
    SPI.setMOSI(PC2); // using pin number PYn
    SPI.begin(2);
User avatar
fpiSTM
Posts: 1780
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 93
Location: Le Mans
Contact:

Re: Bug in SPI-library or in example sketch?

Post by fpiSTM »

Sketch has not been updated after SPI rework.
STM32ardui
Posts: 45
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: Bug in SPI-library or in example sketch?

Post by STM32ardui »

fpiSTM wrote: Sun May 19, 2024 11:25 am Sketch has not been updated after SPI rework.
I changed sketch to new functions and used a WeAct Studio BlackPill STM32F411CEUS, pin numbers are from their pinout graphic. LED on PA13 is connected to +3.3V, so it shines, when output level of PA13 is LOW. So I placed defines for LED_ON and LED_OFF at the beginning.

At my first try memcmp() fails, because I forgotten to solder some pins to the pin strip *grrrr*. So here is the sketch with a lot of printout.

A hint:
If - for example - pin number of SCLK is wrong, SPI.tranfer() doesn't work and sketch hang up. So you never see the Serial.print() for Pos2.

What happens without #define for SPI-pins and call of SPI.setxxxx()?
Sketch also works.
Inside PeripheralPins.c I see PA_1 as first array member for MOSI. PA_7 I used is the second line. My pin numbers for MISO, SCLK and CS are the first line. So I still wonder, how such a mixture can work or if compiler takes default pins from a different file. :o

Code: Select all

//-----------------------------------------------------------------------------
// SPI_loopback
// https://github.com/stm32duino/STM32Examples/blob/main/examples/NonReg/SPI_loop/SPI_loop.ino
//
// Pinout (WeAct STM32F411CEUS):
//   MOSI1    PA7
//   MISO1    PA6
//   SCLK     PA5
//   NSS1/3   PA4  
//   RX1      PA10
//   TX1      PA9
//-----------------------------------------------------------------------------

#include "SPI.h"

#ifndef LED_BUILTIN
#define LED_BUILTIN PA13
#endif

// on WeAct Blackpill LED is connected to +3.3V
// change for your board if LED is connected to GND
#define LED_ON   LOW
#define LED_OFF  HIGH

#define MOSI_PIN  PA7  
#define MISO_PIN  PA6  
#define SCK_PIN   PA5  
#define CS_PIN    PA4  

uint8_t buffer_tx[] = "Thequickbrownfoxjumpsoverthelazydog\0";
#define BUF_SIZE  sizeof(buffer_tx)
uint8_t buffer_rx[BUF_SIZE] = {};

/* SPI transfer loop nb */
#define TEST_LOOP_NB 9

void setup() {
  uint8_t tested_ok = 0; // test result
  pinMode(LED_BUILTIN, OUTPUT);   
  Serial.begin(9600);
  digitalWrite(LED_BUILTIN, LED_ON);
  delay(2000);
  digitalWrite(LED_BUILTIN, LED_OFF);
  Serial.print("\n\n ----- SPI Loop Test with STM32F411CEUS -----\n");

  SPI.setMOSI(MOSI_PIN);
  SPI.setMISO(MISO_PIN);
  SPI.setSCLK(SCK_PIN);
  SPI.setSSEL(CS_PIN);

  SPI.begin();
  Serial.println("   Pos1 - behind SPI.begin()");

  for (uint8_t received = 0; received < TEST_LOOP_NB; received++) {
    SPI.transfer(buffer_tx, buffer_rx, BUF_SIZE);
    Serial.printf("   Pos2 - tested_ok = %d\n", tested_ok );
    for(uint8_t i = 0; i<BUF_SIZE; i++) Serial.print(buffer_tx[i], HEX);
    Serial.println();
    for(uint8_t i = 0; i<BUF_SIZE; i++) Serial.print(buffer_rx[i], HEX);
    Serial.println();
    // compare what is received to what was sent 
    // memcp() returns 0, if both string are equal 
    if ( memcmp(buffer_tx, buffer_rx, BUF_SIZE) == 0) {
      /* this transfer passed */
      tested_ok++;
    }
    memset(buffer_rx, 0, BUF_SIZE);
  }
  /* display test result */
  
  digitalWrite(LED_BUILTIN, LED_OFF); // start with led off
  if (tested_ok == TEST_LOOP_NB) {
      /* success */
      digitalWrite(LED_BUILTIN, LED_ON);
      Serial.println("test successful");
  } else {
      /* error. Please verify MISO is externally connected to MOSI */
      digitalWrite(LED_BUILTIN, LED_OFF);
      Serial.println("test with error");
  }
  Serial.println("   Pos3 - end of setup()");
}

void loop() {
  /* nothing to do */
}
User avatar
fpiSTM
Posts: 1780
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 93
Location: Le Mans
Contact:

Re: Bug in SPI-library or in example sketch?

Post by fpiSTM »

STM32ardui
Posts: 45
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: Bug in SPI-library or in example sketch?

Post by STM32ardui »

Nice document, but not my question.

If I buy a Arduino UNO I can see printed on the board RX, TX, SCL, SDA. So I know where I have to connect a RS485-adapter or some I²C-sensors. And on the manufactor homepage I find a pinout graphic, so I also know where the pins for SPI are.

Is there such a documentation for STM32 chips?
No.
I want to know, where I have to connect UART1, I²C1 and SPI1 after power on.
ag123
Posts: 1709
Joined: Thu Dec 19, 2019 5:30 am
Answers: 27

Re: Bug in SPI-library or in example sketch?

Post by ag123 »

@STM32ardui
in Arduino, it defines a default SPI port. Hence, selection of SPI device is not defined in the API
https://www.arduino.cc/reference/en/lan ... ation/spi/

hence, to an extent this is 'beyond Arduino'
to put things in perspective. you need to consider the hardware on stm32, there can be more than one SPI device (you need to select a particular device), and/but that only specific pins has dedicated functions (e.g. MOSI, MISO, SCK) for SPI, and you need to configure the pinMux at the gpio to use SPI alt functions on those pins as well.
for this you need to review the specs sheet for your soc and the ref manual e.g.
https://www.st.com/resource/en/datashee ... f411ce.pdf
^ check in particular the pinouts and pin description chapter 4
take for instance you can find for SPI1 the alt functions for SPI1 are available on PA4-PA7
- PA4 NSS (not needed unless you are doing SPI slave), you can use this as your SSEL pin
- PA5 SCK
- PA6 MISO
- PA7 MOSI

if this is defined in the variant, normally all you need to do is to simply use the symbol SPI which is the default SPI configuration.
otherwise, you need to create the device specifically, e.g.
https://github.com/stm32duino/Arduino_C ... ki/API#spi

Code: Select all

#include <SPI.h>
//            MOSI  MISO  SCLK   SSEL
SPIClass SPI_1(PA7, PA6, PA5, PA4);

void setup() { 
  SPI_1.begin(); // Enable the SPI_1 instance with default SPISsettings
  SPI_1.beginTransaction(settings); // Configure the SPI_1 instance with other settings
  SPI_1.transfer(0x52); // Transfers data to the first device
  SPI_1.end() //SPI_1 instance is disabled
}
void loop() { ... };
Actually for that to work those pins configuration need to be specified in the variant accordingly, such that that would select SPI1.
and in addition, review the *reference manual* in particular those chapters on SPI e.g. for stm32f411
https://www.google.com/search?q=stm32f4 ... nce+manual
e.g.
https://www.st.com/resource/en/referenc ... ronics.pdf
Last edited by ag123 on Sun May 19, 2024 8:55 pm, edited 1 time in total.
STM32ardui
Posts: 45
Joined: Mon May 06, 2024 1:46 pm
Answers: 1
Location: Germany

Re: Bug in SPI-library or in example sketch?

Post by STM32ardui »

Also for a STM32 must be a default setting, so after power up program recognizes a SD-card at the correct SPI-pins or a sensor at SDA/SCL.

And the datasheet is not the right place!
Of course I looked into chapter 4 and there in table 8. In column "Pin name (function after reset)" there is only the pin number PA1, PA2 and so on - no default function!
There is another column "Alternate functions". For PA7 it contains: TIM1_CH1N, TIM3_CH2, SPI1_MOSI/I2S1_SD ... so which is the default value???

Because I used for SPI-Loop-sketch a BlackPill-Board and select so in ArduinoIDE, I think in between, that variant_BLACKPILL_F411CE.h is the right place.

Code: Select all

// SPI definitions
#ifndef PIN_SPI_SS
  #define PIN_SPI_SS            PA4
#endif

#ifndef PIN_SPI_MOSI
  #define PIN_SPI_MOSI          PA7
#endif
#ifndef PIN_SPI_MISO
  #define PIN_SPI_MISO          PA6
#endif
#ifndef PIN_SPI_SCK
  #define PIN_SPI_SCK           PA5
#endif
...
#ifndef PIN_SERIAL_RX
  #define PIN_SERIAL_RX         PA10
#endif
#ifndef PIN_SERIAL_TX
  #define PIN_SERIAL_TX         PA9
#endif
That seems to be correct for my board.

But for the small STM32C011 I see in variant_generic.h:

Code: Select all

// SPI definitions
#ifndef PIN_SPI_SS
  #define PIN_SPI_SS            PA8
#endif

#ifndef PIN_SPI_MOSI
  #define PIN_SPI_MOSI          PA2
#endif
#ifndef PIN_SPI_MISO
  #define PIN_SPI_MISO          PA11
#endif
#ifndef PIN_SPI_SCK
  #define PIN_SPI_SCK           PA1
#endif

// I2C definitions
#ifndef PIN_WIRE_SDA
  #define PIN_WIRE_SDA          PA10_R
#endif
#ifndef PIN_WIRE_SCL
  #define PIN_WIRE_SCL          PA9_R
#endif


// Default pin used for generic 'Serial' instance
#ifndef PIN_SERIAL_RX
  #define PIN_SERIAL_RX         PA1
#endif
#ifndef PIN_SERIAL_TX
  #define PIN_SERIAL_TX         PA0
#endif 
PA1 for PIN_SERIAL_RX and PIN_SPI_SCK ???


P.S.: I'm familiar with ESP32. You can set there I²C or SPI to pins you like. If you don't, there are default pins for HSPI and VSPI (the two SPI-interfaces you can use).
Last edited by STM32ardui on Sun May 19, 2024 9:00 pm, edited 1 time in total.
ag123
Posts: 1709
Joined: Thu Dec 19, 2019 5:30 am
Answers: 27

Re: Bug in SPI-library or in example sketch?

Post by ag123 »

all the pins are normally GPIO, the alternate functions column are the alternate functions available at those particular pins, so for the gpio pin mux, you actually need to configure the pin mux so that it select the correct alternate function at the pin.
If you do not know how to do that, this is done when you construct the SPI object, that specifies the pins for the pin mux, the configuration happens subsequently when you issue the SPI_1.begin() call.

Code: Select all

#include <SPI.h>
//            MOSI  MISO  SCLK   SSEL
SPIClass SPI_1(PA7, PA6, PA5, PA4);
I'd suggest you stick with STM32F411 while getting familiar with the basics like SPI. On C011 you need to struggle first with all these basics such as the pin configurations, then that is not all, you may actually run out of memory doing even just SPI, I think for some devices there is like 6 k of sram for *everything*, and you won't even know if your stack simply overwrite your global variables such as SPI buffers etc.

For SPI1 I'd suggest you can try what I've suggested on STM32F411 i.e. PA4, PA5, PA6, PA7 for SPI1, and create your SPI_1 object as such.
the methods calls are then available under SPI_1.method() (e.g. SPI_1.transfer( .... )).

if you use the default SPI symbol, check in the variant for the default SPI 1 pin configuration.
normally for 'standard' Arduino, SPI is the default symbol. If you need to use more than one SPI device, that goes 'beyond arduino' and you need to create those SPI objects (e.g. name them like SPI_2, SPI_3 etc) with the relevant pin configurations. And that won't be using the symbol SPI.

if you insist on using C011, as well as the default SPI symbol, you can make some changes in the variant for your local copy. e.g. to redefine them using PA4, PA5, PA6, PA7 in the variant.h file. Then you can possibly simply #include <SPI.h> and simply use the SPI symbol.
PA4-PA7 is nearly there in most of the stm32 devices that I see. But note that C011 has an '8 pin' thingy
https://www.st.com/resource/en/datashee ... c011f6.pdf
PA0, PA1, PA2 are packed on a single pin, PA4-PA7 are simply *absent*, and PA0-PA2 has alt functions like SPI1_SCK, SPI1_MOSI on a single pin which means that it is impossible to do SPI on the '8 pin' thingy. But for f6p6 the 20 pin chip, you have PA4-PA7.
note that technically, if you go wire things around those pins, you can literally use

Code: Select all

#include <SPI.h>
//            MOSI  MISO  SCLK   SSEL
SPIClass SPI_1(PA2, PA11, PA1, PA8);

/*
#ifndef PIN_SPI_SS
  #define PIN_SPI_SS            PA8
#endif

#ifndef PIN_SPI_MOSI
  #define PIN_SPI_MOSI          PA2
#endif
#ifndef PIN_SPI_MISO
  #define PIN_SPI_MISO          PA11
#endif
#ifndef PIN_SPI_SCK
  #define PIN_SPI_SCK           PA1
#endif
*/
I think that would be the configs for the SPI symbol.
But that if you prefer a more 'regular looking' set of SPI pins, you can edit your local copy of the variant file.

@fpiSTM
just IMHO, I think we can use PA4-PA7 for the default SPI pins on c011 as the '8 pin' chip can't practically use SPI
User avatar
fpiSTM
Posts: 1780
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 93
Location: Le Mans
Contact:

Re: Bug in SPI-library or in example sketch?

Post by fpiSTM »

ag123 wrote: Sun May 19, 2024 8:59 pm @fpiSTM
just IMHO, I think we can use PA4-PA7 for the default SPI pins on c011 as the '8 pin' chip can't practically use SPI
Right, physically not possible. But those file are automatically generated and have no info they shared the same pins so hard to change it.
As usual, this is a default(generic) definition and it always up to end user to ensure pin mapping is correct depending on his hardware (package, wiring, ...)
Post Reply

Return to “Libraries & Hardware”