Skip to content

The STM32G474RE and the NUCLEO-G474RE: a second STM32 family - #118

Open
teo1747 wants to merge 10 commits into
mainfrom
feat/nucleo-g474re
Open

teo1747 wants to merge 10 commits into
mainfrom
feat/nucleo-g474re

Conversation

@teo1747

@teo1747 teo1747 commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

A second STM32 family on the bench: the STM32G474RE and ST's NUCLEO-G474RE (MB1367), the first stage of the board. The G4's clock, power and flash IP, its U(S)ARTs/LPUART, and the shared GPIO, EXTI, timers, CRC and watchdogs are modelled: 41 of the part's 82 peripheral blocks (docs/coverage.md). The ADCs, DACs, comparators, op-amps, I2C, RTC, FDCAN, USB, HRTIM, the math accelerators and the rest keep their registers until the next PRs.

The MCU

  • st/stm32g474re: registers from ST's Apache-2.0 STM32G474.svd v3.0. tools/importers/stm32g474_regs.sh corrects it where RM0440, stm32g474xx.h or the HAL disagree, among them:
    • RCC_CR's reset value (the SVD copies the L4's MSI);
    • EXTI's IMR reset values, from the HAL's line types;
    • PWR_SR2's PVMO bits;
    • the timers' OCxM[3] bits, which ST's file leaves out;
    • TIM2's 32-bit CNT;
    • misplaced interrupts.
  • LQFP64 pinout, analog map and alternate functions from ST's open pin data; the DMAMUX request numbers from the HAL.
  • New models:
    • stm32g4-rcc: HSI16, HSE, LSI, LSE, HSI48, the PLL's P, Q and R outputs, kernel clocks, the voltage range and wait-state limits;
    • stm32g4-pwr: ranges and boost, the PVD, Stop 0/1, Standby with SRAM2 and pull retention, Shutdown, the wake-up pins;
    • stm32g4-flash: double-word and fast programming, page and bank erase with read-while-write between banks, the option bytes with complements, OBL_LAUNCH, BOOT0 on PB8 or nBOOT0;
    • stm32-usart-v2: FIFOs, 7/8/9-bit frames, MSBFIRST, DATAINV, SWAP, DE, character match, receiver timeout, wake-up from Stop;
    • stm32g4-dma and stm32g4-dmamux: DMA1 and DMA2's eight channels (memory to memory, table 89's packing, circular mode, the flags and the bits locked while EN is set, a bus error's TEIF), DMAMUX's sixteen channels on the 115 request lines with synchronisation (NBREQ, SOF), event generation, the four request generators (OF) and DMAMUX_OVR.
  • Shared models taught the G4:
    • GPIO's BRR;
    • SYSCFG;
    • EXTI's two banks;
    • the programmable CRC;
    • the IWDG's window and its option-byte hardware start and freeze;
    • the WWDG's 3-bit prescaler;
    • DBGMCU;
    • the timers' TISEL clocks, and freeze bits found by name;
    • the SPIs, as the FIFO SPI: 4 to 16-bit frames, the 32-bit FIFOs (TXE, FRXTH, FTLVL, FRLVL, OVR), packed accesses, LDMA_TX/LDMA_RX, CRC8/CRC16 (CRCL), NSSP.

