v2n-gd32-bridge-functional
Single-pass functional validation of the V2N module's GD32G553 supervisor-MCU bridge, followed by a forever PWM7 duty staircase as a live oscilloscope observable.
Where v2n-gd32-bridge-hil-soak proves the link (every opcode answers, forever), this app proves the functions: each test drives a bridge surface with a known stimulus and asserts the value that comes back. sqrt(4) is 2.0. sin(π/2) is 1.0. A TRNG pull has entropy. An invalid ADC configuration is rejected. A PWM setpoint reads back within tolerance.
Source: examples/v2n/v2n-gd32-bridge-functional/.
Like the soak and v2n-gd32-bridge-ping, this is a maintainer bench tool in example form. It exercises the gd32g553 chip driver directly — the documented exception to the portable-API rule for dedicated bridge demos.
What it tests (one pass, in table order)
- TMU math — every native CORDIC primitive value-asserted in F32 (sqrt, sin, cos, atan, atan2, hypot, log, sinh, cosh) plus a Q31 sqrt.
tan/exp/tanhmust answerALP_ERR_NOSUPPORT— there is no native mode for them, so a wrong value here would be a defect. - TRNG — two 16-byte pulls with the documented one-retry fault-recover tolerance. Asserts non-constant bytes, and that the second pull differs from the first.
- PWM — 1 kHz / 50 % setpoint on channel 7 with readback within one tick.
pwm_configuredefaults must answer OK; the center-aligned knob may answerNOSUPPORT(a documented partial). - ADC — the illegal 14-bit / no-oversampling combination must be rejected (
INVAL/NOSUPPORT), then all 8 channels are swept against the physical ceiling. - DSP chain pool — lifecycle open, accepting the documented pre-wave-2
NOSUPPORTcontract. - Identity —
GET_VERSIONtwice (must be stable), and the DA9292 status forward returns the0xFF"no nets on this HW rev" sentinel.
Reading the verdict — there is no console on this SoM
The M33 target has no console. Results publish to a RAM verdict block: find the func_results symbol in zephyr.map and read it over the DAP.
| Word | Meaning |
|---|---|
[0] | 0xF07C7E57 magic |
[1] | State: 1 = testing, 2 = staircase running (tests done), 0xDEAD = link never came up |
[2] | Pass count |
[3] | Fail count |
[4+i] | Per-test result: 0 = PASS, 0x7E = value assertion failed (status was OK), anything else = the failing alp_status_t |
[40] | Staircase: current duty per-mille (live) |
[41] | Staircase: step counter (liveness) |
The 0x7E code is the interesting one — it separates "the wire worked but the answer was wrong" from "the transport failed."
The scope observable
After the suite the app parks in a forever PWM7 duty staircase: a 1 kHz carrier whose duty walks 10 % → 90 % in 10-point steps, 2 s per step, then wraps.
PWM7 doubles as the EVK LED pad, so a scope probe shows the high time visibly widening every 2 s — and the naked eye sees a brightness ramp. Every step is a fresh PWM_SET + PWM_GET pair over the bridge, so the staircase doubles as a slow link soak.
board.yaml
som:
sku: E1M-V2M101
preset: e1m-x-evk
cores:
a55_cluster:
os: "off"
m33_sm:
app: ./src
# SPI is the 25 MHz fast path under test; I2C is enabled so the
# driver's hybrid surface compiles (the suite passes i2c = NULL --
# BRD_I2C correctness has its own HIL coverage).
peripherals:
- spi
- i2c
chips:
- gd32g553
diagnostics:
log_level: info
Status
build_only: true on native_sim/native/64 — there is no GD32 to answer off-silicon, so CI proves compile + link only. Every value assertion is a bench signal.
See also
v2n-gd32-bridge-ping— minimal liveness probev2n-gd32-bridge-hil-soak— full-opcode forever soakv2n-gd32-bridge-loopback— the jumpered tier that closes the loop in copperv2n-gd32-swd-flash— bridge firmware recovery- GD32 bridge protocol — wire spec
- Chip catalogue — the
gd32g553host driver API - Examples overview