Skip to content

0006. Monitor: U3 attachment is the shared session, not VC_CORERESET

Date: 2026-09-03

isMonitorEnabled() on the STM32U3 mailbox path stopped consulting MONCONNECTED (DEMCR.VC_CORERESET). A host timeout path could leave the flag set, latching "attached" for the rest of a boot and holding the tag at about 1 mA. Extracted verbatim from Tag Monitor Interface.

Context, decision and evidence

isMonitorEnabled() consulted MONCONNECTED on every target, which contradicted the paragraph above and cost the U3 tags their sleep.

DEMCR.VC_CORERESET is set by the host as an attachment flag -- the host code says so in as many words, at host/libraries/tagcore/tagmonitor.cc:

// VC_CORERESET is used as attachment flag to embedded app.

The host has two resume paths after a failed monitor call. One clears the flag; the other, taken when the timeout probe has halted the target, resumes with (demcr | MON_EN | VC_CORERESET) and deliberately leaves it set. Nothing on the tag clears VC_CORERESET except monitorSharedSetDisconnected(), which runs only from a session teardown -- and a teardown needs a session. So one timed-out monitor call latched "attached" for the rest of that boot:

  • every sleep path refused, because they all gate on isMonitorEnabled();
  • the main loop took its blocking chEvtWaitAny() branch;
  • the tag drew about 1 mA instead of 6 uA, indefinitely;
  • only a reset recovered it, because the reset command established a fresh session whose teardown then cleared the flag.

Measured on an IMUTagNandBmp581 at 3.29 V: 1037-1040 uA whenever a monitor call had timed out, with demcr=0x1000001 in the timeout dump, against 5.8-6.3 uA whenever it had not. Eight logic-analyser channels were silent throughout the fault -- no NAND, no SPI, no I2C, no sensor data-ready -- so the current was the core alone, not stranded peripheral activity.

The fix restores what this document specified: on the mailbox path isMonitorEnabled() is monitorIsAttached() || monitorAttachGraceActive(), gated by TAG_MONITOR_MAILBOX so L4 keeps vector catch as its attach mechanism. MONCONNECTED is deliberately retained in monitorResetRecoveryActive(), where the question genuinely is whether a debugger connected under reset; it was only ever wrong as a liveness test.

Verified by 160 attach/detach cycles down to 400 ms attached / 250 ms detached with zero timeouts and zero errors, the tag answering on every cycle, and idle at 5.43-5.50 uA afterwards. That test matters because the risk of ignoring the hint is the opposite failure: a tag that sleeps while a host is still reaching for it would show up as attach timeouts.