Skip to content

docs(fusa): [c-RCP-18-tracker Part 1] propagate tc18_master_id for REQ-CAN-*/REQ-GPIO-*/REQ-PWM-*/REQ-SPI-*/REQ-UART-*/REQ-WAKEUP-* - #110

Merged
SoundMatt merged 1 commit into
mainfrom
tc18-533-propagate-can-gpio-pwm-spi-uart-wakeup-master-id
Aug 19, 2026
Merged

SoundMatt merged 1 commit into
mainfrom
tc18-533-propagate-can-gpio-pwm-spi-uart-wakeup-master-id

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

docs(fusa): [c-RCP-18-tracker Part 1] propagate tc18_master_id for REQ-CAN-/REQ-GPIO-/REQ-PWM-/REQ-SPI-/REQ-UART-/REQ-WAKEUP-

Scope note: REQ-CAN-* does not exist in cpp-RCP's .fusa-reqs.json. Unlike
go-RCP (where a REQ-CAN-* client-ergonomics wrapper package canbr still
exists alongside the real endpoint's REQ-CANEP-), cpp-RCP's canbr.hpp/
linbr.hpp bridge stubs — which historically used REQ-CAN-001..004/
REQ-LIN-001..004 (ROADMAP.md, "44 requirement entries that back the
deleted packages") — were already DEPRECATEd and deleted outright in a
prior milestone, and their requirement entries pruned from
.fusa-reqs.json entirely (README.md: "CAN and LIN are native TC18
Endpoint types ... not bridge targets, so this package carries no
canbr.hpp/linbr.hpp"). REQ-CANEP-
(the real CAN endpoint) was already
linked in PR #109. So there is nothing to link under REQ-CAN-* here: 0
entries exist under that prefix.

This batch instead covers cpp-RCP's remaining per-endpoint-type packages:
REQ-GPIO-* (9), REQ-PWM-* (7), REQ-SPI-* (5), REQ-UART-* (7),
REQ-WAKEUP-* (5) — 33 entries in scope, 24 linked, 9 deliberately skipped.

Section numbers verified directly against TC18.txt (not assumed from
memory or from go-RCP's citations, which use a different section
layout for at least PWM):

  • GPIO: §13.7.4 (NOT §13.7.3 as originally guessed — §13.7.3 is SPI)
  • SPI: §13.7.3
  • PWM_OUT: §13.7.5, PWM_IN: §13.7.6
  • UART: §13.7.8
  • WAKEUP: §13.7.2
  • Shared evt-field semantics table (GPIO/PWM_OUT write combinators,
    saturation, ep_type enum, compound-wait): §13.2/§13.5/§13.5.1

== Per-prefix verdict ==

REQ-CAN-*: 0 entries exist (see scope note above). N/A.

REQ-GPIO-* (9 total): 6 linked, 3 skipped.
Linked: 001, 002, 003, 004, 005, 009.
Skipped:
- 006 "GPIO functional config block wiring" — the file's own header
comment explicitly disclaims that "the concrete pin-direction bit
convention, functional-config layout... chosen in this file are
this implementation's own." TC18's actual GPIO functional-config
register map (Table 44, §13.7.4.2) has no pin-direction or
per-pin edge-enable fields at all (only debounce/clock/enable/
status) — linking to Table 44 would be a section-proximity match,
not a content match, the exact mistake PR #109's review caught.
- 007 "GpioEndpoint request-dispatch pattern" — an internal API
orchestration claim (apply write + evaluate triggers + report
bitmask "in one call"); its constituent behaviors are already
individually covered by REQ-GPIO-002/003/004/005's own citations.
Same shape as REQ-MDIO-003 ("MDIO register write-then-read
round-trip"), left unlinked in PR #109 for the same reason.
- 008 "GpioEndpoint error propagation and GpioErrc category" —
implementation-only error-category plumbing, consistent with
every other endpoint's *Errc entries (REQ-SPI-005, REQ-I2C-005,
REQ-ADC-006, REQ-MDIO-005, REQ-UART-007, REQ-PWM-007,
REQ-WAKEUP-005 below) being left unlinked throughout this and the
prior batch.

REQ-PWM-* (7 total): 6 linked, 1 skipped.
Linked: 001, 002 (citation corrected), 003 (citation corrected), 004,
005, 006 (citation corrected).
Skipped: 007 (PwmErrc error category — implementation-only, see above).

REQ-SPI-* (5 total): 4 linked, 1 skipped.
Linked: 001 (citation corrected), 002, 003, 004.
Skipped: 005 (SpiErrc error category — implementation-only).

REQ-UART-* (7 total): 4 linked, 3 skipped.
Linked: 001, 002, 003, 005.
Skipped:
- 004 "UART payload-less pure read requests" — TC18 §13.7.8.1 only
says a UART read carrying a byte_msg_payload is rejected
(UNKNOWN_CMD); it does not define a distinct non-blocking
"pure read" request kind for UART the way §13.7.4.3 explicitly
names one for GPIO. handle_pure_read's own doc comment concedes
this is this implementation's own API convenience ("no read_size
is carried at all, so there is nothing to wait on"), not a
TC18-named UART behavior distinct from what REQ-UART-002/003
already cover.
- 006 "UART RX FIFO / read_size single-AVTPDU accepted limitation"
— this requirement documents a deliberate NON-conformance: TC18
§13.7.8.1 mandates fragmenting the response when read_size
exceeds uart_rx_fifo_size (TC18-13.7.8.1-004); this milestone's
accepted limitation (ROADMAP.md milestone 52, fragmentation
no-go) instead rejects such requests outright. Linking it would
misrepresent a documented gap as coverage.
- 007 (UartErrc error category — implementation-only).

REQ-WAKEUP-* (5 total): 4 linked, 1 skipped.
Linked: 001, 002, 003, 004.
Skipped: 005 (WakeupErrc error category — implementation-only).

== Full id -> master-catalog-id mapping (24 entries) ==

REQ-GPIO-001 -> TC18-13.7.4.1-005 "GPIO request length validation": TC18
requires rejecting any GPIO request not exactly 4 bytes
(INVALID_PARAMETER); matches kGpioPayloadLen=4 / short_buffer.
REQ-GPIO-002 -> TC18-13.5-001 "EP-specific usage of evt-field": Table 33's
GPIO/PWM_OUT row defines evt[2:0]=000b/001b/010b/011b as
Replace/OR/AND/XOR against current interface status; matches
apply_bitmask_write's Replace/Or/And/Xor.
REQ-GPIO-003 -> TC18-13.5-003 "Saturation arithmetic for GPIO/PWM_OUT
add/subtract": "neither overflows nor wrap-arounds... saturated at
0x0000/0xFFFF" — matches the saturating (not wrapping) Add/Subtract
rule directly.
REQ-GPIO-004 -> TC18-13.5-001: same Table 33 GPIO/PWM_OUT row,
evt[2:0]=100b (reserved/rejected) and 111b (reconfigure — endpoint
config change, not a value written to the interface); matches
Reserved-rejected / Reconfigure-retargets-directions split.
REQ-GPIO-005 -> TC18-13.7.4.1-011 "Optional GPIO edge/change trigger
generation": "generates triggers for all its mapped IO-pins on the
change, falling and rising edge" — matches per-pin Change/Rising/
Falling signal evaluation.
REQ-GPIO-009 -> TC18-13.7.4.3-004 "Write to input pin is ignored":
"A write request to an input pin is ignored for this input pin" —
direct match, quote already correct pre-existing; only the line
number and master_id were added.

REQ-PWM-001 -> TC18-13.7.5.3-001 "pwmo request format": "The PWM_out
request and response contain two values in the payload. The active
time... as well as the period" — matches the shared two-field
PwmValue{period, active_duration} shape.
REQ-PWM-002 -> TC18-13.5-001: Table 33 GPIO/PWM_OUT row, evt[2:0]=000b
("byte_msg_payload is presented at the interface") — matches Replace
applying period/active_duration directly. CITATION CORRECTED (was
"Table 30", which is TC18's actual "Error codes in responses" table,
not the evt-field table — the real table is Table 33).
REQ-PWM-003 -> TC18-13.5-003: same saturation clause as REQ-GPIO-003,
applied per-field to PwmValue's uint16_t range. CITATION CORRECTED
(was "Table 30" + "TC18.txt L3694-3714", which points at an unrelated
sequencer request-state-machine passage, not Table 33/the saturation
note at all).
REQ-PWM-004 -> TC18-13.5-001: same Table 33 row, evt[2:0]=100b/111b, as
REQ-GPIO-004 — matches Reserved-rejected / Reconfigure-unsupported
(PWM_OUT has no reconfigure target of its own besides its functional
config registers).
REQ-PWM-005 -> TC18-13.7.6.1-001 "PWM_IN max-period exceeded /
source-loss error notification": "if... the external PWM source
stops, the PWM_IN endpoint will detect this and... notify the RC
Client with an error response message" (error code PWM_IN_NO_SIGNAL,
Table 30) — matches no_signal before first measurement / after
clear_signal().
REQ-PWM-006 -> TC18-13.7.6.1-002 "pwmi trigger outputs": Table 47 defines
exactly two PWM_IN trigger signals (0=rising edge, 1=falling edge) —
matches RisingEdge/FallingEdge notification. CITATION CORRECTED (was
"§13.7.5.1 Table 44" — §13.7.5.1 is PWM_OUT's pin-config section and
Table 44 is GPIO's functional-config register map; the real anchor is
§13.7.6.1 Table 47, the actual "pwmi trigger outputs" table).

REQ-SPI-001 -> TC18-13.7.3.2-006 "Parallel SPI: up to 6 CS
configurations, selected via evt[2:0]": "up to 6 CS signals may be
handled by the SPI endpoint... the SPI bus functional configuration
supports up to 6 different configurations in parallel... determined
by evt[2:0]" — matches kMaxChannels=6, evt[2:0] 0-5 valid / 6,7
rejected. CITATION CORRECTED (was "§13.7.3.1" quoting "up to 6
pre-configurable sets of SPI configurations" at L4192 — TC18.txt
L4192 is CRC/Safe-command-mode text, unrelated; and §13.7.3.1's real
text says "up to 16" pre-configurable sets selected via byte_bus_id,
not evt[2:0] — a known, spec-internal, editorially-flagged
inconsistency between the "16" figure in §13.7.3.1 and the "6" figure
in §13.7.3.2, per master-catalog entry TC18-13.7.3.1-002's own notes.
cpp-RCP's kMaxChannels=6 + evt[2:0] selection matches §13.7.3.2's "6"
clause, not §13.7.3.1's "16" one).
REQ-SPI-002 -> TC18-13.5.1-001 "Compound-wait byte-length mismatch
handling": "the interface status shall be capped to the length of
the byte message payload. For SPI this means that e.g. only the
first four out of 20 received bytes will be checked..." — exact
match, including cpp-RCP's own kCompoundWaitCompareLen=4 /
kMaxStatusBytes=20 constants mirroring TC18's own worked example.
REQ-SPI-003 -> TC18-13.7.3.1-003 "Client byte-send request to SPI
endpoint": "The RC Client can request the SPI endpoint to send one or
more bytes that are delivered as byte_msg_payload..." — matches the
raw PICO-out/POCI-in transfer request/response mechanism.
REQ-SPI-004 -> TC18-13.7.3.1-007 "SPI trigger outputs mapping": Table 41
defines signal 0 = SPI execution done, (2+2n) = CSn asserted,
(3+2n) = CSn de-asserted — matches CsAssert/TransferComplete/
CsDeassert and the per-(channel,signal) distinct SignalId scheme (the
specific notification order is this implementation's own choice,
not spec-mandated, consistent with this file's own disclaimer).

REQ-UART-001 -> TC18-13.7.8.1-001 "UART EP dual independent TX/RX
request storages": "these two processes are independent from each
other, thus the UART EP has two EP request storages" — direct match.
REQ-UART-002 -> TC18-13.7.8.1-002 "UART RX FIFO buffering and overflow
flagging": "the UART EP shifts the received data into a
fifo-rx-buffer... emptied by read requests. Overflow is flagged..."
— direct match.
REQ-UART-003 -> TC18-13.7.8.1-004 "UART read request trigger conditions
and fragmentation sizing": "A read request will be started as soon
as the fifo-rx-buffer is filled with as many bytes as requested in
the read_size or when the uart_timeout has expired" — matches the
read-completion rule. (Citation deliberately quotes only the
read_size/timeout portion, not the fragmentation sentence that
follows it in the same TC18 passage — this implementation's
read_size_exceeds_bound rejection is a documented divergence from
that fragmentation behavior, per REQ-UART-006, not an implementation
of it.)
REQ-UART-005 -> TC18-13.7.8.3-004 "UART EP ignores trailing
non-integer-multiple bits when transmitting": "In case uart_nr_bits
is not a multiple integer of 8... the EP ignores the last up to
'uart_nr_bits - 1' bits..." — matches the sub-octet
mask-to-low-bits/zero-pad-high-bits packing rule.

REQ-WAKEUP-001 -> TC18-13.2-002 "ep_type enumerated values": Table 32
lists 0x01 = WakeUp — matches kEndpointTypeWakeup=0x01. Same
master_id as REQ-CANEP-001/REQ-MDIO-001 from PR #109 (same table,
different row). Deliberately NOT linked to TC18-13.7.2.1-001 ("WakeUp
endpoint fixed at EP nr 1") — that clause is about EP_Nr (instance
position), a different field from ep_type (the type-code value this
requirement actually tests); confirmed by reading endpoint.hpp's own
kEndpointType* constant block, which is exactly Table 32's ep_type
enumeration.
REQ-WAKEUP-002 -> TC18-13.7.2.3-004 "SleepCMD fixed code value":
"SleepCMD is coded as 0xA5." — direct, exact match.
REQ-WAKEUP-003 -> TC18-13.7.2.2-002 "WakeUp functional configuration
register map": Table 39's wup_status register — "Indication of
wake-up source, writing '1' clears the flag. Each bit represents a
wake-up source" — matches record_wake_source_event setting a bit /
clear_wake_source_pins() resetting the mask.
REQ-WAKEUP-004 -> TC18-13.7.2.1-002 "Repetitive wake-up messages after
reconnection": "After establishing a network connection, the WakeUp
endpoint sends repetitive messages. The timing interval is
configurable (flush_time)." — matches the repeating WakeUp-message
handshake for hot-start-from-Sleep.

== Citation corrections found (5) ==

  1. REQ-SPI-001: wrong section (§13.7.3.1 instead of §13.7.3.2), wrong
    quote (misattributed the "6" figure to §13.7.3.1's text, which
    actually says "16"), and wrong line number (L4192 is CRC/Safe-mode
    text, not SPI channel-count text at all).
  2. REQ-PWM-002: "Table 30" corrected to "Table 33" (Table 30 in TC18 is
    "Error codes in responses"; the evt-field table is Table 33).
  3. REQ-PWM-003: same Table 30->33 correction, plus the line range
    L3694-3714 (sequencer request-state-machine text) corrected to the
    real Table 33 saturation-note location, L4094-4119.
  4. REQ-PWM-006: "§13.7.5.1 Table 44" corrected to "§13.7.6.1 Table 47"
    (§13.7.5.1/Table 44 are PWM_OUT/GPIO material; PWM_IN's actual
    trigger-outputs table is §13.7.6.1 Table 47).
  5. REQ-GPIO-009: quote content was already accurate; only the missing
    "TC18.txt L####" line-number suffix was added for consistency with
    every other linked entry's citation format.

Note: REQ-PWM-002/003's own pre-existing text fields also say
"§13.5 Table 30" — left untouched per field-preservation (only tc18/
tc18_master_id are new/corrected fields in this batch); the text
field's wording is a separate, smaller pre-existing inaccuracy not in
this batch's scope to rewrite.

== Deliberately-untouched entries (9) ==
REQ-GPIO-006, REQ-GPIO-007, REQ-GPIO-008, REQ-PWM-007, REQ-SPI-005,
REQ-UART-004, REQ-UART-006, REQ-UART-007, REQ-WAKEUP-005 — reasoning
per-entry above (per-prefix verdict section).

== Verification ==

  • cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DRELAY_BUILD_CLI=ON -G Ninja &&
    cmake --build build --parallel: clean rebuild, 0 errors.
  • ctest --test-dir build --output-on-failure -j1: 53/53 passing
    (matches PR docs(fusa): [c-RCP-18-tracker Part 1] propagate tc18_master_id for REQ-CANEP-*/REQ-I2C-*/REQ-ISELED-*/REQ-LINEP-*/REQ-MDIO-*/REQ-ADC-* #109 baseline).
  • cpfusa v0.18.0 check: 0 errors, 2 warnings, 1 info (unchanged from
    baseline).
  • cpfusa v0.18.0 trace --format json: 376 total/376 traced/376 tested/
    64 secTested (identical before and after — only citation metadata
    fields were added, no requirement entries or test annotations
    changed).
  • git diff --stat: 1 file changed (.fusa-reqs.json only), 67
    insertions(+), 24 deletions(-) — 24 tc18_master_id fields added, 24
    tc18 fields present after (19 new + 5 corrected in place).

Signed-off-by: Matt Jones 47545907+SoundMatt@users.noreply.github.com
Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

…Q-CAN-*/REQ-GPIO-*/REQ-PWM-*/REQ-SPI-*/REQ-UART-*/REQ-WAKEUP-*

Scope note: REQ-CAN-* does not exist in cpp-RCP's .fusa-reqs.json. Unlike
go-RCP (where a REQ-CAN-* client-ergonomics wrapper package `canbr` still
exists alongside the real endpoint's REQ-CANEP-*), cpp-RCP's canbr.hpp/
linbr.hpp bridge stubs — which historically used REQ-CAN-001..004/
REQ-LIN-001..004 (ROADMAP.md, "44 requirement entries that back the
deleted packages") — were already DEPRECATEd and deleted outright in a
prior milestone, and their requirement entries pruned from
.fusa-reqs.json entirely (README.md: "CAN and LIN are native TC18
Endpoint types ... not bridge targets, so this package carries no
canbr.hpp/linbr.hpp"). REQ-CANEP-* (the real CAN endpoint) was already
linked in PR #109. So there is nothing to link under REQ-CAN-* here: 0
entries exist under that prefix.

This batch instead covers cpp-RCP's remaining per-endpoint-type packages:
REQ-GPIO-* (9), REQ-PWM-* (7), REQ-SPI-* (5), REQ-UART-* (7),
REQ-WAKEUP-* (5) — 33 entries in scope, 24 linked, 9 deliberately skipped.

Section numbers verified directly against TC18.txt (not assumed from
memory or from go-RCP's citations, which use a different section
layout for at least PWM):
  - GPIO: §13.7.4 (NOT §13.7.3 as originally guessed — §13.7.3 is SPI)
  - SPI: §13.7.3
  - PWM_OUT: §13.7.5, PWM_IN: §13.7.6
  - UART: §13.7.8
  - WAKEUP: §13.7.2
  - Shared evt-field semantics table (GPIO/PWM_OUT write combinators,
    saturation, ep_type enum, compound-wait): §13.2/§13.5/§13.5.1

== Per-prefix verdict ==

REQ-CAN-*: 0 entries exist (see scope note above). N/A.

REQ-GPIO-* (9 total): 6 linked, 3 skipped.
  Linked: 001, 002, 003, 004, 005, 009.
  Skipped:
    - 006 "GPIO functional config block wiring" — the file's own header
      comment explicitly disclaims that "the concrete pin-direction bit
      convention, functional-config layout... chosen in this file are
      this implementation's own." TC18's actual GPIO functional-config
      register map (Table 44, §13.7.4.2) has no pin-direction or
      per-pin edge-enable fields at all (only debounce/clock/enable/
      status) — linking to Table 44 would be a section-proximity match,
      not a content match, the exact mistake PR #109's review caught.
    - 007 "GpioEndpoint request-dispatch pattern" — an internal API
      orchestration claim (apply write + evaluate triggers + report
      bitmask "in one call"); its constituent behaviors are already
      individually covered by REQ-GPIO-002/003/004/005's own citations.
      Same shape as REQ-MDIO-003 ("MDIO register write-then-read
      round-trip"), left unlinked in PR #109 for the same reason.
    - 008 "GpioEndpoint error propagation and GpioErrc category" —
      implementation-only error-category plumbing, consistent with
      every other endpoint's *Errc entries (REQ-SPI-005, REQ-I2C-005,
      REQ-ADC-006, REQ-MDIO-005, REQ-UART-007, REQ-PWM-007,
      REQ-WAKEUP-005 below) being left unlinked throughout this and the
      prior batch.

REQ-PWM-* (7 total): 6 linked, 1 skipped.
  Linked: 001, 002 (citation corrected), 003 (citation corrected), 004,
  005, 006 (citation corrected).
  Skipped: 007 (PwmErrc error category — implementation-only, see above).

REQ-SPI-* (5 total): 4 linked, 1 skipped.
  Linked: 001 (citation corrected), 002, 003, 004.
  Skipped: 005 (SpiErrc error category — implementation-only).

REQ-UART-* (7 total): 4 linked, 3 skipped.
  Linked: 001, 002, 003, 005.
  Skipped:
    - 004 "UART payload-less pure read requests" — TC18 §13.7.8.1 only
      says a UART read *carrying* a byte_msg_payload is rejected
      (UNKNOWN_CMD); it does not define a distinct non-blocking
      "pure read" request kind for UART the way §13.7.4.3 explicitly
      names one for GPIO. handle_pure_read's own doc comment concedes
      this is this implementation's own API convenience ("no read_size
      is carried at all, so there is nothing to wait on"), not a
      TC18-named UART behavior distinct from what REQ-UART-002/003
      already cover.
    - 006 "UART RX FIFO / read_size single-AVTPDU accepted limitation"
      — this requirement documents a deliberate NON-conformance: TC18
      §13.7.8.1 mandates fragmenting the response when read_size
      exceeds uart_rx_fifo_size (TC18-13.7.8.1-004); this milestone's
      accepted limitation (ROADMAP.md milestone 52, fragmentation
      no-go) instead rejects such requests outright. Linking it would
      misrepresent a documented gap as coverage.
    - 007 (UartErrc error category — implementation-only).

REQ-WAKEUP-* (5 total): 4 linked, 1 skipped.
  Linked: 001, 002, 003, 004.
  Skipped: 005 (WakeupErrc error category — implementation-only).

== Full id -> master-catalog-id mapping (24 entries) ==

REQ-GPIO-001 -> TC18-13.7.4.1-005 "GPIO request length validation": TC18
  requires rejecting any GPIO request not exactly 4 bytes
  (INVALID_PARAMETER); matches kGpioPayloadLen=4 / short_buffer.
REQ-GPIO-002 -> TC18-13.5-001 "EP-specific usage of evt-field": Table 33's
  GPIO/PWM_OUT row defines evt[2:0]=000b/001b/010b/011b as
  Replace/OR/AND/XOR against current interface status; matches
  apply_bitmask_write's Replace/Or/And/Xor.
REQ-GPIO-003 -> TC18-13.5-003 "Saturation arithmetic for GPIO/PWM_OUT
  add/subtract": "neither overflows nor wrap-arounds... saturated at
  0x0000/0xFFFF" — matches the saturating (not wrapping) Add/Subtract
  rule directly.
REQ-GPIO-004 -> TC18-13.5-001: same Table 33 GPIO/PWM_OUT row,
  evt[2:0]=100b (reserved/rejected) and 111b (reconfigure — endpoint
  config change, not a value written to the interface); matches
  Reserved-rejected / Reconfigure-retargets-directions split.
REQ-GPIO-005 -> TC18-13.7.4.1-011 "Optional GPIO edge/change trigger
  generation": "generates triggers for all its mapped IO-pins on the
  change, falling and rising edge" — matches per-pin Change/Rising/
  Falling signal evaluation.
REQ-GPIO-009 -> TC18-13.7.4.3-004 "Write to input pin is ignored":
  "A write request to an input pin is ignored for this input pin" —
  direct match, quote already correct pre-existing; only the line
  number and master_id were added.

REQ-PWM-001 -> TC18-13.7.5.3-001 "pwmo request format": "The PWM_out
  request and response contain two values in the payload. The active
  time... as well as the period" — matches the shared two-field
  PwmValue{period, active_duration} shape.
REQ-PWM-002 -> TC18-13.5-001: Table 33 GPIO/PWM_OUT row, evt[2:0]=000b
  ("byte_msg_payload is presented at the interface") — matches Replace
  applying period/active_duration directly. CITATION CORRECTED (was
  "Table 30", which is TC18's actual "Error codes in responses" table,
  not the evt-field table — the real table is Table 33).
REQ-PWM-003 -> TC18-13.5-003: same saturation clause as REQ-GPIO-003,
  applied per-field to PwmValue's uint16_t range. CITATION CORRECTED
  (was "Table 30" + "TC18.txt L3694-3714", which points at an unrelated
  sequencer request-state-machine passage, not Table 33/the saturation
  note at all).
REQ-PWM-004 -> TC18-13.5-001: same Table 33 row, evt[2:0]=100b/111b, as
  REQ-GPIO-004 — matches Reserved-rejected / Reconfigure-unsupported
  (PWM_OUT has no reconfigure target of its own besides its functional
  config registers).
REQ-PWM-005 -> TC18-13.7.6.1-001 "PWM_IN max-period exceeded /
  source-loss error notification": "if... the external PWM source
  stops, the PWM_IN endpoint will detect this and... notify the RC
  Client with an error response message" (error code PWM_IN_NO_SIGNAL,
  Table 30) — matches no_signal before first measurement / after
  clear_signal().
REQ-PWM-006 -> TC18-13.7.6.1-002 "pwmi trigger outputs": Table 47 defines
  exactly two PWM_IN trigger signals (0=rising edge, 1=falling edge) —
  matches RisingEdge/FallingEdge notification. CITATION CORRECTED (was
  "§13.7.5.1 Table 44" — §13.7.5.1 is PWM_OUT's pin-config section and
  Table 44 is GPIO's functional-config register map; the real anchor is
  §13.7.6.1 Table 47, the actual "pwmi trigger outputs" table).

REQ-SPI-001 -> TC18-13.7.3.2-006 "Parallel SPI: up to 6 CS
  configurations, selected via evt[2:0]": "up to 6 CS signals may be
  handled by the SPI endpoint... the SPI bus functional configuration
  supports up to 6 different configurations in parallel... determined
  by evt[2:0]" — matches kMaxChannels=6, evt[2:0] 0-5 valid / 6,7
  rejected. CITATION CORRECTED (was "§13.7.3.1" quoting "up to 6
  pre-configurable sets of SPI configurations" at L4192 — TC18.txt
  L4192 is CRC/Safe-command-mode text, unrelated; and §13.7.3.1's real
  text says "up to 16" pre-configurable sets selected via byte_bus_id,
  not evt[2:0] — a known, spec-internal, editorially-flagged
  inconsistency between the "16" figure in §13.7.3.1 and the "6" figure
  in §13.7.3.2, per master-catalog entry TC18-13.7.3.1-002's own notes.
  cpp-RCP's kMaxChannels=6 + evt[2:0] selection matches §13.7.3.2's "6"
  clause, not §13.7.3.1's "16" one).
REQ-SPI-002 -> TC18-13.5.1-001 "Compound-wait byte-length mismatch
  handling": "the interface status shall be capped to the length of
  the byte message payload. For SPI this means that e.g. only the
  first four out of 20 received bytes will be checked..." — exact
  match, including cpp-RCP's own kCompoundWaitCompareLen=4 /
  kMaxStatusBytes=20 constants mirroring TC18's own worked example.
REQ-SPI-003 -> TC18-13.7.3.1-003 "Client byte-send request to SPI
  endpoint": "The RC Client can request the SPI endpoint to send one or
  more bytes that are delivered as byte_msg_payload..." — matches the
  raw PICO-out/POCI-in transfer request/response mechanism.
REQ-SPI-004 -> TC18-13.7.3.1-007 "SPI trigger outputs mapping": Table 41
  defines signal 0 = SPI execution done, (2+2n) = CSn asserted,
  (3+2n) = CSn de-asserted — matches CsAssert/TransferComplete/
  CsDeassert and the per-(channel,signal) distinct SignalId scheme (the
  specific notification *order* is this implementation's own choice,
  not spec-mandated, consistent with this file's own disclaimer).

REQ-UART-001 -> TC18-13.7.8.1-001 "UART EP dual independent TX/RX
  request storages": "these two processes are independent from each
  other, thus the UART EP has two EP request storages" — direct match.
REQ-UART-002 -> TC18-13.7.8.1-002 "UART RX FIFO buffering and overflow
  flagging": "the UART EP shifts the received data into a
  fifo-rx-buffer... emptied by read requests. Overflow is flagged..."
  — direct match.
REQ-UART-003 -> TC18-13.7.8.1-004 "UART read request trigger conditions
  and fragmentation sizing": "A read request will be started as soon
  as the fifo-rx-buffer is filled with as many bytes as requested in
  the read_size or when the uart_timeout has expired" — matches the
  read-completion rule. (Citation deliberately quotes only the
  read_size/timeout portion, not the fragmentation sentence that
  follows it in the same TC18 passage — this implementation's
  read_size_exceeds_bound rejection is a documented divergence from
  that fragmentation behavior, per REQ-UART-006, not an implementation
  of it.)
REQ-UART-005 -> TC18-13.7.8.3-004 "UART EP ignores trailing
  non-integer-multiple bits when transmitting": "In case uart_nr_bits
  is not a multiple integer of 8... the EP ignores the last up to
  'uart_nr_bits - 1' bits..." — matches the sub-octet
  mask-to-low-bits/zero-pad-high-bits packing rule.

REQ-WAKEUP-001 -> TC18-13.2-002 "ep_type enumerated values": Table 32
  lists 0x01 = WakeUp — matches kEndpointTypeWakeup=0x01. Same
  master_id as REQ-CANEP-001/REQ-MDIO-001 from PR #109 (same table,
  different row). Deliberately NOT linked to TC18-13.7.2.1-001 ("WakeUp
  endpoint fixed at EP nr 1") — that clause is about EP_Nr (instance
  position), a different field from ep_type (the type-code value this
  requirement actually tests); confirmed by reading endpoint.hpp's own
  kEndpointType* constant block, which is exactly Table 32's ep_type
  enumeration.
REQ-WAKEUP-002 -> TC18-13.7.2.3-004 "SleepCMD fixed code value":
  "SleepCMD is coded as 0xA5." — direct, exact match.
REQ-WAKEUP-003 -> TC18-13.7.2.2-002 "WakeUp functional configuration
  register map": Table 39's wup_status register — "Indication of
  wake-up source, writing '1' clears the flag. Each bit represents a
  wake-up source" — matches record_wake_source_event setting a bit /
  clear_wake_source_pins() resetting the mask.
REQ-WAKEUP-004 -> TC18-13.7.2.1-002 "Repetitive wake-up messages after
  reconnection": "After establishing a network connection, the WakeUp
  endpoint sends repetitive messages. The timing interval is
  configurable (flush_time)." — matches the repeating WakeUp-message
  handshake for hot-start-from-Sleep.

== Citation corrections found (5) ==

1. REQ-SPI-001: wrong section (§13.7.3.1 instead of §13.7.3.2), wrong
   quote (misattributed the "6" figure to §13.7.3.1's text, which
   actually says "16"), and wrong line number (L4192 is CRC/Safe-mode
   text, not SPI channel-count text at all).
2. REQ-PWM-002: "Table 30" corrected to "Table 33" (Table 30 in TC18 is
   "Error codes in responses"; the evt-field table is Table 33).
3. REQ-PWM-003: same Table 30->33 correction, plus the line range
   L3694-3714 (sequencer request-state-machine text) corrected to the
   real Table 33 saturation-note location, L4094-4119.
4. REQ-PWM-006: "§13.7.5.1 Table 44" corrected to "§13.7.6.1 Table 47"
   (§13.7.5.1/Table 44 are PWM_OUT/GPIO material; PWM_IN's actual
   trigger-outputs table is §13.7.6.1 Table 47).
5. REQ-GPIO-009: quote content was already accurate; only the missing
   "TC18.txt L####" line-number suffix was added for consistency with
   every other linked entry's citation format.

Note: REQ-PWM-002/003's own pre-existing `text` fields also say
"§13.5 Table 30" — left untouched per field-preservation (only `tc18`/
`tc18_master_id` are new/corrected fields in this batch); the `text`
field's wording is a separate, smaller pre-existing inaccuracy not in
this batch's scope to rewrite.

== Deliberately-untouched entries (9) ==
REQ-GPIO-006, REQ-GPIO-007, REQ-GPIO-008, REQ-PWM-007, REQ-SPI-005,
REQ-UART-004, REQ-UART-006, REQ-UART-007, REQ-WAKEUP-005 — reasoning
per-entry above (per-prefix verdict section).

== Verification ==
- cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DRELAY_BUILD_CLI=ON -G Ninja &&
  cmake --build build --parallel: clean rebuild, 0 errors.
- ctest --test-dir build --output-on-failure -j1: 53/53 passing
  (matches PR #109 baseline).
- cpfusa v0.18.0 check: 0 errors, 2 warnings, 1 info (unchanged from
  baseline).
- cpfusa v0.18.0 trace --format json: 376 total/376 traced/376 tested/
  64 secTested (identical before and after — only citation metadata
  fields were added, no requirement entries or test annotations
  changed).
- git diff --stat: 1 file changed (.fusa-reqs.json only), 67
  insertions(+), 24 deletions(-) — 24 tc18_master_id fields added, 24
  tc18 fields present after (19 new + 5 corrected in place).

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@SoundMatt
SoundMatt merged commit 416448e into main Aug 19, 2026
46 of 85 checks passed
@SoundMatt
SoundMatt deleted the tc18-533-propagate-can-gpio-pwm-spi-uart-wakeup-master-id branch August 19, 2026 22:16
SoundMatt added a commit that referenced this pull request Aug 19, 2026
…Q-LIFECYCLE-*/REQ-PWR-*/REQ-WDG-*/REQ-ENDPOINT-* (#111)

Scope: REQ-LIFECYCLE-001..007, REQ-PWR-001..014, REQ-WDG-001..008,
REQ-ENDPOINT-001..006 (35 entries, all previously 0 linked). 25 linked,
10 deliberately left unlinked (implementation-only behavior with no
TC18 textual counterpart, or a claim TC18 does not make). All section
numbers and line numbers verified directly against TC18.txt (6095-line
plaintext extraction), independent of any other repo's citations.

What each package actually is (confirming/correcting the batch hypothesis):
- REQ-LIFECYCLE-* (rcp/lifecycle.hpp): the 3-state HW_UNCONFIGURED /
  HW_CONFIGURED / RCP_CONFIGURED machine of TC18 §12.3/§12.3.1.x, plus
  the byte-encoding table in §13.7.1.2 Table 36 (EP0's own functional
  config register map). Confirmed.
- REQ-PWR-* (rcp/powerstate.hpp): TC18 §12.4/§12.4.1 (power modes,
  cold/hot start) and §12.5 (goto sleep/standby entry-refusal rules).
  Confirmed, with one notable naming discrepancy flagged below.
- REQ-WDG-* (rcp/watchdog.hpp): TC18 §12.7.7's per-request-stream
  watchdog/safe-state register fields (Table 24: rx_wd_timeout_intervall,
  rx_enforce_watchdog, rx_stream_status) plus the general safety-tagged-
  request retention rule of §11.2.2. This is narrower than "12.7.7 area"
  guessed in the task brief -- it also draws on §11.2.2, not just §12.7.7.
- REQ-ENDPOINT-* (rcp/endpoint.hpp): confirmed as the generic
  ep_type/evt-field/write-semantics/trigger-signal layer -- §13.2 Table 32
  (ep_type enum) and §13.5 Table 33 (evt[2:0] usage), the same tables
  already cited by prior batches' REQ-GPIO-*/REQ-I2C-* entries. All 6
  entries linked.

Pre-existing citations corrected (both had right topic, wrong TC18.txt
line number -- verified by grep for the quoted text itself):
- REQ-PWR-001: was "TC18.txt L2268" (that line is actually mid-Table-17,
  unrelated). Real location of "The RC Server may support different
  power modes." is L2644. Master id TC18-12.4-001 was already correct
  in spirit; added the definitions' line range (L2644-2651) and now also
  the tc18_master_id field.
- REQ-LIFECYCLE-001: was "TC18.txt L2063" citing "The three lifecycle
  states..." (that line is actually mid-Figure-15, unrelated -- the real
  "three lifecycle states" sentence is at L2438, part of the §12.3 intro
  before Figure 17). On closer reading, REQ-LIFECYCLE-001's actual content
  (ServerState encodes HwUnconfigured=0x00/HwConfigured=0x55/
  RcpConfigured=0xAA) is not this generic-enumeration sentence at all --
  it is the literal byte-value table, found only in §13.7.1.2 Table 36
  ("svr_lifecycle_state ... 0x00: HW_UNCONFIGURED / 0x55: HW_CONFIGURED /
  0xAA: RCP_CONFIGURED", TC18.txt L4388-4390). Re-cited to that clause and
  linked to TC18-13.7.1.2-001, a materially better content match than the
  original guess.

Full id -> master-catalog-id mapping (linked entries):

REQ-LIFECYCLE-001 -> TC18-13.7.1.2-001 -- Table 36's svr_lifecycle_state
  row gives the exact 0x00/0x55/0xAA byte values the requirement asserts.
REQ-LIFECYCLE-002 -> TC18-12.3.1.1-006 -- "A request to advance the state
  directly to RCP_CONFIGURED will be rejected" is TC18's one explicit
  skip-rejection rule; the requirement generalizes it (also forbidding
  backward moves and no-op repeats), which TC18 does not state as
  explicitly for the other two transitions, but this is the only textual
  anchor for the family of behavior.
REQ-LIFECYCLE-003 -> TC18-12.3.1.1-007 -- HW_CFG_INCONSITENT plausibility
  check, exact match (spec's own spelling "INCONSITENT" reproduced in the
  master catalog; code correctly spells INCONSISTENT).
REQ-LIFECYCLE-004 -> TC18-12.3.1.2-006 -- RCP_CFG_INCONSISTENT
  plausibility check, exact match.
REQ-LIFECYCLE-005 -> TC18-12.3.1.2-001 -- "access to the HW_config and
  EP_generic_config are locked" in HW_CONFIGURED is the direct source for
  generic_config_locked; TC18-12.3.1.3-001 (RCP_CONFIGURED write-lock)
  additionally informs the functional_config_locked half but only one
  master id fits the field, so the more literally name-matching clause
  was chosen.
REQ-LIFECYCLE-006 -> TC18-12.3.1.2-007 -- explicit revert-to-
  HW_UNCONFIGURED via svr_lifecycle_state write. TC18 states this path
  only from HW_CONFIGURED; the code's deconfigure() generalizes it to
  work from any state, which is an implementation extension beyond the
  literal text.
REQ-LIFECYCLE-007 -> UNLINKED -- callback-firing/ordering is a pure API
  contract, no TC18 textual counterpart.

REQ-PWR-001 -> TC18-12.4-001 -- the four power-mode definitions
  (Unpowered/Powered/Sleep/StandBy) match exactly; code's "Normal" is
  TC18's "Powered".
REQ-PWR-002 -> UNLINKED -- "only from Normal" is a reasonable
  precondition but TC18 §12.5 never states it explicitly.
REQ-PWR-003/004/005 -> TC18-12.5-005 (all three) -- the three bullets of
  the sleep/standby REQUEST_CANCELED rejection list (wup_status not
  cleared / EP not idle / responder queue non-empty) map 1:1 to these
  three requirements, matching this catalog's existing precedent of
  reusing one Table/list-bearing master id across several decomposed
  REQ- entries (e.g. TC18-13.2-002 used 5x by earlier GPIO/I2C batches).
REQ-PWR-006 -> UNLINKED, with a finding: TC18 §12.4.1 explicitly labels
  its network-re-enable/WakeUp-handshake procedure as the "Hot-start-up
  procedure" (hot start = wake from StandBy, per its own L2663-2664
  definition), but cpp-RCP's powerstate.hpp instead drives that identical
  handshake from Sleep (calling it "hot-start-from-Sleep" in its own
  header comment) and gives StandBy wake-up no handshake at all. This
  looks like either a TC18 draft inconsistency (the handshake content --
  re-enabling a powered-down network PHY -- fits recovery from Sleep,
  where "only part of the network PHY shall be powered" per §12.5, far
  better than StandBy, where wake-up control alone is said to stay
  active) or a deliberate, unstated divergence in this implementation.
  Left unlinked rather than asserting a citation that would misrepresent
  the match; flagged here for maintainer attention.
REQ-PWR-007 -> TC18-12.4.1-003 -- the network-interface-reenable/
  availability-check mechanics match this clause closely; see the
  hot/cold naming caveat under REQ-PWR-006 above.
REQ-PWR-008 -> UNLINKED -- handshake-step guard against being called
  outside an active handshake is a defensive-programming detail, not
  independently specified in TC18.
REQ-PWR-009 -> UNLINKED -- the WakeUp message repeat *limit* with a
  Failed terminal state is an implementation addition; TC18 L2676
  describes unconditional repetition "until a valid AVTPDU ... is
  received", with no stated give-up condition.
REQ-PWR-010 -> TC18-12.4.1-003 -- "After reception of valid message from
  the sleep request Client all used endpoints and response queues will be
  enabled" is an exact match for acknowledge_wakeup's queue-reenable/
  Normal-transition behavior.
REQ-PWR-011 -> TC18-12.4-001 -- Unpowered's definition ("no sufficient
  power supply is available") is inherently a hardware event outside
  protocol-level refusal gating, matching the "unconditionally" claim.
REQ-PWR-012 -> TC18-12.4-001 -- Powered's definition is the basis for
  "returns to Normal" on power restoration.
REQ-PWR-013 -> TC18-12.4.1-001 -- "a cold start (after power-on or
  wake-up from sleep) and a hot start (=wake-up from StandBy)" is TC18's
  own Hot/Cold definition sentence (L2663-2664); the master catalog does
  not have its own entry for this specific intro sentence (12.4.1-001/002
  both begin one sentence later), so the closest existing TABLE/MUST
  entry whose own citation text overlaps this content was used.
REQ-PWR-014 -> UNLINKED -- error_category/message API convention, no
  TC18 counterpart.

REQ-WDG-001 -> TC18-12.7.7-001 -- Table 24's rx_wd_timeout_intervall
  ("WatchDog time out ... 0dec: WD is disabled") and rx_enforce_watchdog
  ("0b: no watchdog ... 1b: stream is blocked upon WD overflow") fields
  are exactly what StreamWatchdog::check reports.
REQ-WDG-002 -> TC18-12.7.7-001 -- the reset-per-request rule ("the
  watchdog is reset with each request received from this RC Client",
  L3301-3302) is prose immediately following Table 24 in the same
  clause/section, not its own separate master-catalog entry; cited via
  the section's sole TABLE/MUST id.
REQ-WDG-003 -> TC18-11.2.2-001 -- the general MSB-set (0x8x) safety-
  request retention rule ("shall not be deleted when the EP needs to go
  to safe state") is the exact generalization apply_watchdog_overflow's
  purge-normal/retain-safety logic implements; it is more general than
  TC18-11.2.2.2-006/11.2.2.3-007/11.2.2.5-005 (the compound/compound-wait/
  triggered-specific instances of the same rule, each explicitly tied to
  watchdog overflow) but those are per-request-type, while this
  requirement and its RequestLedger are type-generic across exactly the
  three MSB-set request kinds §11.2.2 defines is_safety over.
REQ-WDG-004 -> TC18-12.7.7-001 -- Table 24's rx_enforce_watchdog latch
  behavior and rx_stream_status "1b: stream is blocked, requests are
  rejected" bit (set automatically on overflow, not self-clearing) is the
  textual basis for "does not re-fire until explicitly cleared".
REQ-WDG-005 -> UNLINKED -- the repeating "still in safe state" info
  notification (rx_wd_info_enable) has no TC18.txt counterpart found;
  grepped "notification"/"repeated"/"repetitive" across the whole
  document, nothing else in §12.7.7 or elsewhere describes this signal.
REQ-WDG-006/007/008 -> UNLINKED -- Manager multiplexing, unregistered-
  stream error codes, and callback-ordering are all pure implementation
  API surface with no TC18 textual analog.

REQ-ENDPOINT-001 -> TC18-13.2-002 -- Table 32's ep_type enum: 0x02 GPIO,
  0x03 SPI, exact match.
REQ-ENDPOINT-002 -> TC18-13.5-001 -- Table 33's full GPIO/PWM_OUT evt[2:0]
  row set (000b write / 001b-011b OR-AND-XOR / 100b reserved / 101b-110b
  add-subtract / 111b reconfigure) is exactly the 8-value mapping
  write_semantics_of implements.
REQ-ENDPOINT-003 -> TC18-13.5-001 -- the OR/AND/XOR combinator rows
  specifically (reused master id, same table, decomposed sub-behavior --
  same pattern prior batches used for TC18-13.5-001, already reused 4x by
  REQ-GPIO-*/REQ-PWM-*).
REQ-ENDPOINT-004 -> TC18-13.5-003 -- "neither overflows nor wrap-arounds
  shall occur ... saturated at 0x0000 ... 0xFFFF", exact match, same
  clause already used by REQ-GPIO-003.
REQ-ENDPOINT-005 -> TC18-13.5-001 -- the 100b-reserved/111b-reconfigure
  rows specifically (third decomposed reuse of the same table).
REQ-ENDPOINT-006 -> TC18-11.2.2.5-002 -- "Each endpoint may generate one
  or more trigger signals" is the generic, per-endpoint-type-agnostic
  trigger-signal-generation clause TriggerRegistry's enable/notify/drain
  API implements; distinguished from TC18-11.2.2.5-003 ("configured to
  start a request upon receiving a trigger"), which is about consuming a
  trigger to start a request elsewhere, not generating/gating one.

Deliberately-untouched entries and reasoning: see per-prefix notes above
(REQ-LIFECYCLE-007, REQ-PWR-002/006/008/009/014, REQ-WDG-005/006/007/008
-- 10 entries total). Each is either a pure implementation/API-surface
detail with no TC18 textual counterpart, or (REQ-PWR-006/009) a claim
TC18's text does not actually make, left unlinked rather than force-fit
per this effort's established discipline.

Verification pipeline (all against origin/main @ 416448e, PR #110's tip):
- cmake configure + build: clean, 0 errors (toolchain-only -Wnonnull
  warnings from libstdc++/Catch2 internals, pre-existing, unrelated).
- ctest --output-on-failure -j1: 53/53 passing (matches PR #110 baseline).
- cpfusa check (v0.18.0): 0 errors / 2 warnings / 1 info, identical
  before and after this change (confirmed via git stash A/B comparison).
- cpfusa trace --format json coverage: {tracedRequirements: 376,
  testedRequirements: 376, totalRequirements: 376, secTestedRequirements:
  64} both before and after -- byte-identical, confirming this change
  only adds tc18/tc18_master_id fields and touches no trace-relevant
  field.
- git diff --stat: .fusa-reqs.json | 98 ++++++++++++++++++++++++++++++
  ++++++++++++++++++---------------, 1 file changed, 73 insertions(+),
  25 deletions(-) -- only the 35 target-prefix entries touched.

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
SoundMatt added a commit that referenced this pull request Aug 19, 2026
…Q-E2E-*/REQ-REGMAP-*/REQ-SEQ-* (#112)

Links 35 of 41 REQ-E2E-*/REQ-REGMAP-*/REQ-SEQ-* entries in .fusa-reqs.json
to the RELAY tc18-master-catalog.json (447 entries), adding "tc18" and
"tc18_master_id" fields. cpp-RCP moves from 78/376 to 113/376 linked.

Scope verification (all three packages carry an explicit TC18-scope doc
comment citing "extraction" section numbers — none of the excluded
"integration shell" naming patterns from #109/#110 apply here):

- rcp/e2e.hpp (REQ-E2E-*): TC18's end-to-end CRC integrity mechanism
  (crc32/coverage_buffer/verify_crc) plus the per-request-stream
  watchdog/safe-state primitives, riding on rcp/acf.hpp, rcp/avtp.hpp,
  rcp/regmap.hpp and rcp/request.hpp. Confirms the task hypothesis
  (CRC/E2E protection, cross-cutting into §12.7.7 and §13.6).
- rcp/regmap.hpp (REQ-REGMAP-*): the RC Server register-map data model
  and EP0 pseudo-endpoint (generic/functional config split, root-client
  arbitration, whole-map read/write). Confirms the §12.6/§12.7.x
  hypothesis, and additionally reaches into §12.3.1.x (lifecycle-gated
  locking) and §13.1/§13.2/§13.7.1.2 (EP0/ROOT_CLIENT semantics).
- rcp/request.hpp (REQ-SEQ-*, module renamed from rcp/sequencer.hpp per
  RELAY spec §13.7.2): conditional-request taxonomy (compound,
  compound-wait, triggered, chained, timed) AND sequencer-state
  primitives, both living in one file/prefix. Confirms the §12.10
  hypothesis but the taxonomy half draws far more heavily on §11.2.2/
  §11.2.2.x/§11.2.3.x (conditional-request wire format, cancellation)
  and §12.9.2/§12.9.3 (priority/lifecycle) than on §12.10 itself, which
  in this file is used only for REQ-SEQ-004's default/advance rule.

Per-prefix verdict: E2E 11/14 linked, REGMAP 13/15 linked, SEQ 11/12
linked — all three fully TC18-scoped (no entries excluded as
non-TC18 "integration shell"); the 6 gaps are cases where cpp-RCP's own
field/enum granularity goes beyond what TC18's text literally defines,
not scope exclusions.

== REQ-E2E-* (11/14 linked) ==

REQ-E2E-001 -> TC18-13.6-003 (CRC32P4 polynomial parameters, Table 34):
crc32's poly/init/refin/refout/xorout constants are a verbatim match for
Table 34's 0xF4ACFB13/0xFFFFFFFF/TRUE/TRUE/0xFFFFFFFF.

REQ-E2E-002 -> TC18-13.6-005 (ACF_GBB under NTSCF header CRC field
layout, Figure 21): coverage_buffer's ACF_GBB 16-byte Message-Info form
(message_timestamp spliced between the two header quadlets) is exactly
Figure 21's byte layout; Figure 20 (ACF_ABB, TC18-13.6-004) covers the
other half of the same requirement's text but only one master_id fits
the field, so the more heavily-described GBB case was chosen as primary.

REQ-E2E-003 -> TC18-13.6-006 (acf_msg_length accounting for appended
CRC): "adding the CRC to the byte_msg_payload increases the
acf_msg_length by 1" is a direct match for apply_acf_length_adjustment's
+1-quadlet rule; the companion +4-octet control_data_length adjustment
is this implementation's own derived consequence for wrapping headers,
not separately spelled out in TC18 text.

REQ-E2E-004 -> TC18-13.6-001 (Safe command mode CRC mismatch handling):
"the request is not executed, and an error response is generated with
error code: CRC_ERROR" is a verbatim match for verify_crc's
crc_error/CRC_ERROR contract.

REQ-E2E-005 -> SKIPPED. crc_required checks three independently-toggled
booleans keyed by MessageRole (Request/Ack/Response) living in
EndpointGenericConfig; TC18's only literal CRC-enable bits are
per-request-STREAM (rx_enforce_crc, §12.7.7 Table 24) and per-BBID
(CRC_required, §12.7.8 Table 26) — neither is keyed by message role.
implemented_options_bit's kOptSafetyRequests also has no literal TC18
bit position: svr_implemented_options (§12.7.5 Table 20) documents only
bits a-e (compound&wait/trigger/chained/timed/enhanced-cancellation) of
its 8-bit "abcdefgh" pattern; f/g/h are undocumented. Read both Table 20
and Table 26 directly before concluding neither's granularity matches —
left unlinked rather than forcing a section-only match.

REQ-E2E-006 -> TC18-12.7.7-001 (Request stream configuration register
map, Table 24): rx_enforce_crc's documented 0/1 semantics ("stream is
not blocked, when CRC check at EP fails" / "stream is blocked until
released ... and Safe state will be entered") is exactly
RxStreamGuard's drop-vs-latch rule gated on rx_enforce_e2e.

REQ-E2E-007 -> TC18-12.7.7-001 (same Table 24): rx_enforce_sequence's
0/1 semantics ("not blocked upon out of order reception" / "blocked
... and Safe state will be entered") is exactly RxSequenceGuard's
accept-vs-sequence_violation rule gated on rx_enforce_seq.

REQ-E2E-008 -> TC18-12.7.7-001 (same Table 24, reusing REQ-WDG-001's
already-merged citation for the identical field pair):
rx_wd_timeout_intervall + rx_enforce_watchdog's documented semantics
match RxWatchdog::overflowed's rx_wd_enable/rx_wd_timeout_interval gate.

REQ-E2E-009 -> TC18-11.2.2-001 (Safety-request retention on MSB-set
condition identifiers): "the request is treated as a safety request and
will not be deleted when the EP needs to go to safe state" is the
general principle apply_watchdog_overflow implements via
RequestLedger::cancel_all(true) (purge is_safety=false, retain
is_safety=true). The specific *mechanism* reused
(cancel_all/non_safestate_only) is separately TC18-cited for
REQ-SEQ-012; TC18's own text does not itself connect watchdog overflow
to that named cancellation operation, so the general retention
principle is the better-grounded citation here.

REQ-E2E-010 -> TC18-11.2.2-001 (same clause): apply_queue_overflow
implements "the same purge-normal/retain-safety rule via a distinct
trigger" per its own title — same underlying TC18 principle, different
RequestStreamConfig gate (rx_ovrflw_safestate_enable vs.
rx_wd_safestate_enable).

REQ-E2E-011 -> TC18-12.7.7-001 (Request stream configuration, Table 24
+ prose). CITATION CORRECTION: the pre-existing tc18 field on this entry
quoted TC18.txt L2935, but L2935 is mid-Table-20 (svr_implemented_options
bit descriptions) and does not contain the quoted text at all — grep
confirms "a safe state may be enforced. The safe state to enter can be
chosen via the Safety_Measure parameter" appears exactly once in
TC18.txt, at L3300 (§12.7.7's paragraph following Table 24). Fixed the
line number to L3300 and added the missing tc18_master_id (rx_safestate_
seqencer/rx_safe_sequencer_state are Table 24 fields; the Safety_Measure
parameter is this same paragraph, matching endpoint_in_configured_safe_
state's RxSafetyMeasure::ForceHighImpedance/RunSafeSequencer strategies).

REQ-E2E-012 -> TC18-11.2.2-001 (same MSB-safety clause as 009/010):
may_execute_now's execution-eligibility gate for is_safety=true records
is this implementation's behavioral extension of the same "treated as a
safety request" principle (TC18 states retention; this requirement adds
the complementary "gated execution once eligible" behavior on the same
underlying is_safety concept — no separate TC18 clause describes
execution-gating specifically, so the root MSB-safety clause is cited).

REQ-E2E-013 -> SKIPPED. RxWatchdog::should_emit_info_notification's
rx_wd_info_enable field and "repeating info notification while latched"
behavior have no TC18 textual basis found — grepped TC18.txt for
"notification"/"repeating"/"periodic" near the watchdog sections; no
match. This is cpp-RCP's own v2.6.0 field-set extension per
regmap.hpp's own disclaimer ("Concrete field widths ... are this
implementation's own encoding of that behavior").

REQ-E2E-014 -> SKIPPED, following the established cross-batch precedent
(confirmed by grepping the file: every other "-Errc is a distinct
category with non-empty ... messages" requirement in this repo —
REQ-PWR-014, REQ-REGMAP-014, REQ-DISC-008, REQ-SPI-005, REQ-I2C-005,
REQ-UART-007, REQ-ADC-006, REQ-PWM-007, REQ-SEQ-009, REQ-LINEP-004,
REQ-CANEP-007, REQ-ISELED-005, REQ-MDIO-005, REQ-WAKEUP-005 — is
unlinked). This is a generic C++ std::error_category implementation
pattern, not itself a TC18 clause, even where the enum's individual
values happen to reuse TC18 error-code names.

== REQ-REGMAP-* (13/15 linked) ==

REQ-REGMAP-001 -> TC18-13.2-001 (ep_generic_config register map):
the generic-vs-functional split is §13.2's own title framing
("Generic part of endpoint register map (owned by the RC Server)"),
contrasted with "EP_functional configuration" used throughout §13.1/
§13.7. The specific field list in the requirement's text (HW pin
indices, queue sizes) doesn't literally match Table 31's own field
list (ep_type/ep_used/ep_delay_time/...) — this implementation chose
its own contents for the generic block; the structural split itself is
what's TC18-grounded.

REQ-REGMAP-002 -> TC18-12.3.1.1-004 (EP0 full register-map access in
HW_UNCONFIGURED): "Via EP0 the entire register map (i.e. all endpoints)
can be accessed (read and write access)" matches read_whole_map's
unrestricted-read contract. Note: TC18 states this specifically for
HW_UNCONFIGURED state; cpp-RCP generalizes it to be state-independent.
Read all three lifecycle-state subsections (§12.3.1.1-.3) directly to
confirm nothing elsewhere restricts reads at other states (only writes
are gated by W*/W markers) before treating this as a defensible
generalization rather than a mismatch.

REQ-REGMAP-003 -> TC18-13.7.1.2-002 (svr_root_client_index write-access
scope): "Write requests to EP0 via all other streams are limited to
EP0 and not beyond (i.e. other EPs)" is the direct textual basis for
write_whole_map's unauthorized_access-unless-root-client rule.

REQ-REGMAP-004 -> TC18-13.7.1.2-002 (same field): "The svr_root_client_
index is an index that selects the request stream which is in
HW_CONFIGURED still allowed to access all registers" is the field
claim_root_client operates on. Note: TC18 describes this as a plain
register write, not a claim/reject/release transaction protocol —
the request_rejected-on-distinct-claimant / no-op-on-self-reclaim /
release-then-reclaim state machine is this implementation's own
encoding of "how a write to this field gets validated," not literal
TC18 text.

REQ-REGMAP-005 -> TC18-13.1-004 (ROOT_CLIENT-exclusive write access to
server config): matches verbatim — "For other RC Clients than the
ROOT_CLIENT write access is only given to EP_functional configuration
of endpoints which are allocated to the RC Client" is exactly
check_write_access's FUNCTIONAL-block-only rule for non-root clients
(the requirement's own text already cited TC18 §13.1/§13.2 by number;
confirmed §13.1's own MUST clause is the better single anchor for the
write-restriction assertion itself).

REQ-REGMAP-006 -> TC18-12.3.1.2-001 (HW config locked in HW_CONFIGURED):
"access to the HW configuration ... shall have been concluded and as
such all access to the HW_config and EP_generic_config are locked"
directly grounds generic_config_locked's LOCKED_MEM_ACCESS behavior.
Note: TC18 does not describe a symmetric, independently-settable
"functional_config_locked" flag with the same "locked" semantics —
§12.3.1.3 (RCP_CONFIGURED) actually leaves functional config *writable*
via specific stream/root-client paths rather than locking it the same
way. The second half of this requirement (functional_config_locked) is
this implementation's own extension into a second independently-lockable
block; only the generic-config half has a clean 1:1 TC18 match.

REQ-REGMAP-007 -> TC18-12.7.5-001 (RC Server register map, static/
general part, Table 20): direct match — magic/version/vendor_id/
device_id/ep_count and the *_ptr/*_capacity TablePointer fields for
each sub-table are exactly Table 20's own field list.

REQ-REGMAP-008 -> TC18-12.7.6-003 (HW_config pin-mapping table layout,
Table 21): hw_pin_map's HwPinMapEntry(pin_id, function) is this
implementation's simplified encoding of Table 21's per-pin
hw_ep_nr/hw_ep_pin_nr/hw_pin_type triplet.

REQ-REGMAP-009 -> TC18-12.7.7-001 (Request stream configuration,
Table 24): direct match for the whole v2.6.0 watchdog/safe-state field
set (rx_wd_timeout_interval~rx_wd_timeout_intervall,
rx_enforce_e2e~rx_enforce_crc, rx_enforce_seq~rx_enforce_sequence,
rx_safestate_sequencer~rx_safestate_seqencer,
rx_safe_sequencer_state~rx_safe_sequencer_state verbatim). The
rx_wd_safestate_enable/rx_wd_info_enable/rx_seq_safestate_enable/
rx_ovrflw_safestate_enable booleans are this implementation's own
decomposition of Table 24's combined enforce-bit + "and Safe state
will be entered" semantics into separate enable/safestate-enable pairs
— same "own encoding" pattern flagged in e2e.hpp's header comment.

REQ-REGMAP-010 -> TC18-12.7.8-006 (Ascending order of Request_Stream_
Index/BBID entries): "This has to be ensured by the instance that is
sending the configuration to this table" is a verbatim match for
ep_id_mapping's explicit non-re-sorting, non-re-deriving,
insertion-order-preserving contract (the server deliberately does NOT
enforce the ordering TC18 assigns to the client).

REQ-REGMAP-011 -> TC18-12.7.9-007 (Responder QUEUE_config register map,
Table 27): response_queue_size/ack_queue_size are this implementation's
two named instances of Table 27's generic per-queue "queue_size" field,
applied once each to the response queue and the acknowledge queue per
§12.7.9's own prose ("For each response stream or acknowledge stream
the RC Server needs to reserve a transmit queue ... size is given by
... queue_size").

REQ-REGMAP-012 -> TC18-12.7.10-004 (SEQUENCER_config register map,
Table 28): "Seq_state (8bit, current state, default 1 ...)" is a direct
match for sequencer_states' one-persistent-8-bit-value-per-slot storage
model, predating (per the requirement's own "ahead of the sequencing
behavior introduced in v2.5.0" text) the try_advance/kDefaultState
*behavior* separately cited for REQ-SEQ-004.

REQ-REGMAP-013 -> TC18-12.9.6-004 (Table 30: Error codes in responses):
INVALID_PARAMETER(15) "Request parameter out of range" is the specific
Table-30 row check_read_access/check_write_access/set_endpoint_owner's
invalid_parameter return matches — distinguished from the generic
"-Errc is a distinct category" pattern (REQ-REGMAP-014, skipped below)
by describing one specific error code's semantic trigger condition
rather than the enum-as-a-whole's category-implementation machinery.

REQ-REGMAP-014 -> SKIPPED, same "-Errc is a distinct category" precedent
as REQ-E2E-014 above (generic error_category C++ idiom, not a TC18
clause, even though its four values happen to be Table 30's own names).

REQ-REGMAP-015 -> SKIPPED, same granularity gap as REQ-E2E-005: the
three ep_*_crc_enable booleans are keyed per-endpoint-per-message-role,
which has no literal TC18 counterpart (see REQ-E2E-005's reasoning
above — checked both Table 24's stream-level rx_enforce_crc and
Table 26's BBID-level CRC_required; neither is role-keyed).

== REQ-SEQ-* (11/12 linked) ==

REQ-SEQ-001 -> TC18-11.2.2-002 (Conditional request type identifiers,
Table 5): the mtv=0 message_timestamp-repurposing scheme and the
first-byte-selects-opcode decode this requirement describes is exactly
Table 5's "first byte in message_timestamp field" -> "type of
condition" mapping, introduced by §11.2.2's own "conditional requests
are sent using ACF_GBB having mtv = 0 ... using the bytes of the
message_timestamp field to convey the execution condition" paragraph.

REQ-SEQ-002 -> TC18-12.9.2-003 (Execution priority order across request
types): "In case two or more requests are due for execution then the
priorities are as follows: 1. cancellation 2. triggered 3. timed
4. compound 5. compound wait 6. chained 7. standard" is a verbatim
7-level match for category_of's RequestCategory enum values and
select_next_due's priority_rank ordering (the same paragraph's next
sentence, "starting the execution shall happen in the order ... the
requests arrived," independently covers the FIFO tie-break half of this
requirement, catalogued separately as TC18-12.9.2-004 but not chosen as
primary since the priority list itself is this requirement's dominant
assertion).

REQ-SEQ-003 -> TC18-12.2-004 (Optional compound requests bundle):
verbatim match — "Support of compound requests (0x0F/0x8F) ...
Implementation of at least four sequencers (see 12.10) ... Clear all
non-safestate requests from an EP request storage" is exactly
validate_feature_bundles' compound+compound_wait+clear_non_safestate+
sequencer_count>=kMinCompoundSequencers(4) all-four-required rule.

REQ-SEQ-004 -> TC18-12.9.3-002 (Table 29: Execution procedure, compound
row): "the state of sequencer cmp_sequencer is set to cmp_next_state
if the sequencer state still equals the cmp_start_state, else the
sequencer state is not changed" is a verbatim match for try_advance's
increment-only-if-current-equals-expected_start / leave-unchanged-
otherwise contract. The default-value half (kDefaultState=1) is
separately grounded in TC18-12.7.10-002/-004's "default 1" register
description (already used for REQ-REGMAP-012); this requirement's more
novel/behaviorally-distinctive assertion is the conditional-advance
rule, so Table 29 was chosen as the single master_id.

REQ-SEQ-005 -> TC18-11.2.3-002 (Chained successor cancellation
propagation): "If a request is cancelled to which a request is chained,
then the chained successors shall be cancelled by the RC Server as
well" is a verbatim match for cancel_single's cascade-to-every-
transitive-chained-successor behavior — chosen as the single most
distinctive assertion in this requirement's bundled text; the
Pending/Started-only cancellable window (TC18-11.2.3-001) and the
REQUEST_CANCELED outcome (TC18-11.2.3-003) are the same §11.2.3
paragraph's other two sentences, covering the requirement's remaining
clauses but not separately assigned a master_id.

REQ-SEQ-006 -> TC18-12.9.3-001 (Request lifecycle states pending/RS/
RE/RF): "it is in the state 'request pending' ... enters the state
'request started' (RS) ... advances to 'request under execution' (RE)
... and then to 'request finalized' (RF)" is a verbatim 4-state match
for RequestLedger's Pending->Started->UnderExecution->Finalized
single-step-forward-only state machine.

REQ-SEQ-007 -> TC18-11.2.2.6-011 (Conditional-start (cs) bit semantics
for chained requests): "cs ... 1b: request will not be executed in
case the previous request returned an error ... error response with
error code = CHAIN_ABORTED" is the direct textual basis for
should_execute_chained(successor.cs, errored)'s cascade-cancel-on-error
rule driving RequestLedger::finalize's chained-successor propagation.

REQ-SEQ-008 -> TC18-11.2.2.3-008 (cs-bit execution-due semantics for
compound wait): "If cs = 0, then compound wait request is due for
execution, when the sequencer is in the cmpw_start_state. If cs = 1,
... when EP output state has changed after the sequencer reached the
cmpw_start_state" is the direct textual basis for
compound_wait_check_of's cs->CompoundWaitCheck mapping.
  ** CONFORMANCE FINDING (not fixed in this docs-only PR, flagging for
  a follow-up issue): TC18 states cs=0 -> "due immediately" and
  cs=1 -> "due only after an EP output state change." cpp-RCP's actual
  mapping (include/rcp/request.hpp:371-372, exercised by
  tests/test_request.cpp:520-522) is inverted: cs=true (1) ->
  CompoundWaitCheck::Immediate, cs=false (0) -> AfterChangeOnly — the
  opposite polarity from the spec text quoted above. This master_id is
  still the correct citation for *which clause this requirement's
  subject is drawn from*; the polarity defect is an implementation bug
  independent of the citation and out of scope for this PR (same
  practice as PR #162/#163's conformance-defect flags, which likewise
  documented rather than silently fixed the finding).

REQ-SEQ-009 -> SKIPPED, same "-Errc is a distinct category" precedent
as REQ-E2E-014/REQ-REGMAP-014 above.

REQ-SEQ-010 -> TC18-11.2.2-002 (Table 5, same clause as REQ-SEQ-001):
"0x0F, 0x8F Compound ... 0x0B, 0x8B Compound wait ... 0x0E, 0x8E
Triggered" is Table 5's own enumeration of exactly the three MSB-set
identifier pairs is_valid_request_type/decode_request_type must accept
as CompoundSafety/CompoundWaitSafety/TriggeredSafety.

REQ-SEQ-011 -> TC18-11.2.2-001 (Safety-request retention on MSB-set
condition identifiers, same clause used for REQ-E2E-009/010/012):
"the MSB of the identifier (0x8x) is set the request is treated as a
safety request" is the direct textual basis for is_safety_variant
returning true for exactly the three 0x8x-prefixed opcodes.

REQ-SEQ-012 -> TC18-11.2.3.2-001 (Clear-all-non-safestate-requests
optional cancellation feature): "Clear all non-safestate requests from
an EP request storage ... request_type ... is 0x06" is the named
cancellation operation request_record_for's is_safety derivation feeds
into cancel_all(non_safestate_only=true) — the more precise mechanistic
match versus the general MSB-safety-retention clause used elsewhere,
since this requirement's assertion is specifically about exclusion from
*this* named operation.

== Deliberately untouched (6 of 41) ==

REQ-E2E-005, REQ-REGMAP-015: per-endpoint-per-message-role CRC-enable
granularity has no literal TC18 field; see REQ-E2E-005 reasoning above.
REQ-E2E-013: rx_wd_info_enable / repeating info notification has no
TC18 textual basis found (grepped for notification/repeating/periodic).
REQ-E2E-014, REQ-REGMAP-014, REQ-SEQ-009: generic "-Errc is a distinct
category" C++ idiom, consistent with the precedent set across all 14
other such requirements already present in this file (all unlinked).

== Verification ==

- CMake configure (cmake -B build -DCMAKE_BUILD_TYPE=Release
  -DCMAKE_CXX_STANDARD=17 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
  -DRELAY_BUILD_CLI=ON -G Ninja) + build: clean, 0 errors (219/219
  targets), only pre-existing benign -Wnonnull warnings from a system
  <bits/stl_algobase.h> header, unrelated to this change.
- ctest --test-dir build --output-on-failure -j1: 53/53 passing
  (matches PR #111 baseline).
- cpfusa v0.18.0 check: 0 errors / 2 warnings / 1 info, byte-identical
  before and after this change (FUSA004, FUSA005, HARA005 — all
  pre-existing and unrelated).
- cpfusa v0.18.0 trace --format json coverage: totalRequirements=376,
  tracedRequirements=376, testedRequirements=376, secTestedRequirements=64
  before AND after (confirmed identical via git-stash A/B comparison) —
  this change only adds tc18/tc18_master_id metadata fields, it does not
  touch any fusa:req annotation, test, or requirement count.
- git diff --stat: only .fusa-reqs.json changed, 81 insertions(+),
  12 deletions(-) (the 12 deletions are the "severity"/closing-brace
  lines displaced by each of the 34 new two-line tc18/tc18_master_id
  insertions plus REQ-E2E-011's 1-line citation correction).

Freshness: confirmed via fresh `git clone` at session start (tip
87ba239, matching PR #111 as claimed) and via `git fetch origin` +
`git log --oneline -1 origin/main` immediately before this push — no
new commits landed on main while this batch was in progress.

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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