The board

  • emblink/nucleo_g474re, built from MB1367 D-01's schematic with every part's designator and value:
    • the 24 MHz crystal X3 and the 32.768 kHz X2;
    • U4 (STMPS2151STR) with C11, C5, R8 on T_PWR_EN, and LD4 with R1 on its FAULT;
    • U11 and U12 with their capacitors;
    • JP5's four supply positions (STLK, VIN, E5V, CHGR), JP6 (IDD), JP7 with R31;
    • VREF from U14 (TL1431CL5T) and Q2 at 2.5 x (1 + 10k / 33k) = 3.26 V, on VREF+ through JP8's factory position, C47 and L2;
    • VDD's, VDDA's (through L1) and VBAT's decoupling;
    • LD2 switched by Q1 from 3V3 (R25, R29, R28), so LD2's current doesn't pass JP6's ammeter;
    • B1 active high as the schematic draws it: VDD through B1, R26 to ground, R27 and C35 on PC13;
    • LD3, B2 and C34 on NRST;
    • the Arduino and morpho connectors, the VCP on LPUART1;
    • the option bytes as ST ships the board (nSWBOOT0 0);
    • original 2D artwork (JP8 and LD4 included) and seven fixtures: USB, VIN, E5V, VIN without JP5, the IDD ammeter, B1, LD2 through Q1.
  • Two parts the board needed:
    • emblink/tl1431cl5t: ST's TL1431 shunt reference in SOT23-5L. VREF is 2.500 V, the amplifier has figure 19's open-loop gain, Ioff matches, and a 1 mA step settles within figure 22's microsecond (five fixtures).
    • emblink/bsr14: the BSR14 NPN with onsemi's SPICE model. Fixtures cover VCE(sat) and VBE(sat) at 150 mA and 500 mA, and MB1367's LD2 circuit.
  • A board can now give its MCU's memory as shipped (mcu.memory), and an MCU model can decide the boot (boot_pin/boot_system).
  • examples/nucleo-g474re-blink-serial and gallery shots (Design, Run, the board's 2D face).

Evidence

  • test_stm32g4: 16 tests, 147,605 checks, the DMA and SPI tests among them.
  • tests/vendor/stm32cubeg4/run.py runs 26 unmodified STM32CubeG4 NUCLEO-G474RE examples under scenarios, and it is added to CI's linux-gcc job:
    • GPIO_IOToggle, GPIO_EXTI;
    • HAL_TimeBase_TIM, RCC_ClockConfig;
    • UART_Printf;
    • the four CRC examples;
    • CORTEXM_ModePrivilege, ProcessStack, SysTick;
    • FLASH_EraseProgram and FastProgram, with their timing;
    • IWDG_Reset, IWDG_WindowMode, WWDG_Example;
    • PWR_STOP0;
    • TIM_PWMOutput, TIM_OCToggle;
    • DMA_FLASHToRAM and LL's DMA_CopyFromFlashToMemory_Init;
    • UART_HyperTerminal_DMA (USART2 on PA2/PA3) and UART_ReceptionToIdle_CircularDMA (LPUART1);
    • SPI_FullDuplex_ComPolling and SPI_FullDuplex_ComDMA on two boards (the runner builds each example's _Master and _Slave projects).
  • The whole catalog validates: 2410 ok, 4635 fixtures.
  • The example passes its 10 checks, and LD2 draws 2.5 mA through Q1 in it.
  • dev and ci-clang build without warnings and pass the suite, except real_captures/tools_unittests. Those two fail only on this machine: Homebrew's libsigrok installs a sigrok namespace package that shadows tools/verify/sigrok.py.

Checked against ST's documents

  • The board against MB1367 D-01's schematic (part by part) and UM2505 Rev 7: the STLINK-V3E's 5 V path, the solder bridges in their factory state (CN10 pins 35/37 on USART1), JP8 and VREF+, the crystals' part numbers.
  • B1 is active high, which the schematic shows. CubeG4's GPIO_EXTI takes the falling edge, so on this board it toggles LD2 on the release, as it does on a real board; the scenario says so.
  • The part against DS12288 Rev 6 and RM0440 Rev 9: the start-up, flash and PVD values, the reset values, EXTI's direct lines and the package code. The fast-row programming time is now the datasheet's 1.91 ms.

Fixed on the way

  • Exception entry left CONTROL.SPSEL set, so a handler read CONTROL[1] as 1 on every Cortex-M part. ARMv7-M's ExceptionTaken clears it; CubeG4's CORTEXM_ProcessStack found this.
  • The regulator primitive now has a 1 mOhm output resistance while it regulates. At the operating point every capacitor is held at its initial voltage, so an LDO with its input already up faced its own output capacitor as a second ideal source. Newton then cycled between the regulator's modes, and VIN with U11's capacitors didn't solve. The regulator now starts in current limit and charges the capacitor, as a real one does.

The bench

  • A board's console is the UART the firmware muxes onto its bridge's pins (console.tx, console.rx), as the wiring is: the NUCLEO-G474RE's VCP hears USART2 on PA2/PA3 as it hears LPUART1.
  • A pin given another alternate function hears its level at once: SPI1's SCK on PB3, after the reset's AF0, saw nothing until its first edge, which a slave took as its baseline (every byte one bit off).
  • An EXTI line that SYSCFG gives another port sees the new pin's level at once, an edge when it differs (STM32F4 and G4).
  • An analog island is still when its branch currents move by less than a nanoampere and a millionth of their value; node voltages keep their microvolt test. An LED warming by picoamps, or a ferrite bead's numerical ringing, no longer keeps a supply island stepping every quantum. The G474RE example takes 9 s of CPU, down from 33.

Declared, not yet done

  • The timers' G4 additions: OCxM/SMS fourth bits, channels 5 and 6, dithering, the encoder index, the G4's ITR table.
  • The STLINK-V3E itself: its USB, SWD and drive.
  • SPI_FullDuplex_ComIT: the master's fourth received byte loses a bit; the slave's MISO change, made in its TXE interrupt, reaches the line after the master's next sample. It stays out of the suite until the two boards' timing is solved.
  • Functional policy: the board's resistors are wires there, so R28/R29 tie PA5 to GND and R26/R27 tie PC13; LD2 and B1 work in the electrical policy (declared in the fidelity).
  • Two boards on SPI run about 230 times slower than real time under the electrical policy: their supply islands step with the bus's edges.
  • IWDG_Reset: its "invalid address" 0x00040001 lies inside the G474's 512 KiB flash alias. The store sets PGSERR without a fault, so on this part the example's reset doesn't come. The scenario says so; this is not checked on a board.

- svd2regs.py: --strip-prefixes (TIM2_CR1 in TIM2 named CR1, as ST's
  STM32G4 file prefixes them), --rename, and --drop leaving the
  peripherals derived from the dropped one its registers (the G4's FDCAN
  listed at its message RAM's address).
- stm32pins.py: a pin whose ADCs number it differently lists each group
  (the G4's PB0: "ADC1_IN15, ADC3_IN12"); esk_rf_analog_pin reads them.
- dma_requests: a DMAMUX's request inputs by number (0 to 255).
ARMv7-M's ExceptionTaken sets CONTROL.SPSEL to 0: a handler entered from
a thread on the process stack reads CONTROL[1] as 0, and EXC_RETURN sets
it again. The core switched stacks but left the bit set, which
STM32CubeG4's CORTEXM_ProcessStack found.
- st/stm32g474re: registers from ST's STM32G474.svd v3.0 with the
  corrections tools/importers/stm32g474_regs.sh applies, the LQFP64
  pinout, analog inputs and alternate functions from ST's open pin data,
  the DMAMUX's request numbers, the memory map with both banks' option
  bytes, the engineering bytes, SRAMCAN and the USB packet memory.
- New models: stm32g4-rcc, stm32g4-pwr, stm32g4-flash and stm32-usart-v2
  (USARTs, UARTs and LPUART of the ISR/ICR layout).
- Shared models taught the G4: GPIO's BRR, SYSCFG, EXTI's two banks, the
  programmable CRC, the IWDG's window and option bytes, the WWDG's 3-bit
  prescaler, DBGMCU's names, the timers' TISEL clocks and freeze bits.
- A board can give its MCU's memory as shipped (mcu.memory), an MCU
  model the boot's choice (boot_pin, boot_system: BOOT0 on PB8).
- test_stm32g4: 13 tests.
- emblink/nucleo_g474re (MB1367): X3 24 MHz and X2, LD2, LD3, B1, B2,
  JP5's four supply positions, JP6, JP7, U11, U12, the Arduino and morpho
  connectors, the VCP on LPUART1, the option bytes as ST ships the board,
  original artwork and six fixtures.
- examples/nucleo-g474re-blink-serial: 170 MHz from the crystal, LD2, B1
  and the echo on LPUART1; gallery shots.
- tests/vendor/stm32cubeg4: 21 of CubeG4's NUCLEO-G474RE examples built
  unmodified and run under scenarios, also in CI's linux-gcc job.
The filter's look-back took ti + (es_time_t)(tt * 1e12) with tt <= 0,
undefined behaviour that clang's -fsanitize=undefined reports; it is
ti - (es_time_t)(-tt * 1e12), the same sample times.
- The board as UM2505 Rev 7 gives it: U4 (STMPS2151STR) and LD4 in the
  STLINK-V3E's 5 V path, CN10 pins 35 and 37 on USART1 as the factory
  solder bridges leave them, VREF+ on its own net (CN5 pin 8, CN10 pin 7)
  through JP8 and the ferrite bead L2, VDDA through L1, the crystals'
  parts (NX2016SA 24 MHz, NX3215SA), DS12288's decoupling scheme.
- DS12288 Rev 6: a fast-programmed row takes 1.91 ms; the PVD has its
  falling and rising thresholds; the start-up and flash times confirmed.
- RM0440 Rev 9: the package code (LQFP64) in the engineering bytes; the
  reset values and EXTI's direct lines confirmed.
- STM32CubeG4's examples: 20, as the suite holds them.
Every part of MB1367 D-01 with its designator and value: U4's path with
C11, C5, R8 and LD4 on FAULT; U11's and U12's capacitors; the supplies'
decoupling; VREF from U14 (TL1431CL5T) and Q2 at 3.26 V on VREF+
through JP8's factory position; LD2 switched by Q1 from 3V3; B1 active
high as the schematic draws it (R26, R27, C35). The example counts B1's
rising edges; CubeG4's GPIO_EXTI toggles LD2 on the release, as on a
board. JP8 and LD4 on the artwork; a fixture for LD2 through Q1.

emblink/tl1431cl5t: the shunt reference against ST's datasheet (VREF,
figure 19's open-loop gain, Ioff, figure 22's step). emblink/bsr14: the
BSR14 with onsemi's SPICE model, VCE(sat) and VBE(sat) fixtures.

The regulator primitive's output has 1 mOhm while it regulates: an LDO
with its input up at the operating point no longer faces its output
capacitor's initial-voltage source as a second ideal source, which made
Newton cycle (9 V on VIN did not solve).
stm32g4-dma: eight channels a controller, one item a request or memory
to memory, table 89's packing, circular mode, HT, TC, TE and GIF, the
bits locked while EN is set, a bus error's TEIF. stm32g4-dmamux: sixteen
channels on the 115 request lines, synchronisation on an EXTI line or a
channel's event (NBREQ, SOF), event generation, the four request
generators (OF), DMAMUX_OVR. test_stm32g4 covers them; CubeG4's
DMA_FLASHToRAM, LL DMA_CopyFromFlashToMemory_Init, UART_HyperTerminal_DMA
and UART_ReceptionToIdle_CircularDMA run unmodified (24 examples).

A board's console is the UART the firmware muxes onto its bridge's pins,
as the wiring is: the NUCLEO-G474RE's VCP hears USART2 on PA2/PA3 as it
hears LPUART1. An EXTI line SYSCFG gives another port sees the new pin's
level at once (an edge when it differs).

An analog island is still when its branch currents move by less than a
nanoampere and a millionth (nodes keep their microvolt test): an LED
warming and a ferrite bead's numerical ringing no longer keep a supply
island stepping every quantum. The G474RE example: 9 s of CPU, was 33.
spi.c learned RM0440 42's SPI: 4 to 16-bit frames (DS, 8 bits forced for
the values not used), the 32-bit transmit and receive FIFOs (TXE at
half, RXNE at FRXTH's threshold, FTLVL, FRLVL, OVR when full), packed
16-bit accesses to DR, LDMA_TX and LDMA_RX, CRCL's CRC8 and CRC16 (two
frames after 8-bit data), NSSP's pulse. test_stm32g4 covers it, and
CubeG4's SPI_FullDuplex_ComPolling and _ComDMA run on two boards
(run.py builds an example's _Master and _Slave projects; 26 examples).
SPI_FullDuplex_ComIT stays out: the master's fourth byte loses a bit,
the slave's MISO change in its TXE interrupt reaching the line late.

gpio_f4.c: a pin given another alternate function hears its level at
once; SPI1_SCK on PB3, after the reset's AF0, saw no level until the
first edge, which a slave took as its baseline.

The board's fidelity declares that its resistors are wires in the
functional policy (LD2 and B1 work in the electrical one).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant