Skip to main content
Visitor II
September 1, 2026
Question

ISM330DHCX + MMC5983MA locked in I2C mode on custom STM32G474 PCB, never respond in SPI

  • September 1, 2026
  • 4 replies
  • 66 views

Hello everyone,

I'm working on a custom PCB (professionally soldered, LGA packages) built
around an STM32G474RET6, and I'm stuck on a communication issue with two
of my three SPI sensors. I'd really appreciate some insight from anyone
who has run into this before.

My setup:
- Host MCU: STM32G474RET6
- Shared SPI3 bus: SCK=PC10, MISO=PC11, MOSI=PC12
- TMAG5170 (SPI-only magnetometer), CS=PA11
- ISM330DHCX (IMU), CS=PD2
- MMC5983MA (magnetometer), CS=PA12

The symptom I'm seeing:
My TMAG5170 communicates perfectly over SPI, which tells me my SPI3 bus,
my shared SCK/MISO/MOSI wiring, and my power rail are all healthy.
However, my ISM330DHCX and MMC5983MA never respond in SPI mode — WHO_AM_I
/ Product ID reads keep returning garbage (0xFF).

Here's what I've already tried:

1. I ruled out a software bug by switching from separate
   HAL_SPI_Transmit / HAL_SPI_Receive calls to a single
   HAL_SPI_TransmitReceive — no change.
2. I checked for solder bridges under the LGA packages with a multimeter
   (MISO to 3V3, MISO to GND) and found no short.
3. I added a 10k pull-down on MISO, and my reading changed from 0xFF to
   0x00. This tells me MISO is genuinely floating while my ISM CS is
   asserted — the sensor never drives the bus in SPI mode.
4. I checked the decoupling caps near my ISM330DHCX footprint and I'm
   seeing 3.3V there, so local power delivery looks fine to me.
5. I added a 4.7k pull-down directly on CS (PD2), hoping to force SPI
   selection from power-on, but it had no effect — WHO_AM_I still reads
   garbage in SPI mode.
6. I bit-banged I2C on the same physical pins (SCL=PC10, SDA=PC12, with
   external 4.7k pull-ups added), and my ISM330DHCX responded reliably
   and correctly: WHO_AM_I = 0x6B, stable. So I know my sensor is alive,
   properly powered, and correctly wired — it just seems locked into
   I2C mode.

My question:
My previous board (STM32L4-based, same schematic minus 33R series
resistors on MOSI/SCK) worked fine in SPI without any CS pull-down. So I
suspect a POR timing race on my new board: my sensor might be sampling
CS before my G4 finishes MX_GPIO_Init() and drives CS low, latching I2C
mode before my firmware even gets a chance to configure the pin.

- Is CS interface selection on the ISM330DHCX / MMC5983MA sampled once
  at POR and latched, or is it checked continuously during subsequent
  SPI transactions?
- What CS pull-down value (and rough timing margin) would you recommend
  to reliably guarantee SPI mode selection across a typical MCU/regulator
  power-up sequence?
- Is there any known erratum or app note covering this kind of
  interface-selection race condition?

I'm happy to attach a schematic snippet or my test firmware if that
would help diagnose this. Thanks a lot in advance for any pointers!

4 replies

Ozone
Principal
September 2, 2026

From your description, it sounds like the MEMS devices determine between I2C and SPI at runtime, according to the /CS level.

> My TMAG5170 communicates perfectly over SPI, which tells me my SPI3 bus, my shared SCK/MISO/MOSI wiring, and my power rail are all healthy.

SPI is not a narrow standard like I2C.
I suggest you compare all three datasheets, especially the SPI interface sections.
Most common issue are the two clock-related options CPOL and CPHA, which define the clock polarity and the data sampling edge.
If those are not identical for all three devices, you cannot operate them at the same bus - unless you reconfigure those settings every time.
It sounds like you SPI settings are fine for the TMAG5170, but not for the others.

I always recommend to use a scope or logic analyzer, record a transmission sequence, and compare it to the datasheet.

Associate
September 2, 2026

I don't think it's a CPOL/CPHA mismatch in this case — the ISM330DHCX datasheet explicitly says it supports SPI modes 0 and 3, and the code here is configured for mode 0 (SPI_POLARITY_LOW + SPI_PHASE_1EDGE), so that should be compatible. Also, a clock polarity/phase mismatch would typically produce garbled/shifted data on the bus, not a clean floating line reading 0xFF/0x00 depending on the external pull resistor — that pattern points to nothing driving the line at all, not misaligned sampling.

Associate
September 2, 2026

I checked the ISM330DHCX datasheet section on the I²C/SPI interface, and there's no mention of a power-on latch. The CS pin is just a live signal, same as the SPI protocol enable line: CS high (tied to VDD_IO) selects I²C, CS low selects SPI — it's checked continuously, not sampled once at POR. So the "race condition at startup" theory doesn't match the datasheet.

On your pull-down experiment: since CS is a live signal (not a static level to be biased), adding an external pull-down doesn't help — your firmware is already correctly driving it low/high per transaction via HAL_GPIO_WritePin. I'd remove that pull-down; it's not doing anything useful here and could interact badly with your SPI's normal idle-high state.

Given the floating MISO you measured, I'd put a scope or logic analyzer directly on the sensor's pins (CS/SCK/MOSI/MISO at the chip, not just at the MCU) during a transaction, to confirm whether a valid SPI frame is actually reaching the device.

 

TDK
September 2, 2026

The CS value is actively monitored to determine I2C/SPI.

Consider that your results are consistent with the CS pin not actually being held low. Likely, this is the problem. Recheck your assumptions. It’s a hard package to solder.

Consider trying the I2C interface when CS is “held” low. If it responds, it is not being held low.

Using this sensor on an SPI bus with other sensors isn’t really doable since the I2C interface is activated when CS is released. When CS is high, the I2C interface is active so any activity on SDA/SCL will be clocked and responded to if appropriate. Maybe you can ensure that the signal is never valid, but seems unlikely to rule out entirely.

"If you feel a post has answered your question, please click ""Accept as Solution""."