FlexIO0 SPI-controller TX shifter (SHIFTCTL, PINCFG=11b) never drives its output pin, despite SHIFTS

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FlexIO0 SPI-controller TX shifter (SHIFTCTL, PINCFG=11b) never drives its output pin, despite SHIFTS

35 Views
hafeezmhd
Fresh Out Contributor

Board: FRDM-MCXN236 (MCX N236, dual Cortex-M33)
Toolchain: MCUXpresso IDE 25.6.136, bare-metal register-level C (no SDK peripheral drivers)
RM reference: MCX N23x Reference Manual Rev. 4, 2025-03-05, Chapter 53 (FlexIO), Table 453 (SPI controller, CPHA=0 configuration)

What I am building:

FlexIO0 configured as an SPI controller per RM Table 453: 2 shifters (shifter0 = TX, shifter1 = RX) + 1 timer (timer0 = SCK, dual 8-bit counter baud mode), reading a BME280 sensor over SPI. Pins: P1_0/P1_1/P1_2 muxed to ALT6 (FLEXIO0_D8/D9/D10), confirmed correct via PORT1->PCR readback.

Observation:
The RX shifter and the SCK timer output both work perfectly — SCK toggles cleanly and on-schedule (confirmed via two independent registers, see below), and SHIFTSTAT/TIMSTAT report normal, on-time, error-free completion of every transfer. But the TX shifter's own output pin (SDO, D8) never shows any electrical movement whatsoever, regardless of what's written to it, under every variation I've been able to think of. The chip-ID register read back from the sensor is always 0x00, never the expected 0x60 (which a separate, working FlexComm/LPSPI3 driver on the same board, same sensor, same boot, reads correctly).

Register configuration (matches RM Table 453 exactly, PINSEL substituted for real pins)

SHIFTCFG0 = 0x0000_0000 (RM: 0000_0000h -- start/stop bit disabled)
SHIFTCTL0 = 0x0083_0002 (RM: 0083_0002h, PINSEL=8 for our real D8/SDO)
decodes to: TIMSEL=0, TIMPOL=1(neg edge), PINCFG=3(11b, driven output),
PINSEL=8, PINPOL=0, SMOD=2(Transmit) -- every field verified against RM's
literal example, only PINSEL substituted
SHIFTCFG1 = 0x0000_0000
SHIFTCTL1 = 0x0000_0101 (RM: 0000_0101h, PINSEL=10 for our real D10/SDI)
TIMCMP0 = derived per RM's own formula (8-bit frames, baud divider for 1MHz SCK)
TIMCFG0 = 0x0100_2222 (RM literal value, no pin substitution needed)
TIMCTL0 = 0x01C3_0201 (RM: 01C3_0201h, PINSEL=9 for our real D9/SCK)

What I've ruled out, each via direct hardware evidence (debugger register/memory inspection, no oscilloscope available):

  1. Pin mux not reaching ALT6 -- PCR readback confirms correct ALT6 config on all four pins used.
  2. Sensor/wiring fault -- a separate, working FlexComm/LPSPI3 SPI driver reads the chip ID (0x60) correctly from the same physical sensor, same boot.
  3. SCK never toggling on the physical pin -- confirmed toggling via TWO independent registers sampled at the same instants: FLEXIO0->PIN (bit 9) and GPIO1->PDIR (bit 1, a completely separate peripheral block with no FlexIO-internal logic in its path). Both agree, in real time, sample for sample.
  4. TX byte-lane placement in SHIFTBUFBIS (the bit-swapped alias register) -- tried the low byte, the high byte (re-derived from RM 53.3.1's shift-register microarchitecture description, not just the summary table), and a byte-lane-agnostic full 32-bit alternating write (0xAAAAAAAA) -- all produce an identical, permanently flat SDO.
  5. TX buffer underrun (SHIFTERR) -- reads 0x0 (clean) every time, captured immediately after a successful RX-ready wait.
  6. Pin/pad-specific fault -- retargeted shifter0's PINSEL to a completely different physical pin (D9 instead of D8); still flat. The timer, using the identical PINCFG=11b "driven output" mechanism, drives either pin correctly.
  7. "Implicit load on enable" (RM 53.3.1: the shifter status flag sets "when data has been loaded from SHIFTBUF into the shifter or when the shifter is initially configured for Transmit mode" -- i.e. a possible stale first-cycle load) -- ruled out via a throwaway first transfer followed by a traced, unambiguously-second transfer: identical flat result.
  8. SHIFTBUFBIS alias write-path asymmetry -- wrote the same byte-lane-agnostic pattern through the plain, non-aliased SHIFTBUF[0] register instead of SHIFTBUFBIS[0]: identical flat result.
  9. FLEXIO0->PINOUTD/PINOUTE/PINOUTDIS (the global per-pin software output-override registers, RM 53.3.3.3) -- live readback shows all zero, meaning "controlled by timer/shifter configuration" (the normal state) on both the working SCK pin and the non-working SDO pin identically. Not the cause.
  10. FLEXIO0->PIN readback itself being unreliable -- see #3 above; independently confirmed via GPIO1->PDIR.
  11. Shifter0-instance-specific defect -- reproduced the identical flat result using shifter2 instead, configured with the bit-for-bit identical SHIFTCTL value. Same failure. Not instance-specific.
  12. RM 53.7.1.27's documented two-step PINCFG write sequence (write 10b first, then a separate write to 11b, to avoid a brief low glitch on first configuration) -- applied directly: identical flat result.

I also checked the one published mask-set errata document for this part (MCXN23x_0P21K Rev. 2.0) -- no FlexIO-related entries at all -- and NXP's own FlexIO-SPI application note (AN12780), which adds no guidance beyond what RM Table 453 already documents.

Question:

Given the shifter's internal bookkeeping (SHIFTSTAT, SHIFTERR, TIMSTAT) reports completely normal, on-schedule, error-free Transmit-mode operation on every test — including the TX-ready flag correctly clearing and re-setting across multiple transfers within the same CS-bracketed transaction, which per RM 53.3.1 should only happen on a genuine timer-triggered reload — and the shift clock itself (same PINCFG=11b "driven output" mechanism, just via TIMCTL instead of SHIFTCTL) is independently proven to reach its physical pin correctly:

Is there a known silicon behavior, an undocumented prerequisite, or an RM gap that would prevent a shifter's SHIFTCTL.PINCFG=11b Transmit-mode output specifically (as opposed to a timer's identical PINCFG=11b output) from reaching its assigned pin, on the MCXN23x mask set, even though every register-level configuration matches RM Table 453's own worked example exactly?

Happy to share the full register-level project source and a complete, append-only investigation log (every hypothesis tried, every retraction, with exact hardware evidence for each) if useful.

 

 

Labels (1)
0 Kudos
Reply
0 Replies