SPI2 On STM32 MicroMod Hangs Code

Hey all!

I have an STM32 MicroMod I’m working with, and I have been able to successfully interface with the SPI1 peripheral using the default pins (PA5 / PA6 / PA7). However using the exact same code, and changing out the pins to those associated with SPI2 on PB10 / PC2 / PB15, the code hangs at mySPI.transfer.

I’ve gone back and forth to the datasheet to re-verify the valid SPI2 pins, that the ports correspond to the LQFP64 pinout, that those are brought to the MicroMod connector, and how that connector is then brought to the headers of the ATP board:

SPI2 SCK          = PB10  = uMod 14 = SCL
SPI2 CIPO (MISO)  = PC2   = uMod 71 = G6
SPI2 COPI (MOSI)  = PB15  = uMod 35 = HOST D+
SPI2 CS           = PB9   = uMod 43 = CAN TX

When viewing this on a scope, none of the SPI signal pins do anything, but the CS pin does toggle low before the code hangs. I wrote some quick code to toggle them as standard GPIOs, verifying that I was connecting at the correct locations, and that there didn’t seem to be any hidden alternate default function, and that worked without issue. Using them as a SPI peripheral seems to cause a conflict that isn’t readily obvious. Just in case there was something I was unaware of that precluded using different SPI peripherals, I verified I could talk to the Flash module over SPI3 (using code not included here, but same setup and configuration essentially).

Here’s the code that hangs at “CODE HANGS HERE”. Commenting out #define USE_SPI2 reverts to the SPI1 default pins and runs normally.

/*

A sketch to control the 10-Bit, 8-channel ADC MCP3008
Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf

*/

#include <SPI.h>            // Include the SPI library

#define USE_SPI2

#ifdef USE_SPI2             // SPI2 Peripheral Pins
  #define MYSPI_SCLK   PB10
  #define MYSPI_MISO   PC2
  #define MYSPI_MOSI   PB15
  #define MYSPI_NSS    PB9
#else                       // SPI1 Peripheral Pins
  #define MYSPI_SCLK   PA5
  #define MYSPI_MISO   PA6
  #define MYSPI_MOSI   PA7
  #define MYSPI_NSS    PC4 
#endif

SPISettings MCP3008 (2000000, MSBFIRST, SPI_MODE0);

SPIClass mySPI(MYSPI_MOSI, MYSPI_MISO, MYSPI_SCLK);

const byte adc_single_ch0   = (0x08);     // ADC Channel 0
const byte adc_single_ch1   = (0x09);     // ADC Channel 1
const byte adc_single_ch2   = (0x0A);     // ADC Channel 2
const byte adc_single_ch3   = (0x0B);     // ADC Channel 3
const byte adc_single_ch4   = (0x0C);     // ADC Channel 4
const byte adc_single_ch5   = (0x0D);     // ADC Channel 5
const byte adc_single_ch6   = (0x0E);     // ADC Channel 6
const byte adc_single_ch7   = (0x0F);     // ADC Channel 7

uint8_t counter = 0;        // Used for debug

void setup() {

  pinMode (LED_BUILTIN, OUTPUT);  // Used for debug
  
  Serial.begin  (115200);
  delay(1000);
  
  mySPI.begin ();

  // Datasheet suggests toggling NSS to initialize chip
  pinMode       (MYSPI_NSS, OUTPUT);
  digitalWrite  (MYSPI_NSS, LOW);
  digitalWrite  (MYSPI_NSS, HIGH);

}



void loop() {
  
  counter++;
  double vRef     = 3.30;
  int adc_reading = 0;
  adc_reading     = adc_single_channel_read (adc_single_ch7);
 
  Serial.print    ("ADC Ch ");
  Serial.print    (adc_single_ch7 & 0x07);
  Serial.print    ("... Reading: ");
  Serial.print    (adc_reading);  
  Serial.print    (" and Voltage: ");
  Serial.println  ((adc_reading * vRef) / 1024, 4);
  Serial.println  ();
  delay(125);
}


int adc_single_channel_read(byte readAddress) {

  byte dataMSB =    0;
  byte dataLSB =    0;
  byte JUNK    = 0x00;

  // Output to serial monitor that we got this far and toggle the LED
  Serial.println  ("SPI TEST: " + String(counter));
  digitalWrite    (LED_BUILTIN, HIGH);
  delay           (125);
  digitalWrite    (LED_BUILTIN, LOW);
  delay           (125);

  mySPI.beginTransaction  (MCP3008);                                // Use the SPI configuration
  digitalWrite            (MYSPI_NSS, LOW);                         // Drive MYSPI CS Low
  mySPI.transfer          (0x01);                                   // Transmit Start Bit <---- CODE HANGS HERE
  dataMSB =               mySPI.transfer(readAddress << 4) & 0x03;  // Send readAddress and receive MSB data, masked to two bits
  dataLSB =               mySPI.transfer(JUNK);                     // Push junk data and get LSB byte return
  digitalWrite            (MYSPI_NSS, HIGH);
  mySPI.endTransaction    ();
  
  return               dataMSB << 8 | dataLSB;

}

I have used the spi2 port (as i2s) on the stm405 mmod, though I was using PB12,13,14,15.

Your pins should work – did you init the pins as alternate functions, and set them to AF5?

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_Init(…)

GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);