diff --git a/.fusa-reqs-pending.json b/.fusa-reqs-pending.json index e88acd0..3ed0879 100644 --- a/.fusa-reqs-pending.json +++ b/.fusa-reqs-pending.json @@ -956,6 +956,271 @@ "tc18": "§13.5 Table 33 (GPIO/PWM_OUT row, evt[2:0]=111b: \"The byte_msg_payload is not presented to the interface but used to change the configuration of the endpoint (see 12.7.1).\"), TC18.txt L4114-4115", "tc18_master_id": "TC18-13.5-001", "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 9, include/rcp/pwm.hpp module). The behavior itself is genuinely implemented and tested in include/rcp/pwm.hpp / tests/test_pwm.cpp. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-PWM-009 (\"PwmInEndpoint::handle_request reports config-write (evt[2:0]==111b) as not yet supported\"). Genuinely implemented+tested: rcp::pwm::apply_write() (include/rcp/pwm.hpp) returns current unchanged for evt==WriteSemantics::Reconfigure (callers must route that value to apply_reconfig() instead) -- tests/test_pwm.cpp's \"apply_write leaves state unchanged for Reconfigure (fail-safe)\" TEST_CASE (bracket-tagged [REQ-PWM-009] already -- same coincidental-numeral note: this catalog's own pre-existing REQ-PWM-009 entry describes unrelated PwmInEndpoint::handle_request config-write-not-supported content) exercises exactly this." + }, + { + "id": "REQ-SPI-001", + "title": "rcp_ep_spi_strerror() never returns NULL and is unique per code", + "text": "rcp_ep_spi_strerror() shall return a non-NULL, non-empty, distinct message for each rcp_ep_spi_errc_t value.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-SPI-001 (\"SPI channel selection via evt[2:0]\"). Genuinely implemented+tested: rcp::spi::spi_category()/make_error_code(SpiErrc) is a real, distinct std::error_category with non-empty per-code messages -- tests/test_spi.cpp's \"SpiErrc category reports a non-empty, distinct message for every known code\" TEST_CASE (tagged [REQ-SPI-001]) (tests/test_spi.cpp)." + }, + { + "id": "REQ-SPI-002", + "title": "rcp_ep_spi_channel_valid() bounds channel indices to 0..5", + "text": "rcp_ep_spi_channel_valid() shall return true iff channel < RCP_EP_SPI_MAX_CHANNELS (6).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (SPI row, \"selects channel 0 … 5\"), TC18.txt L4076-4078 -- still current per the RC5 PDF's own tracked-change comment marking the competing byte_bus_id-based proposal as conditional/not-yet-accepted (see ep_spi.h's own 'INVESTIGATED 2026-08-11' file-header note, issue #256 task #98). NOTE: the secondary §13.7.3.1 quote this entry previously carried (\"the SPI endpoint may support up to 6 pre-configurable sets of SPI configurations\") is now stale -- current RC5 §13.7.3.1 prose has been edited in place to read \"up to 16\" per that same not-yet-accepted proposal; Table 33 remains the authoritative source per §13.5's own governing statement and should be cited alone.", + "tc18_master_id": "TC18-13.5-001", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-SPI-002 (\"SPI compound-wait status-byte truncation rule\"). Genuinely implemented+tested: rcp::spi::kMaxChannels == 6 and channel_valid() bounds channel indices to 0..5 -- tests/test_spi.cpp's \"kMaxChannels is 6\" and \"channel_valid bounds channel indices to 0..5\" TEST_CASEs (tagged [REQ-SPI-002]) (tests/test_spi.cpp)." + }, + { + "id": "REQ-SPI-003", + "title": "rcp_ep_spi_mode_valid() accepts exactly 0..3", + "text": "rcp_ep_spi_mode_valid() shall return true iff v <= 3.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42 (0.5.1_RC5; formerly Table 39 in the 0.5.1_RC baseline this codebase originally cited) (\"spi_clk_polarity0\"/\"spi_clk_phase0\", each 1-bit R/W), TC18.txt L4654-4659 -- fresh PDF extraction confirms Table 39 was renumbered Table 42 by the RC5 rebaseline, same shift REQ-SPI-035/038/039 already document; the four (polarity, phase) combinations this implementation groups as \"mode 0..3\" are unchanged.", + "tc18_master_id": "TC18-13.7.3.2-002", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-SPI-003 (\"SPI raw PICO-out/POCI-in transfer\"). Genuinely implemented+tested: rcp::spi::mode_valid() accepts exactly clock-mode values 0..3 -- tests/test_spi.cpp's \"mode_valid accepts exactly 0..3\" TEST_CASE (tagged [REQ-SPI-003]) (tests/test_spi.cpp)." + }, + { + "id": "REQ-SPI-004", + "title": "rcp_ep_spi_mode_cpol() derives CPOL correctly for all 4 modes", + "text": "rcp_ep_spi_mode_cpol() shall return false for RCP_EP_SPI_MODE_0/_1 and true for RCP_EP_SPI_MODE_2/_3.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42 (0.5.1_RC5; formerly Table 39) (\"spi_clk_polarity0 ... polarity of SCLK signal, 0b: normal, 1b: inverted\"), TC18.txt L4654-4656 -- same Table 39→42 renumbering as REQ-SPI-003.", + "tc18_master_id": "TC18-13.7.3.2-002", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-SPI-004 (\"SPI transfer-complete and per-CS trigger signals\"). Genuinely implemented+tested: rcp::spi::mode_cpol() derives the CPOL bit correctly for all 4 clock modes -- tests/test_spi.cpp's \"mode_cpol derives CPOL correctly for all 4 modes\" TEST_CASE (tagged [REQ-SPI-004]) (tests/test_spi.cpp)." + }, + { + "id": "REQ-SPI-005", + "title": "rcp_ep_spi_mode_cpha() derives CPHA correctly for all 4 modes", + "text": "rcp_ep_spi_mode_cpha() shall return false for RCP_EP_SPI_MODE_0/_2 and true for RCP_EP_SPI_MODE_1/_3.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42 (0.5.1_RC5; formerly Table 39) (\"spi_clk_phase0 ... sample phase of SCLK, 0b: sample on rising edge, 1b: sample on falling edge\"), TC18.txt L4657-4659 -- same Table 39→42 renumbering as REQ-SPI-003.", + "tc18_master_id": "TC18-13.7.3.2-002", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-SPI-005 (\"SpiErrc is a distinct error category with a non-empty message\"). Genuinely implemented+tested: rcp::spi::mode_cpha() derives the CPHA bit correctly for all 4 clock modes -- tests/test_spi.cpp's \"mode_cpha derives CPHA correctly for all 4 modes\" TEST_CASE (tagged [REQ-SPI-005]) (tests/test_spi.cpp)." + }, + { + "id": "REQ-SPI-037", + "title": "SPI error state resets the EP enable bit; a clamped pin flags every response", + "text": "NOT IMPLEMENTED, genuinely blocked by spec silence (investigated 2026-08-12, issue #336): TC18 13.7.3.3 states \"If the SPI stops execution (see cs/hs bits) -- then SPI endpoint is in error state (-> spi_ep_status, already modeled as RCP_EP_SPI_REG_EP_STATUS/Table 39/42 -- CORRECTED 2026-08-13: RC1's own text said \"->debug register)\"; RC5's own correction, \"051RC5 corrected TI_088\", changed this to \"-> spi_ep_status )\"). And the SPI endpoints enable bit in the EP_config is reset,\" but the specification never defines what \"cs/hs bits\" indicating a stopped execution actually means for SPI -- every request-format table in the document (standard requests, §11.2.2.3 Trigger requests) lists both ACF header bits as fixed 0b/reserved, with only §11.2.2.4's Chained request giving cs a real, unrelated meaning (\"Conditional start\"). It is equally plausible the sentence instead means the SPI bus's own physical CS (chip select)/HS (handshake) hardware signal lines -- a distinct, electrical-level concept §13.7.3.1's own Table 38 already names \"CS0\"-\"CS5\" -- rather than the ACF protocol header's cs/hs bits at all. The two readings lead to entirely different implementations (an observable protocol-level condition vs. a hardware signal this pure protocol-core library has never modelled for any endpoint type), and there is no way to determine which is intended from the text as written. Filed as a genuine specification defect, not a local implementation gap: TC18_spec_defects_report.md item 56 (and its own _quadruple_checked.md review copy). The requirement's own second half -- a clamped pin setting the err flag in every subsequent response -- does not depend on this ambiguity, but the pin-electrical-state detection it requires is itself hardware this module has never modelled for any endpoint type (matching every other endpoint's own 'never itself owns a timer, thread, or ... hardware' scope boundary), so it is left unattempted alongside the blocked half rather than force-splitting one requirement into two differently-dispositioned catalog entries.", + "standard": "iso26262", + "level": "QM", + "asil": "QM", + "scope": "tc18-gap", + "status": "not-implemented", + "tc18": "§13.7.3.3, TC18.txt L4740-4750 -- CORRECTED 2026-08-13, citation-drift fix (issue #341 lineage): this repo's own cached TC18.txt was a stale RC1-dated pdftotext dump, since re-extracted from the real RC5 PDF", + "gap": "Genuine spec-defect gap, matching c-RCP's own disposition verbatim (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). c-RCP's own .fusa-reqs.json records this same id as status=not-implemented, blocked by real specification silence: TC18 §13.7.3.3 gestures at \"cs/hs bits\" indicating stopped execution without ever defining what that means for SPI, and the two plausible readings (the ACF header's own cs/hs bits, vs. the SPI bus's own physical CS/HS hardware signal lines) lead to entirely different implementations (c-RCP: TC18_spec_defects_report.md item 56). include/rcp/spi.hpp's own file header documents this identical disposition and cites the same spec defect; nothing is ported for it in this codebase either, matching c-RCP's own choice rather than guessing at a resolution. No test exists for it (correctly -- tests/test_spi.cpp's own top-of-file fusa:test manifest deliberately omits REQ-SPI-037)." + }, + { + "id": "REQ-UART-001", + "title": "rcp_ep_uart_nr_bits_valid() accepts exactly 1..8", + "text": "rcp_ep_uart_nr_bits_valid() shall return true for nr_bits in RCP_EP_UART_NR_BITS_MIN..RCP_EP_UART_NR_BITS_MAX (1..8) inclusive and false for 0 or any value above 8.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51 (\"uart_nr_bits ... Nr of data bits\", 8 bit R/W), TC18.txt L5343", + "tc18_master_id": "TC18-13.7.8.2-001", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-001 (\"UART TX queue is independent of the RX FIFO\"). Genuinely implemented+tested: rcp::uart::nr_bits_valid() accepts exactly 1..8 -- tests/test_uart.cpp's \"nr_bits_valid accepts 1..8 and rejects everything else\" TEST_CASE (tagged [REQ-UART-001]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-UART-002", + "title": "rcp_ep_uart_bit_pad_mask() computes (1 << nr_bits) - 1, and 0 for an invalid nr_bits", + "text": "rcp_ep_uart_bit_pad_mask() shall return (1u << nr_bits) - 1 for every rcp_ep_uart_nr_bits_valid() nr_bits (0xFF for nr_bits == 8, 0x7F for nr_bits == 7, ...) and 0 for any nr_bits outside 1..8.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.3 (\"In case uart_nr_bits is not a multiple integer of 8, then the RC Client might need to append up to 'uart_nr_bits - 1' bits...\"), TC18.txt L5402-5403", + "tc18_master_id": "TC18-13.7.8.3-002", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-002 (\"UART RX FIFO fill/drain semantics\"). Genuinely implemented+tested: rcp::uart::bit_pad_mask() computes (1<common to false, baud_rate/ep_rx_buffer_size/uart_timeout_ms to 0, parity to RCP_EP_UART_PARITY_NONE, stop_bits to RCP_EP_UART_STOP_BITS_ONE, and cfg->uart_nr_bits to RCP_EP_UART_NR_BITS_MAX (8), regardless of cfg's prior contents.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-004 (\"UART payload-less pure read requests\"). Genuinely implemented+tested: rcp::uart::functional_cfg_init() zero-initializes cfg except uart_nr_bits (left at kNrBitsMax) -- tests/test_uart.cpp's \"functional_cfg_init zeroes every field except uart_nr_bits\" TEST_CASE (tagged [REQ-UART-004]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-UART-005", + "title": "rcp_ep_uart_functional_cfg_writable() is false while HW_UNCONFIGURED", + "text": "rcp_ep_uart_functional_cfg_writable() shall return false for state == RCP_LIFECYCLE_HW_UNCONFIGURED, for any writer, by delegating to rcp_server_field_writable() with kind RCP_LIFECYCLE_FIELD_FUNCTIONAL_W.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.2 (\"...all access to the HW_config and EP_generic_config are locked.\"), TC18.txt L2553-2554", + "tc18_master_id": "TC18-12.3.1.2-001", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-005 (\"UART sub-octet bit-width padding rules\"). Genuinely implemented+tested: rcp::uart::functional_cfg_writable() is false while HwUnconfigured -- tests/test_uart.cpp's \"functional_cfg_writable is false in HwUnconfigured regardless of writer\" TEST_CASE (tagged [REQ-UART-005]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-UART-006", + "title": "rcp_ep_uart_functional_cfg_writable() requires an authorized writer while HW_CONFIGURED", + "text": "rcp_ep_uart_functional_cfg_writable() shall return true for state == RCP_LIFECYCLE_HW_CONFIGURED if and only if writer.via_root_client_ep0, writer.via_owning_stream, or writer.via_discovery_stream is true, and false for an unauthorized writer. Corrected 2026-08-10 (c-RCP-AUDIT-06, issue #256 Group F): this entry previously claimed \"regardless of writer's contents\", superseded by REQ-LIFECYCLE-030/036's authorization-gating fix (issue #198) -- the code was already correct; only this entry's own text had gone stale.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.2 (\"Write access via EP0 to other EPs configuration is only possible for a configured 'root client' of via the discovery stream.\"), TC18.txt L2560", + "tc18_master_id": "TC18-12.3.1.2-004", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-006 (\"UART RX FIFO / read_size single-AVTPDU accepted limitation\"). Genuinely implemented+tested: rcp::uart::functional_cfg_writable() in HwConfigured requires EP0/owning-stream/discovery-stream -- tests/test_uart.cpp's \"functional_cfg_writable in HwConfigured requires EP0/owning-stream/discovery-stream\" TEST_CASE (tagged [REQ-UART-006]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-UART-007", + "title": "rcp_ep_uart_functional_cfg_writable() requires authorization once RCP_CONFIGURED", + "text": "rcp_ep_uart_functional_cfg_writable() shall return false for state == RCP_LIFECYCLE_RCP_CONFIGURED when writer has neither via_root_client_ep0 nor via_owning_stream set, and true when either is set.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3 (\"...only write access to the EP's functional configurations is allowed via their dedicated stream_id/byte_bus_id combinations or via root client access EP0... Write access to some parameters might be prohibited in this life-cycle state, this is marked by * in the R/W-column of the respective tables.\"), TC18.txt L2581-2582, L2601-2602", + "tc18_master_id": "TC18-12.3.1.3-001", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-007 (\"UartErrc is a distinct error category with a non-empty message\"). Genuinely implemented+tested: rcp::uart::functional_cfg_writable() in RcpConfigured requires EP0/owning-stream, not discovery -- tests/test_uart.cpp's \"functional_cfg_writable in RcpConfigured requires EP0/owning-stream, not discovery\" TEST_CASE (tagged [REQ-UART-007]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-UART-008", + "title": "rcp_ep_uart_set_baud_rate() rejects an unauthorized write", + "text": "rcp_ep_uart_set_baud_rate() shall return false and leave cfg unchanged when rcp_ep_uart_functional_cfg_writable() does not authorize the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51 (\"uart_baud_rate ... Baud rate in kbit/s\", 16 bit R/W), TC18.txt L5342 -- NOTE: units diverge from TC18's own field (this implementation uses uint32_t with no documented unit); tracked separately at REQ-UART-037", + "tc18_master_id": "TC18-13.7.8.2-001", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-008 (\"UartEndpoint::handle_request applies Table 33 Row 2 evt[2:0] classification before routing on req.op to enqueue_tx or handle_read\"). Genuinely implemented+tested: rcp::uart::set_baud_rate() rejects an unauthorized writer -- tests/test_uart.cpp's \"set_baud_rate rejects an unauthorized writer\" TEST_CASE (tagged [REQ-UART-008]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-UART-009", + "title": "rcp_ep_uart_set_baud_rate() applies an authorized write", + "text": "rcp_ep_uart_set_baud_rate() shall set cfg->baud_rate to baud_rate and return true when rcp_ep_uart_functional_cfg_writable() authorizes the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same authorization basis as REQ-UART-007", + "tc18_master_id": "TC18-12.3.1.3-005", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-UART-009 (\"UartEndpoint::handle_request reports config-write (evt[2:0]==111b) as not yet supported\"). Genuinely implemented+tested: rcp::uart::set_baud_rate() applies the write when authorized -- tests/test_uart.cpp's \"set_baud_rate applies when authorized\" TEST_CASE (tagged [REQ-UART-009]) (tests/test_uart.cpp)." + }, + { + "id": "REQ-WAKEUP-001", + "title": "rcp_ep_wakeup_functional_cfg_init() zero-initializes a wakeup functional config", + "text": "rcp_ep_wakeup_functional_cfg_init() shall zero-initialize cfg (including every sources[] entry) and initialize cfg->common via rcp_regmap_ep_functional_cfg_init().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-WAKEUP-001 (\"Wakeup control's ep_type id is 0x01\"). Genuinely implemented+tested: WakeupFunctionalConfig's default-constructed state is fully cleared (ep_enable false, wup_status clear, ep_status 0, repetition_time_us 0, every source disabled) -- tests/test_wakeup.cpp's \"WakeupFunctionalConfig defaults to a fully cleared configuration\" TEST_CASE (tagged [REQ-WAKEUP-001]) (tests/test_wakeup.cpp)." + }, + { + "id": "REQ-WAKEUP-002", + "title": "rcp_ep_wakeup_functional_cfg_writable() delegates to the shared field-authorization logic", + "text": "rcp_ep_wakeup_functional_cfg_writable() shall return rcp_lifecycle_field_writable(state, RCP_LIFECYCLE_FIELD_FUNCTIONAL_W, writer).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.2/.3, TC18.txt L2553-2554, L2601-2602 -- §12.3.1.3 W* marker convention, TC18.txt L2601-2602", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-WAKEUP-002 (\"SleepCMD is a fixed opcode, distinct from rcp::sequencer's RequestTypeOpcode taxonomy\"). Genuinely implemented+tested: rcp::wakeup::functional_cfg_writable() delegates to the shared lifecycle::field_writable() authorization logic -- tests/test_wakeup.cpp's \"functional_cfg_writable delegates to the shared lifecycle field-authorization logic\" TEST_CASE (tagged [REQ-WAKEUP-002]) (tests/test_wakeup.cpp)." + }, + { + "id": "REQ-WAKEUP-003", + "title": "rcp_ep_wakeup_source_asserted() applies one source's own polarity", + "text": "rcp_ep_wakeup_source_asserted() shall return true iff cfg.enabled is true and pin_level equals cfg.active_high.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 40 (wake-up source pin configuration, IO_SRC[15:11]), TC18.txt L4533; reduced to a single active_high/active_low sense rather than Table 40's six-value IO_SRC encoding -- see the pre-existing gap REQ-WAKEUP-022", + "tc18_master_id": "TC18-13.7.2.2-003", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-WAKEUP-003 (\"Wake-source pin monitoring\"). Genuinely implemented+tested: rcp::wakeup::source_asserted() applies one source's own active_high polarity, and is always false while disabled -- tests/test_wakeup.cpp's \"source_asserted applies one source's own polarity\"/\"source_asserted is always false when the source is disabled\" TEST_CASEs (tagged [REQ-WAKEUP-003]) (tests/test_wakeup.cpp)." + }, + { + "id": "REQ-WAKEUP-004", + "title": "rcp_ep_wakeup_any_source_asserted() reports whether any configured source is asserted", + "text": "rcp_ep_wakeup_any_source_asserted() shall return false when fcfg is NULL or when pin_levels is NULL with pin_level_count > 0, and otherwise return true iff rcp_ep_wakeup_source_asserted() is true for at least one of the first min(pin_level_count, RCP_EP_WAKEUP_MAX_SOURCES) source/pin_level pairs.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.1 (\"the endpoint listens to configurable IO signals for activity... When the WakeUp endpoint detects activity during sleep mode it wakes up the RC Server\"), TC18.txt L4484-4488; §13.7.2.2 Table 39 (ep1 - functional configuration), TC18.txt L4496-4515 (wup_nr_io_pins_max, io_scr1/2 entries) -- see the pre-existing gap REQ-WAKEUP-021 for the reduced register model", + "tc18_master_id": "TC18-13.7.2.2-002", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-WAKEUP-004 (\"Repeating WakeUp message handshake for hot-start-from-Sleep\"). Genuinely implemented+tested: rcp::wakeup::any_source_asserted() reports whether any configured source is asserted, consulting only the first min(levels, kMaxWakeSources) entries -- tests/test_wakeup.cpp's \"any_source_asserted reports whether any configured source is asserted\"/\"any_source_asserted only consults the first min(levels, kMaxWakeSources) entries\" TEST_CASEs (tagged [REQ-WAKEUP-004]) (tests/test_wakeup.cpp)." + }, + { + "id": "REQ-WAKEUP-005", + "title": "rcp_ep_wakeup_wup_status_init() clears the wup_status latch", + "text": "rcp_ep_wakeup_wup_status_init() shall set s->latched to false.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39 (ep1 - functional configuration), TC18.txt L4496-4515 (wup_status, \"Indication of wake-up source, writing '1' clears the flag. Each bit represents a wake-up source\"), TC18.txt L4505-4507 -- modeled as a single latch rather than a 16-bit per-source bitfield, see the pre-existing gap REQ-WAKEUP-021", + "tc18_master_id": "TC18-13.7.2.2-002", + "gap": "NOT a behavioral gap -- an id-collision traceability gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)). The behavior itself is genuinely implemented and tested. The blocker is that cpp-RCP's pre-existing catalog range for this low id predates this rewrite's later convention of reusing c-RCP's exact ids: this specific id was already assigned, by file order at the time, to an unrelated pre-rewrite requirement, and this id is already taken in .fusa-reqs.json by a materially different, already-catalogued requirement. Adding a second, conflicting entry under the same id would corrupt the catalog's own id uniqueness and is not attempted here. Filed so a future renumbering-cleanup batch (out of this batch's own scope) can resolve the collision and migrate this entry in. Already taken by: this catalog's own REQ-WAKEUP-005 (\"WakeupErrc is a distinct error category with a non-empty message\"). Genuinely implemented+tested: rcp::wakeup::WupStatus starts clear (mask() == 0, is_clear() true) -- tests/test_wakeup.cpp's \"WupStatus starts clear\" TEST_CASE (tagged [REQ-WAKEUP-005]) (tests/test_wakeup.cpp)." + }, + { + "id": "REQ-WAKEUP-026", + "title": "rcp_regmap_ep0_decode_write_request() denies an EP_ID_config write that would violate a configured fixed-ep_id invariant", + "text": "rcp_regmap_ep0_decode_write_request() shall, when ep_id_map_ep_types is non-NULL, deny an EP_ID_config write with RCP_ERROR_INVALID_PARAMETER and leave the table entirely unchanged whenever the write's own would-be result (rendered from the table's current content, patched with the write's own combined bytes) would leave any row whose ep_types[i] equals fixed_ep_id_target_ep_type with an ep_id other than fixed_ep_id_required_ep_id, and shall apply the write normally otherwise (including when ep_id_map_ep_types is NULL, meaning no enforcement is configured).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.1, TC18.txt L4482-4483 -- CLOSED 2026-08-13 (tc18-gap backlog PR G, issue #336): enforces at write time the invariant REQ-WAKEUP-020's own diagnostic only ever detected after the fact. Static ep_id_map_write_keeps_fixed_ep_id() (src/regmap.c) peeks what a write's own touched row(s) would become -- via the same render-then-patch half of rcp_regmap_ep_id_map_apply_reconfig()'s own idiom, stopped short of committing. Same caller-supplied-target design as REQ-WAKEUP-020's own diagnostic: regmap.c keeps no dependency on ep_wakeup.h and does not hardcode RCP_EP_WAKEUP_EP_TYPE/RCP_EP_WAKEUP_ENDPOINT_NUM -- a real caller supplies ep_wakeup.h's own concrete values. Split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-020's own prior bundled text, which described this enforcement mechanism alongside the unrelated read-only diagnostic function under one id.", + "tc18_master_id": "TC18-13.7.2.1-001", + "gap": "Genuine behavioral gap (2026-08-22, cpp-RCP Phase 6 batch 10 (SPI/UART/WAKEUP)), NOT an id-collision. This requirement's real content lives in c-RCP's regmap.c (rcp_regmap_ep0_decode_write_request()'s fixed-ep_id write-time enforcement), not ep_wakeup.c -- it uses the REQ-WAKEUP prefix only because the invariant it enforces is WakeUp's own fixed EP_Nr (TC18 §13.7.2.1). cpp-RCP's include/rcp/regmap.hpp already ports the READ-ONLY diagnostic half of this pair (REQ-WAKEUP-020's own ep_id_map::ep_type_has_fixed_ep_id(), fully implemented and tested -- see that id's own catalog entry) but does NOT port the WRITE-TIME enforcement half: ep_id_map::apply_reconfig() (regmap.hpp, the EP_ID_config table's own reconfig path) applies every in-range write unconditionally -- it never calls ep_type_has_fixed_ep_id() (or an equivalent would-be-result check) before committing, so a conforming write that would leave WakeUp's own EP_Nr row at anything other than the required fixed value 1 is silently accepted rather than denied with RCP_ERROR_INVALID_PARAMETER as c-RCP's own rcp_regmap_ep0_decode_write_request() does. No test exists for this rejection path because the rejection path itself does not exist. Fix would add a caller-supplied (target_ep_type, required_ep_id, ep_types[]) parameter set to ep_id_map::apply_reconfig() (or a wrapper around it) that peeks the would-be-patched result via the same render-then-check idiom the read-only diagnostic already uses, and rejects before committing -- out of this batch's scope (regmap.hpp is not one of this batch's three in-scope modules)." } ] } diff --git a/.fusa-reqs.json b/.fusa-reqs.json index bae17dd..600b53c 100644 --- a/.fusa-reqs.json +++ b/.fusa-reqs.json @@ -9021,6 +9021,1268 @@ "status": "implemented", "tc18": "§13.5 Table 33, TC18.txt L4069-4116; §13.7.6.2 Table 48, TC18.txt L5104-5149", "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-SPI-006", + "title": "rcp_ep_spi_trigger_fires() never fires for RCP_EP_SPI_TRIGGER_NONE", + "text": "rcp_ep_spi_trigger_fires() shall return false for trigger == RCP_EP_SPI_TRIGGER_NONE regardless of event. CLARIFIED (2026-08-10, c-RCP-AUDIT-06, issue #256 Group C): NONE, and this module's entire 4-value rcp_ep_spi_trigger_t, is an original simplification -- TC18 Table 41 (renumbered from Table 38 by the 0.5.1_RC5 rebaseline) documents 14 fixed, always-on, per-CS-channel trigger signals (execution-done plus an assert/de-assert pair for each of CS0-CS5) with no off/none state and no client-selectable register at all (Table 42, formerly Table 39, has no trigger-select field). See ep_spi.h's own file header for the full clarification.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.1 Table 41 (0.5.1_RC5; renumbered from Table 38 by the RC5 rebaseline -- fresh PDF extraction confirms Table 38 is now the unrelated RC-Server worked example), TC18.txt L4603-4611 (\"An SPI endpoint optionally creates the following HW trigger events\") -- names 14 fixed, per-CS-channel hardware signals, not a client-configurable field this module's 4-value enum reproduces. Same renumbering REQ-SPI-034's own already-fixed citation documents.", + "tc18_master_id": "TC18-13.7.3.1-006" + }, + { + "id": "REQ-SPI-007", + "title": "rcp_ep_spi_trigger_fires() implements RCP_EP_SPI_TRIGGER_TRANSFER_DONE", + "text": "rcp_ep_spi_trigger_fires() shall return true for trigger == RCP_EP_SPI_TRIGGER_TRANSFER_DONE iff event == RCP_EP_SPI_EVENT_TRANSFER_DONE.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.1 Table 41 (0.5.1_RC5; renumbered from Table 38 -- see REQ-SPI-006/REQ-SPI-034), TC18.txt L4603-4611 (trigger signal 0, \"SPI execution done\").", + "tc18_master_id": "TC18-13.7.3.1-007" + }, + { + "id": "REQ-SPI-008", + "title": "rcp_ep_spi_trigger_fires() implements RCP_EP_SPI_TRIGGER_CS_ASSERT", + "text": "rcp_ep_spi_trigger_fires() shall return true for trigger == RCP_EP_SPI_TRIGGER_CS_ASSERT iff event == RCP_EP_SPI_EVENT_CS_ASSERT.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.1 Table 41 (0.5.1_RC5; renumbered from Table 38 -- see REQ-SPI-006/REQ-SPI-034), TC18.txt L4603-4611 (trigger signals 2+2n, \"CSn asserted\", 0<=n<16 in the current RC5 wording, narrowed to this module's 6 channels).", + "tc18_master_id": "TC18-13.7.3.1-007" + }, + { + "id": "REQ-SPI-009", + "title": "rcp_ep_spi_trigger_fires() implements RCP_EP_SPI_TRIGGER_CS_DEASSERT", + "text": "rcp_ep_spi_trigger_fires() shall return true for trigger == RCP_EP_SPI_TRIGGER_CS_DEASSERT iff event == RCP_EP_SPI_EVENT_CS_DEASSERT.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.1 Table 41 (0.5.1_RC5; renumbered from Table 38 -- see REQ-SPI-006/REQ-SPI-034), TC18.txt L4603-4611 (trigger signals 3+2n, \"CSn de-asserted\", 0<=n<16 in the current RC5 wording, narrowed to this module's 6 channels).", + "tc18_master_id": "TC18-13.7.3.1-007" + }, + { + "id": "REQ-SPI-010", + "title": "rcp_ep_spi_functional_cfg_init() zero-initializes cfg", + "text": "rcp_ep_spi_functional_cfg_init() shall set every common flag false and, for every channel, mode = RCP_EP_SPI_MODE_0, bit_order = RCP_EP_SPI_BIT_ORDER_MSB_FIRST, cs_polarity = RCP_EP_SPI_CS_ACTIVE_LOW, trigger = RCP_EP_SPI_TRIGGER_NONE, and clock_divider/inter_byte_delay_ns/inter_transfer_delay_ns all 0.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented" + }, + { + "id": "REQ-SPI-011", + "title": "rcp_ep_spi_functional_cfg_writable() is unwritable while HW_UNCONFIGURED", + "text": "rcp_ep_spi_functional_cfg_writable() shall return false for state == RCP_LIFECYCLE_HW_UNCONFIGURED regardless of writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.2 (\"...all access to the HW_config and EP_generic_config are locked.\"), TC18.txt L2553-2554", + "tc18_master_id": "TC18-12.3.1.2-001" + }, + { + "id": "REQ-SPI-012", + "title": "rcp_ep_spi_functional_cfg_writable() requires an authorized writer while HW_CONFIGURED", + "text": "rcp_ep_spi_functional_cfg_writable() shall return true for state == RCP_LIFECYCLE_HW_CONFIGURED if and only if writer.via_root_client_ep0, writer.via_owning_stream, or writer.via_discovery_stream is true, and false for an unauthorized writer. Corrected 2026-08-10 (c-RCP-AUDIT-06, issue #256 Group F): this entry previously claimed \"regardless of writer\", superseded by REQ-LIFECYCLE-030/036's authorization-gating fix (v0.156.0, issue #198) -- the code and this module's own test (test_functional_cfg_writable_hw_configured_requires_authorization_or_discovery_stream, tests/test_ep_spi.c) were already correct; only this entry's own text had gone stale.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.2 (\"Write access via EP0 to other EPs configuration is only possible for a configured 'root client' of via the discovery stream.\"), TC18.txt L2560", + "tc18_master_id": "TC18-12.3.1.2-004" + }, + { + "id": "REQ-SPI-013", + "title": "rcp_ep_spi_functional_cfg_writable() requires authorization once RCP_CONFIGURED", + "text": "rcp_ep_spi_functional_cfg_writable() shall return false for state == RCP_LIFECYCLE_RCP_CONFIGURED when writer indicates neither via_root_client_ep0 nor via_owning_stream, and true when either is set.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3 (\"...only write access to the EP's functional configurations is allowed via their dedicated stream_id/byte_bus_id combinations or via root client access EP0... Write access to some parameters might be prohibited in this life-cycle state, this is marked by * in the R/W-column of the respective tables.\"), TC18.txt L2581-2582, L2601-2602", + "tc18_master_id": "TC18-12.3.1.3-001" + }, + { + "id": "REQ-SPI-014", + "title": "rcp_ep_spi_set_channel_mode() rejects an invalid channel or an unauthorized write without mutating cfg", + "text": "rcp_ep_spi_set_channel_mode() shall return false and leave cfg unchanged when channel is not rcp_ep_spi_channel_valid() or the write is not authorized by rcp_ep_spi_functional_cfg_writable().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.1 (\"the SPI endpoint may support up to 6 pre-configurable sets of SPI configurations\") is now a stale quote -- current RC5 §13.7.3.1 prose has been edited in place (not-yet-accepted BBID proposal) to read \"up to 16\"; §12.3.1.3, TC18.txt L2601-2602 (W* marker convention) remains accurate and should be cited alone, same basis as REQ-SPI-013. See REQ-SPI-002's finding for the full explanation.", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-015", + "title": "rcp_ep_spi_set_channel_mode() applies the write when authorized", + "text": "rcp_ep_spi_set_channel_mode() shall return true and set cfg->channels[channel].mode to the requested mode when channel is valid and the write is authorized.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-SPI-013", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-016", + "title": "rcp_ep_spi_set_channel_bit_order() rejects an invalid channel or an unauthorized write without mutating cfg", + "text": "rcp_ep_spi_set_channel_bit_order() shall return false and leave cfg unchanged when channel is not rcp_ep_spi_channel_valid() or the write is not authorized by rcp_ep_spi_functional_cfg_writable(). CORRECTED (2026-08-10, c-RCP-AUDIT-06, issue #256): the prior citation named Table 39 fields (spi_clk_polarity0/spi_clk_phase0) as \"bit-order-adjacent\", implying bit_order has a TC18 counterpart nearby -- it does not. That table (renumbered Table 42 by the 2026-08-11 RC5 rebaseline) defines no bit-order field at all (MSB-first/LSB-first is this module's own original addition); the channel-validity/authorization behavior this requirement actually describes is correctly implemented and is what §12.3.1.3's W* marker convention governs. See ep_spi.h's own file header.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- governs the write-authorization behavior; bit_order itself has no TC18 basis (see ep_spi.h's file header)", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-017", + "title": "rcp_ep_spi_set_channel_bit_order() applies the write when authorized", + "text": "rcp_ep_spi_set_channel_bit_order() shall return true and set cfg->channels[channel].bit_order to the requested bit_order when channel is valid and the write is authorized.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-SPI-013", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-018", + "title": "rcp_ep_spi_set_channel_cs_polarity() rejects an invalid channel or an unauthorized write without mutating cfg", + "text": "rcp_ep_spi_set_channel_cs_polarity() shall return false and leave cfg unchanged when channel is not rcp_ep_spi_channel_valid() or the write is not authorized by rcp_ep_spi_functional_cfg_writable().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42 (0.5.1_RC5; formerly Table 39) (\"spi_cs_polarity0 ... polarity of CS signal, 0b: CS is low active, 1b: CS is high active\"), TC18.txt L4660-4662; §12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same Table 39→42 renumbering as REQ-SPI-003.", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-019", + "title": "rcp_ep_spi_set_channel_cs_polarity() applies the write when authorized", + "text": "rcp_ep_spi_set_channel_cs_polarity() shall return true and set cfg->channels[channel].cs_polarity to the requested cs_polarity when channel is valid and the write is authorized.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-SPI-013", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-020", + "title": "rcp_ep_spi_set_channel_clock_divider() rejects an invalid channel or an unauthorized write without mutating cfg", + "text": "rcp_ep_spi_set_channel_clock_divider() shall return false and leave cfg unchanged when channel is not rcp_ep_spi_channel_valid() or the write is not authorized by rcp_ep_spi_functional_cfg_writable().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42 (0.5.1_RC5; formerly Table 39) (\"spi_baud_rate0 ... SPI baud rate in kbit/s\"), TC18.txt L4652; §12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same Table 39→42 renumbering as REQ-SPI-003. NOTE: this module's own clock_divider field is a distinct, non-wire-mapped abstraction from spi_baud_rate0 (which rcp_ep_spi_channel_cfg_t separately models as baud_rate_kbps, per REQ-SPI-035) -- the cited register is the closest TC18 analogue, not a literal wire mapping of clock_divider itself.", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-021", + "title": "rcp_ep_spi_set_channel_clock_divider() applies the write when authorized", + "text": "rcp_ep_spi_set_channel_clock_divider() shall return true and set cfg->channels[channel].clock_divider to the requested value when channel is valid and the write is authorized.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-SPI-013", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-022", + "title": "rcp_ep_spi_set_channel_timing() rejects an invalid channel or an unauthorized write without mutating cfg", + "text": "rcp_ep_spi_set_channel_timing() shall return false and leave cfg unchanged when channel is not rcp_ep_spi_channel_valid() or the write is not authorized by rcp_ep_spi_functional_cfg_writable().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42 (0.5.1_RC5; formerly Table 39) (\"spi_cs_clk_leadtime0\"/\"spi_clk_cs_trailtime0\"/\"spi_bits_max0\"/\"spi_pause_min0\" timing fields), TC18.txt L4672-4681; §12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same Table 39→42 renumbering as REQ-SPI-003. NOTE: this module's own inter_byte_delay_ns/inter_transfer_delay_ns fields are this module's original nanosecond-denominated addition, distinct from the wire's spi_clk-cycle-denominated leadtime/trailtime/pause_min fields (which rcp_ep_spi_channel_cfg_t separately models as cs_clk_leadtime/clk_cs_trailtime/pause_min, per REQ-SPI-035) -- the cited registers are the closest TC18 analogue, not a literal wire mapping of this setter's own two fields.", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-023", + "title": "rcp_ep_spi_set_channel_timing() applies the write when authorized", + "text": "rcp_ep_spi_set_channel_timing() shall return true and set cfg->channels[channel].inter_byte_delay_ns and inter_transfer_delay_ns to the requested values when channel is valid and the write is authorized.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-SPI-013", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-024", + "title": "rcp_ep_spi_set_channel_trigger() rejects an invalid channel or an unauthorized write without mutating cfg", + "text": "rcp_ep_spi_set_channel_trigger() shall return false and leave cfg unchanged when channel is not rcp_ep_spi_channel_valid() or the write is not authorized by rcp_ep_spi_functional_cfg_writable(). CLARIFIED (2026-08-10, c-RCP-AUDIT-06, issue #256 Group C): the channel-validity/authorization behavior this requirement describes is correctly implemented and governed by §12.3.1.3's W* marker convention; the `trigger` concept being written is this module's own original simplification of Table 41's (renumbered from Table 38 by the 0.5.1_RC5 rebaseline) 14 fixed hardware signals -- see REQ-SPI-006 and ep_spi.h's own file header.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- governs the write-authorization behavior; Table 41 (0.5.1_RC5; renumbered from Table 38, trigger outputs), TC18.txt L4603-4611, is the fixed-signal basis `trigger` simplifies (see REQ-SPI-006/REQ-SPI-034).", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-025", + "title": "rcp_ep_spi_set_channel_trigger() applies the write when authorized", + "text": "rcp_ep_spi_set_channel_trigger() shall return true and set cfg->channels[channel].trigger to the requested trigger when channel is valid and the write is authorized.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-SPI-013", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-SPI-026", + "title": "SPI transfer request encode uses the read-direction op", + "text": "rcp_ep_spi_encode_transfer_request() shall encode op RCP_ACF_OP_READ (the reply-expected direction). SPLIT 2026-08-18 (c-RCP-18-tracker, issue #533): the decode round-trip-recovery half of this id is now REQ-SPI-041.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.3 (\"...even if the read_size is less than the number of bytes in the byte_msg_payload.\"), TC18.txt L4767-4769; Figure 24 (renumbered from Figure 23 by the 0.5.1_RC5 rebaseline) worked example (\"SPI request (example to write 20 bytes and get a response with 10 on SPI channel 3)\", op=0/read direction), TC18.txt L4764 -- fresh PDF extraction confirms current Figure 23 is now \"Endpoint sleep request\", an unrelated figure; channel selection per §13.5 Table 33 SPI row (unchanged).", + "tc18_master_id": "TC18-13.7.3.3-007" + }, + { + "id": "REQ-SPI-027", + "title": "rcp_ep_spi_decode_transfer_request() rejects a malformed, misaddressed, or bad-channel frame", + "text": "rcp_ep_spi_decode_transfer_request() shall return RCP_EP_SPI_ERR_SHORT_FRAME for a frame shorter than the ACF_ABB fixed header or its declared payload length, RCP_EP_SPI_ERR_BAD_MSG_TYPE for a non-ACF_ABB frame, RCP_EP_SPI_ERR_WRONG_BUS when byte_bus_id != expected_bus_id, RCP_EP_SPI_ERR_WRONG_OP when op is not RCP_ACF_OP_READ, and RCP_EP_SPI_ERR_BAD_CHANNEL when evt[2:0] is not rcp_ep_spi_channel_valid().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33, TC18.txt L4069-4116 (general ACF frame-validation basis, SPI row for channel selection)", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-SPI-028", + "title": "SPI response encode/decode round-trips when untimed", + "text": "rcp_ep_spi_decode_response() shall, given a frame produced by rcp_ep_spi_encode_response() with timed = false and the same byte_bus_id, return RCP_EP_SPI_OK, recover the original channel, POCI-in payload bytes, and transaction_num, and report *out_timed = false with *out_timestamp = 0.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.3 (\"The SPI EP shall append zeros in case the read_size is larger than the number of bytes in the byte_msg_payload.\"), TC18.txt L4767", + "tc18_master_id": "TC18-13.7.3.3-006" + }, + { + "id": "REQ-SPI-029", + "title": "SPI response encode/decode round-trips when timed", + "text": "rcp_ep_spi_decode_response() shall, given a frame produced by rcp_ep_spi_encode_response() with timed = true, the same byte_bus_id, and a timestamp, return RCP_EP_SPI_OK, recover the original channel, POCI-in payload bytes, and transaction_num, and report *out_timed = true with *out_timestamp equal to the original timestamp.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.3 (\"The SPI EP shall append zeros in case the read_size is larger than the number of bytes in the byte_msg_payload.\"), TC18.txt L4767", + "tc18_master_id": "TC18-13.7.3.3-006" + }, + { + "id": "REQ-SPI-030", + "title": "rcp_ep_spi_decode_response() rejects a malformed, misaddressed, or bad-channel frame", + "text": "rcp_ep_spi_decode_response() shall return RCP_EP_SPI_ERR_SHORT_FRAME for a frame too short for its applicable ACF fixed header, RCP_EP_SPI_ERR_WRONG_BUS when byte_bus_id != expected_bus_id, and RCP_EP_SPI_ERR_BAD_CHANNEL when evt[2:0] is not rcp_ep_spi_channel_valid().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33, TC18.txt L4069-4116 (general ACF frame-validation basis, SPI row for channel selection)", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-SPI-033", + "title": "evt[2:0] selects which of the six SPI channel configurations a request uses", + "text": "IMPLEMENTED (2026-08-12, issue #201 Phase 5e): the SPI endpoint carries RCP_EP_SPI_MAX_CHANNELS (6) independently pre-configured channel configurations (rcp_ep_spi_functional_cfg_t::channels), and rcp_ep_spi_decode_transfer_request() already extracts and validates the requesting channel from the request's evt[2:0] field (rcp_ep_spi_channel_valid()), returning it for a caller to index cfg->channels[] with, per TC18 13.7.3.1/13.7.3.2 -- the same evt-bits mechanism this codebase's own dedicated SPI channel-selection investigation (issue #256, task #98) independently confirmed correct against Table 33/§13.5. This entry's own catalogue text simply never caught up to the already-implemented behavior -- same stale-catalog-entry pattern found and fixed 4+ times this session (REQ-UART-036 and others). No code change: the deviation was in the catalogue, not the code.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (SPI row, evt[2:0] selects channel), TC18.txt L4076-4078 and §13.7.3.2 (spi_nr_cs), TC18.txt L4642", + "tc18_master_id": "TC18-13.7.3.2-006" + }, + { + "id": "REQ-SPI-034", + "title": "SPI trigger output numbering (Table 41)", + "text": "c-RCP now implements TC18 Table 41's SPI trigger output numbering via rcp_ep_spi_trigger_signal_number() -- signal 0 'SPI execution done' (whole-endpoint, not modelled by this per-channel function), signal 1 reserved, and signals 2+2n/3+2n pairing chip select CSn with an asserted/de-asserted event (0 <= n < 16, narrowed to this module's own 6 channels, i.e. signals 2..13). The endpoint's own per-channel trigger selector (rcp_ep_spi_trigger_t) stays the deliberately-collapsed, non-wire-rendered representation described in ep_spi.h's own file header; this numbering function is a separate, additive computation resolving a (channel, CS-edge) pair to its Table 41 signal number.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.1 Table 41, TC18.txt L4603-4611", + "tc18_master_id": "TC18-13.7.3.1-007" + }, + { + "id": "REQ-SPI-035", + "title": "SPI functional-config register block (Table 39/42) is fully modeled", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I): rcp_ep_spi_channel_cfg_t now carries every Table 39/42 per-channel field this module previously omitted -- baud_rate_kbps (spi_baud_rateN, kbit/s), use_common_cs (spi_use_csN), cs_clk_leadtime/clk_cs_trailtime (spi_cs_clk_leadtimeN/spi_clk_cs_trailtimeN, in spi_clk cycles, distinct from this module's own pre-existing nanosecond-denominated inter_byte_delay_ns/inter_transfer_delay_ns), and bits_max (spi_bits_maxN); rcp_ep_spi_functional_cfg_t gained ep_status (spi_ep_status). CPOL/CPHA continue to round-trip losslessly through the pre-existing mode byte via rcp_ep_spi_mode_cpol()/_cpha() and a new inverse. rcp_ep_spi_render_registers()/_apply_reconfig() (evt[2:0] == 111b, Table 33's SPI row + §12.7.1) now serialize/parse the whole block -- spi_ep_len and spi_nr_cs are rendered from RCP_EP_SPI_EP_FUNC_LEN/RCP_EP_SPI_MAX_CHANNELS and are read-only, matching PWM_OUT's/GPIO's own EP_LEN convention. UPDATED 2026-08-11 (spec rebaseline to TC18 0.5.1_RC5): spi_nr_cs (renumbered Table 39 -> Table 42) was narrowed from a plain 8-bit count to a 4-bit \"(count - 1)\" field (bits [3:0], upper nibble reserved) by spec revision RC4 -- rcp_ep_spi_render_registers() now renders (RCP_EP_SPI_MAX_CHANNELS - 1) & 0x0F (0x05) instead of the plain count (0x06). See REQ-SPI-040 for the new spi_deassert_cs_pauseN bit RC5 adds to the same block.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 39 (0.5.1_RC baseline)/Table 42 (0.5.1_RC5), TC18.txt L4628-4703; spi_nr_cs width corrected per RC5 PDF p.96 (051RC4 tag, ticket unlabeled -- \"this standard limits the number of CS line per EP to 32\")", + "tc18_master_id": "TC18-13.7.3.2-002" + }, + { + "id": "REQ-SPI-036", + "title": "SPI zero-fill when read_size exceeds the payload, full payload on PICO otherwise", + "text": "IMPLEMENTED (2026-08-12, issue #201 Phase 5e): the new rcp_ep_spi_transfer_length(tx_len, read_size) computes TC18 13.7.3.3's own transfer-length rule -- max(tx_len, read_size): a caller driving real SPI hardware clocks tx_data[0..tx_len) verbatim followed by zero octets up to the returned length when read_size exceeds tx_len (the bus clocks read_size octets total), and always clocks at least the full tx_len-byte payload on PICO even when read_size is smaller (never truncated). Mutation-tested: bypassing the max() computation caught cleanly; a `>` vs `>=` boundary mutation at read_size==tx_len is a provably equivalent mutant (both branches return the identical numeric value at that exact point) and needs no discriminating test. SPLIT 2026-08-18 (c-RCP-18-tracker, issue #533): the encode_transfer_request()/decode_transfer_request() read_size-carrying half of this id (a second, unrelated pair of functions bundled under the same id -- zero \"shall\" occurrences, missed by the 2+-\"shall\" proxy) is now REQ-SPI-044.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.3, TC18.txt L4767-4769" + }, + { + "id": "REQ-SPI-038", + "title": "rcp_ep_spi_render_registers() serializes the whole §12.7.1 EP_func register block", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I): TC18 §12.7.1 Figure 18 defines one generic configuration request -- evt[2:0] = 111b, byte_msg_payload = a relative register start address within the addressed endpoint's EP_func section followed by configuration data -- usable against every endpoint type. SPI's own Table 33 row confirms 111b carries this exact meaning (distinct from evt[2:0] 000b-101b, which select one of SPI's six pre-configured channels, and 110b, which is reserved/UNSUPPORTED_CMD). rcp_ep_spi_render_registers() serializes cfg's whole Table 39/42 block (the 6-octet common prefix plus six 8-octet per-channel blocks). SPLIT 2026-08-18 (c-RCP-18-tracker, issue #533): the encode_reconfig_request() half of this id (a second, unrelated function bundled under the same id, matching the REQ-AUTH-009 anti-pattern CONTRIBUTING.md documents) is now REQ-SPI-042.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 Configuration of endpoints + Figure 19 (renumbered from Figure 18 by the RC5 rebaseline), TC18.txt L2844-2860; §13.5 Table 33 (SPI row), TC18.txt L4076-4078", + "tc18_master_id": "TC18-12.7.1-001" + }, + { + "id": "REQ-SPI-039", + "title": "rcp_ep_spi_apply_reconfig() applies the addressed §12.7.1 configuration write", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I): rcp_ep_spi_apply_reconfig() decodes the address+data payload TC18 §12.7.1 defines and patches cfg's Table 39/42 register block at octet granularity, then adopts the whole block atomically -- a write whose start_address+length exceeds RCP_EP_SPI_EP_FUNC_LEN is rejected and cfg left entirely unchanged (RCP_EP_SPI_RECONFIG_ERR_OUT_OF_RANGE), matching §12.7.1's own 'such a payload is to be ignored' rule; octets landing on a read-only register (EP_LEN, NR_CS, or a channel's own reserved octet) are silently skipped while the rest of the span is still applied. SPLIT 2026-08-18 (c-RCP-18-tracker, issue #533): the reconfig_strerror() half of this id (a second, unrelated function bundled under the same id) is now REQ-SPI-043.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 Configuration of endpoints, TC18.txt L2844-2860", + "tc18_master_id": "TC18-12.7.1-003" + }, + { + "id": "REQ-SPI-040", + "title": "spi_deassert_cs_pauseN (Table 42, new in spec revision 0.5.1_RC5) is modeled", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, spec rebaseline to TC18 0.5.1_RC5): spi_deassert_cs_pauseN is a new configuration bit (bit 4 of a channel's own +0x02 cfg octet, ticket NXP_100) with no counterpart at all in the 0.5.1_RC baseline this module was originally built against -- \"0b: no de-assertion during break / 1b: de-assertion during break\" during the pause window spi_cs_clk_leadtimeN/spi_pause_minN/spi_clk_cs_trailtimeN define. rcp_ep_spi_channel_cfg_t gains a new deassert_cs_pause field (RCP_EP_SPI_CFG_BIT_DEASSERT_CS_PAUSE); rcp_ep_spi_render_registers()/parse_registers() (the rcp_ep_spi_apply_reconfig() inverse) render/parse it, leaving every pre-existing cfg bit (clk_polarity/clk_phase/cs_polarity/use_cs) untouched -- the same 'new field, existing fields left alone' rule already established for every prior Group I register-block fix this session.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.2 Table 42, TC18.txt L4663-4665, spec revision 0.5.1_RC5 PDF p.96 (ticket NXP_100, tags 051RC5 \"new configuration, optional\" + \"added for clarification\")", + "tc18_master_id": "TC18-13.7.3.2-004" + }, + { + "id": "REQ-SPI-041", + "title": "SPI transfer request decode recovers channel, PICO-out payload, and transaction_num on round trip", + "text": "rcp_ep_spi_decode_transfer_request() shall, given a frame produced by rcp_ep_spi_encode_transfer_request() with the same byte_bus_id, return RCP_EP_SPI_OK and recover the original channel, PICO-out payload bytes, and transaction_num. Split off REQ-SPI-026 (c-RCP-18-tracker, issue #533).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.3 (\"...even if the read_size is less than the number of bytes in the byte_msg_payload.\"), TC18.txt L4767-4769; Figure 24 (renumbered from Figure 23 by the 0.5.1_RC5 rebaseline) worked example (\"SPI request (example to write 20 bytes and get a response with 10 on SPI channel 3)\", op=0/read direction), TC18.txt L4764 -- fresh PDF extraction confirms current Figure 23 is now \"Endpoint sleep request\", an unrelated figure; channel selection per §13.5 Table 33 SPI row (unchanged).", + "tc18_master_id": "TC18-13.7.3.3-007" + }, + { + "id": "REQ-SPI-042", + "title": "rcp_ep_spi_encode_reconfig_request() encodes the §12.7.1 configuration write request", + "text": "rcp_ep_spi_encode_reconfig_request() shall encode an ACF_ABB write request (op=WRITE, evt=111b) carrying a 16-bit big-endian start address followed by data, matching PWM_OUT's/GPIO's own encode_reconfig_request() shape. Split off REQ-SPI-038 (c-RCP-18-tracker, issue #533).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 Configuration of endpoints + Figure 19 (renumbered from Figure 18 by the RC5 rebaseline), TC18.txt L2844-2860; §13.5 Table 33 (SPI row), TC18.txt L4076-4078", + "tc18_master_id": "TC18-12.7.1-001" + }, + { + "id": "REQ-SPI-043", + "title": "rcp_ep_spi_reconfig_strerror() never returns NULL", + "text": "rcp_ep_spi_reconfig_strerror() shall never return NULL, including for an unrecognized error code. Split off REQ-SPI-039 (c-RCP-18-tracker, issue #533).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 Configuration of endpoints, TC18.txt L2844-2860", + "tc18_master_id": "TC18-12.7.1-003" + }, + { + "id": "REQ-SPI-044", + "title": "SPI transfer request encode/decode carry read_size through the ACF header's read_size_or_segment_num field", + "text": "IMPLEMENTED (2026-08-12, issue #201 Phase 5e): rcp_ep_spi_encode_transfer_request()/_decode_transfer_request() carry read_size through the ACF header's own read_size_or_segment_num field (previously unwired) and recover it losslessly on decode. All existing call sites (src/adapt.c's RCP_ADAPT_OP_SPI_TRANSFER, plus test call sites) were updated for the new parameter when this was introduced; adapt.c defaults an absent rcp.spi.read_size meta key to the payload's own length, matching a request that asks for exactly what it sends back. Mutation-tested: dropping read_size on encode caught cleanly. Split off REQ-SPI-036 (c-RCP-18-tracker, issue #533).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.3.3, TC18.txt L4767-4769" + }, + { + "id": "REQ-UART-010", + "title": "rcp_ep_uart_set_frame_format() rejects an invalid nr_bits", + "text": "rcp_ep_uart_set_frame_format() shall return false and leave cfg unchanged when nr_bits is not rcp_ep_uart_nr_bits_valid(), regardless of state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51 (\"uart_nr_bits ... Nr of data bits\", 8 bit R/W), TC18.txt L5343", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-011", + "title": "rcp_ep_uart_set_frame_format() rejects an unauthorized write", + "text": "rcp_ep_uart_set_frame_format() shall return false and leave cfg unchanged when rcp_ep_uart_functional_cfg_writable() does not authorize the write for state/writer, even when nr_bits is valid.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same authorization basis as REQ-UART-007", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-UART-012", + "title": "rcp_ep_uart_set_frame_format() applies a valid, authorized write to all three fields together", + "text": "rcp_ep_uart_set_frame_format() shall set cfg->uart_nr_bits, cfg->parity, and cfg->stop_bits together and return true when nr_bits is rcp_ep_uart_nr_bits_valid() and rcp_ep_uart_functional_cfg_writable() authorizes the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51 (\"uart_nr_bits\"/\"uart_parity_enable\"/\"uart_parity_pol\"/\"uart_stop_bits\" fields), TC18.txt L5343, L5346, L5350, L5364", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-013", + "title": "rcp_ep_uart_set_rx_buffer_size() rejects an unauthorized write", + "text": "rcp_ep_uart_set_rx_buffer_size() shall return false and leave cfg unchanged when rcp_ep_uart_functional_cfg_writable() does not authorize the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"...the UART EP shifts the received data into a fifo-rx-buffer that has a length of uart_rx_fifo_size.\"), TC18.txt L5294 -- NOTE: TC18 describes uart_rx_fifo_size only in prose, not as a numbered Table 51 register; related gap tracked at REQ-UART-032/036", + "tc18_master_id": "TC18-13.7.8.1-002" + }, + { + "id": "REQ-UART-014", + "title": "rcp_ep_uart_set_rx_buffer_size() applies an authorized write", + "text": "rcp_ep_uart_set_rx_buffer_size() shall set cfg->ep_rx_buffer_size to rx_buffer_size and return true when rcp_ep_uart_functional_cfg_writable() authorizes the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same authorization basis as REQ-UART-007", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-UART-015", + "title": "rcp_ep_uart_set_timeout() rejects an unauthorized write", + "text": "rcp_ep_uart_set_timeout() shall return false and leave cfg unchanged when rcp_ep_uart_functional_cfg_writable() does not authorize the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51 (\"uart_timeout ... receiver timeout in bit times, timeout is measure from last received stop bit\", 8 bit R/W), TC18.txt L5366-5367 -- NOTE: units/representation diverge from TC18's own field; tracked separately at REQ-UART-037", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-016", + "title": "rcp_ep_uart_set_timeout() applies an authorized write", + "text": "rcp_ep_uart_set_timeout() shall set cfg->uart_timeout_ms to timeout_ms and return true when rcp_ep_uart_functional_cfg_writable() authorizes the write for state/writer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same authorization basis as REQ-UART-007", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-UART-017", + "title": "rcp_ep_uart_strerror() never returns NULL and returns distinct messages", + "text": "rcp_ep_uart_strerror() shall return a non-NULL, non-empty message for every rcp_ep_uart_errc_t value (including an out-of-range value), with a distinct message per defined error code.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented" + }, + { + "id": "REQ-UART-018", + "title": "rcp_ep_uart_encode_write_request() encodes an ACF_ABB write with evt = 0", + "text": "rcp_ep_uart_encode_write_request() shall produce an ACF_ABB frame with op == RCP_ACF_OP_WRITE, evt == 0, byte_bus_id == byte_bus_id, transaction_num == transaction_num, and payload exactly tx_data[0..tx_len).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (ADC/PWM_IN/I²C/LIN/CAN/UART/ISELED/MDIO row, evt[2:0]=000b-110b reserved so ordinary requests carry evt=0), TC18.txt L4083-4093; §13.7.8.1 (\"A write request leads to a transmission of data to an external connected device.\"), TC18.txt L5296", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-019", + "title": "rcp_ep_uart_decode_write_request() round-trips the raw TX payload", + "text": "rcp_ep_uart_decode_write_request() shall, given a frame produced by rcp_ep_uart_encode_write_request() and the same byte_bus_id, return RCP_EP_UART_OK and recover the original tx bytes and transaction_num unchanged, byte for byte.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (ADC/PWM_IN/I²C/LIN/CAN/UART/ISELED/MDIO row), TC18.txt L4083-4093", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-020", + "title": "rcp_ep_uart_decode_write_request() rejects a malformed, misaddressed, misdirected, or wrong-evt frame", + "text": "rcp_ep_uart_decode_write_request() shall return RCP_EP_UART_ERR_SHORT_FRAME for a frame too short for the ACF_ABB fixed header or its declared payload length, RCP_EP_UART_ERR_BAD_MSG_TYPE for a non-ACF_ABB frame, RCP_EP_UART_ERR_WRONG_BUS when byte_bus_id != expected_bus_id, RCP_EP_UART_ERR_WRONG_OP when op is not RCP_ACF_OP_WRITE, and RCP_EP_UART_ERR_BAD_EVT when evt[2:0] is not 0b000 -- TC18 §13.5 Table 33's only legal value for a plain request in UART's endpoint-type row; every other value shall be rejected with error code UNSUPPORTED_CMD at the dispatch layer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33, TC18.txt L4069-4116", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-021", + "title": "rcp_ep_uart_encode_write_response() encodes ACF_ABB when untimed and ACF_GBB when timed", + "text": "rcp_ep_uart_encode_write_response() shall produce an ACF_ABB frame when timed is false and an ACF_GBB frame with mtv == RCP_ACF_MTV_VALID and message_timestamp == timestamp when timed is true, in both cases with op == RCP_ACF_OP_WRITE, evt == 0, and payload exactly accepted_data[0..accepted_len).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"A write request leads to a transmission of data to an external connected device.\"), TC18.txt L5296; general ACF_ABB/ACF_GBB timed-response distinction, §11.2.1", + "tc18_master_id": "TC18-13.7.8.1-003" + }, + { + "id": "REQ-UART-022", + "title": "rcp_ep_uart_decode_write_response() round-trips the accepted-bytes payload and timing", + "text": "rcp_ep_uart_decode_write_response() shall, given a frame produced by rcp_ep_uart_encode_write_response(), the same byte_bus_id, and either timed value, return RCP_EP_UART_OK, recover the accepted payload bytes and transaction_num, and report *out_timed/*out_timestamp consistently with the original timed/timestamp arguments.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"A write request leads to a transmission of data to an external connected device.\"), TC18.txt L5296", + "tc18_master_id": "TC18-13.7.8.1-003" + }, + { + "id": "REQ-UART-023", + "title": "rcp_ep_uart_encode_read_request() carries read_size in the ACF header's read_size_or_segment_num field, with no payload", + "text": "rcp_ep_uart_encode_read_request() shall produce an ACF_ABB frame with op == RCP_ACF_OP_READ, evt == 0, read_size_or_segment_num == read_size, byte_bus_id == byte_bus_id, transaction_num == transaction_num, and an empty payload.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"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...\"), TC18.txt L5297-5298", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-024", + "title": "rcp_ep_uart_decode_read_request() round-trips read_size and transaction_num", + "text": "rcp_ep_uart_decode_read_request() shall, given a frame produced by rcp_ep_uart_encode_read_request() and the same byte_bus_id, return RCP_EP_UART_OK and recover the original read_size and transaction_num unchanged.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (ADC/PWM_IN/I²C/LIN/CAN/UART/ISELED/MDIO row), TC18.txt L4083-4093", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-025", + "title": "rcp_ep_uart_decode_read_request() rejects a payload-bearing read request with RCP_EP_UART_ERR_UNKNOWN_CMD", + "text": "rcp_ep_uart_decode_read_request() shall return RCP_EP_UART_ERR_UNKNOWN_CMD, rather than RCP_EP_UART_OK, when an otherwise well-formed read request carries a non-empty payload -- the deliberate asymmetry against GPIO/PWM_OUT request types documented in ep_uart.h. It shall also return RCP_EP_UART_ERR_BAD_EVT when evt[2:0] is not 0b000 -- TC18 §13.5 Table 33's only legal value for a plain request in UART's endpoint-type row; every other value shall be rejected with error code UNSUPPORTED_CMD at the dispatch layer.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33, TC18.txt L4069-4116", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-026", + "title": "rcp_ep_uart_encode_read_response() encodes ACF_ABB when untimed and ACF_GBB when timed", + "text": "rcp_ep_uart_encode_read_response() shall produce an ACF_ABB frame when timed is false and an ACF_GBB frame with mtv == RCP_ACF_MTV_VALID and message_timestamp == timestamp when timed is true, in both cases with op == RCP_ACF_OP_READ, evt == 0, and payload exactly rx_data[0..rx_len).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"...or in case the read_size is larger than the uart_rx_fifo_size, when the fifo is full. In the latter case the response is fragmented.\"), TC18.txt L5298-5299", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-027", + "title": "rcp_ep_uart_decode_read_response() round-trips a full-length and a short-read (single-AVTPDU) RX payload", + "text": "rcp_ep_uart_decode_read_response() shall, given a frame produced by rcp_ep_uart_encode_read_response() with rx_len equal to or less than the originating request's read_size, return RCP_EP_UART_OK and recover the rx payload bytes, transaction_num, and timed/timestamp state unchanged, with no segment_num-based reassembly performed or required for a same-AVTPDU short read.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"...or in case the read_size is larger than the uart_rx_fifo_size, when the fifo is full. In the latter case the response is fragmented.\"), TC18.txt L5298-5299", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-028", + "title": "rcp_ep_uart_decode_read_response() rejects a malformed or misaddressed frame", + "text": "rcp_ep_uart_decode_read_response() shall return RCP_EP_UART_ERR_SHORT_FRAME for a frame too short for its applicable ACF fixed header and RCP_EP_UART_ERR_WRONG_BUS when byte_bus_id != expected_bus_id.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (ADC/PWM_IN/I²C/LIN/CAN/UART/ISELED/MDIO row), TC18.txt L4083-4093", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-029", + "title": "rcp_ep_uart_read_response_fragment_count() delegates its answer to fragment.h's rcp_fragment_plan_count()", + "text": "rcp_ep_uart_read_response_fragment_count() shall return rcp_fragment_plan_count(rx_len, max_fragment_payload)'s answer for every input.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"...the response is fragmented. To support fragmentation properly it is essential that the uart_rx_fifo_size is chosen such that it is slightly bigger than the maximum byte_msg_payload to be generated within a single AVTPDU...\"), TC18.txt L5299-5301", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-030", + "title": "rcp_ep_uart_encode_read_response_fragmented() splits a UART read response's payload into correctly-numbered ACF fragments", + "text": "rcp_ep_uart_encode_read_response_fragmented() shall encode rcp_ep_uart_read_response_fragment_count() ACF frames whose ms/read_size_or_segment_num fields follow fragment.h's rcp_fragment_plan() and whose byte_bus_id/op/transaction_num/timed/timestamp match rcp_ep_uart_encode_read_response()'s own single-frame encoding, producing exactly one frame identical to that single-frame encoding when rx_len already fits in one fragment.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"...the response is fragmented.\"), TC18.txt L5299", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-031", + "title": "rcp_ep_uart_decode_read_response_fragment() surfaces a fragment's ms bit, segment_num, and raw payload on success", + "text": "rcp_ep_uart_decode_read_response_fragment() shall, on RCP_EP_UART_OK, populate out_ms and out_segment_num from the decoded ACF header's ms and read_size_or_segment_num fields and out_payload/out_payload_len as a borrowed view of the ACF payload.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (ADC/PWM_IN/I²C/LIN/CAN/UART/ISELED/MDIO row), TC18.txt L4083-4093", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-032", + "title": "UART EP status register (uart_ep_status) exists and round-trips, matching every other endpoint type's own status-register precedent", + "text": "IMPLEMENTED (2026-08-12, catalog-drift correction, issue #336): this requirement's own \"NOT IMPLEMENTED\" text was stale the day it was filed -- rcp_ep_uart_functional_cfg_t::ep_status (uart_ep_status, Table 51 0x0004, 16 bit R/W) has existed as a real, freely-settable, round-tripped register field since PR #276 (issue #256, 2026-08-11, the prior day), fully wired through rcp_ep_uart_render_registers()/_apply_reconfig() and covered by tests/test_ep_uart.c's own register-block round-trip test. TC18 §13.7.8.1 requires an RX FIFO overflow to be \"flagged in the UART EP status register\" but never defines which bit of that 16-bit register carries the flag -- the same \"_ep_status has no printed bit layout\" spec-silence pattern already accepted for CAN/WakeUp/several other endpoint types' own status registers (e.g. REQ-CANEP-028, which reached the identical disposition: \"Bus-off, error-passive and FIFO-overflow conditions are now observable and settable\" with no bit position invented). Consistent with that precedent, this module correctly does not invent an overflow bit -- it stores and round-trips whatever value a caller or register-map write assigns. tests/test_tc18_gaps_ep2.c's own deviation-pin test (renamed test_uart_rx_fifo_size_bounds_nothing_overflow_flag_left_uninterpreted) documents the one thing this genuinely does NOT do: ep_rx_buffer_size itself bounds nothing at the encode/decode layer, by design -- flagging overflow is uart_ep_status's job, and setting that flag from a live FIFO-fill condition is an integrator's runtime responsibility, not this wire/register library's.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1, TC18.txt L5294-5295 (overflow-flagging requirement); §13.7.8.2 Table 51, TC18.txt L5340-5341 (uart_ep_status register itself)", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-033", + "title": "UART read-response completion is triggered by read_size satisfied, uart_timeout expiry, or a full RX FIFO", + "text": "c-RCP now implements the UART read-request completion arbitration (TC18 §13.7.8.1) via rcp_ep_uart_read_completion_decision() — a pure, caller-driven function deciding, from (bytes_available, read_size, elapsed_ms, uart_timeout_ms, rx_fifo_size), which of the three triggers has fired: (a) the fifo-rx-buffer holds as many octets as the request's read_size, or (b) uart_timeout has expired, or (c) read_size exceeds uart_rx_fifo_size and the fifo has filled to capacity, in which case the response must be emitted via the pre-existing rcp_ep_uart_encode_read_response_fragmented(). This module still owns no real FIFO or clock (matching every other caller-driven primitive in this codebase, e.g. rcp_ep_spi_transfer_length()), so a caller supplies the current counters rather than this function tracking state itself.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1, TC18.txt L5297-5299", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-034", + "title": "UART read_size is narrowed to 8 bits, below the ACF header's 12-bit read_size field", + "text": "IMPLEMENTED (2026-08-12, issue #201 Phase 5e): rcp_ep_uart_encode_read_request()'s read_size parameter and rcp_ep_uart_decode_read_request()'s *out_read_size are now uint16_t, matching the ACF byte_message_info read_size_or_segment_num field's own full 12-bit width (0-4095, acf.h). c-RCP can now originate, and faithfully surface, a conforming peer's UART read request anywhere in the 0..4095 range -- previously narrowed to uint8_t, silently truncating any request above 255 (this file header's own since-corrected rationale, that this endpoint's traffic never actually needs fragment.h's ms/segment_num mechanism because 255 bytes always fits a single AVTPDU, did not survive TC18 §13.7.8.1's own text: a read_size larger than uart_rx_fifo_size is the THIRD read-completion trigger, explicitly driving a fragmented response via the mechanism this module already provides). Updated every call site (src/adapt.c's RCP_ADAPT_OP_UART_READ, plus test call sites across tests/test_ep_uart.c and tests/test_tc18_gaps_ep2.c). Mutation-tested (reintroducing the 8-bit truncation on decode): caught cleanly.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1, TC18.txt L5297-5299 (read_size field width)", + "tc18_master_id": "TC18-13.7.8.1-004" + }, + { + "id": "REQ-UART-035", + "title": "UART compound wait request comparison against the RX FIFO, bounded by uart_rx_fifo_size", + "text": "FIXED (v0.110.0/v0.111.0): acf.h's rcp_acf_compound_wait_match() now provides a universal TC18 §13.5.1 comparison surface for every endpoint type, UART included, wired into real dispatch via server.c's rcp_server_tick_ctx_t.current_status. §13.7.8.1's own \"compared length bounded above by uart_rx_fifo_size\" follows directly from §13.5.1's shared length rule once the fifo's real contents (which can never exceed uart_rx_fifo_size) are supplied as current_status: an expected byte_msg_payload longer than the fifo could ever hold never matches (status shorter than payload never matches). No UART-specific comparison logic is needed; this is no longer a gap.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1, TC18.txt L5305-5307; §13.5.1, TC18.txt L4134-4162", + "tc18_master_id": "TC18-13.7.8.1-006" + }, + { + "id": "REQ-UART-036", + "title": "uart_ep_len, the reserved octet, and uart_ep_status register rows of Table 51", + "text": "IMPLEMENTED, TEXT CORRECTED 2026-08-12 (issue #201 batch, doc-only): this entry's own claim was stale, not the code -- REQ-UART-038's own earlier fix (issue #256 Group I, 2026-08-11) already added exactly this register block. rcp_ep_uart_render_registers()/_apply_reconfig() (src/ep_uart.c) serialize uart_ep_len (RCP_EP_UART_REG_EP_LEN, 0x0000, 8 bit, R -- renders RCP_EP_UART_EP_FUNC_LEN), the reserved octet (RCP_EP_UART_REG_RESERVED_01, 0x0001, 8 bit, R -- renders 0x00), and uart_ep_status (RCP_EP_UART_REG_EP_STATUS, 0x0004, 16 bit, R/W -- rcp_ep_uart_functional_cfg_t::ep_status), all directly TC18.txt-verified and covered by tests/test_ep_uart.c's own existing register-block tests. This entry's own text and status simply never caught up when REQ-UART-038 landed -- the same stale-catalog-entry pattern already found and fixed 3+ times earlier this session (REQ-RMAP-033/034/037 and others).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51, TC18.txt L5330-5332 and L5340", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-037", + "title": "rcp_ep_uart_wire_timeout_us() converts a bit-time count to a ceiling-rounded microsecond duration, failing open with no configured baud rate", + "text": "Split 2026-08-18 (c-RCP-18-tracker REQ-UART batch, issue #533) from this id's own prior bundled text, which also covered the baud_rate_kbps/wire_timeout_bit_times struct-field-separation topic (now REQ-UART-048) and the uart_stop_bits three-way half-unit mapping (now REQ-UART-049) -- each already independently, distinctly tested (this clause by five dedicated rcp_ep_uart_wire_timeout_us() tests in tests/test_ep_uart.c, REQ-UART-048 by test_uart_register_units_diverge_from_table_48() in tests/test_tc18_gaps_ep2.c, REQ-UART-049 by the stop_bits-specific tests in both files), the exact shape #519's own REQ-DL-001/REQ-CFG-006 findings warned a single bundled id can hide. IMPLEMENTED 2026-08-14 (issue #341 lineage): rcp_ep_uart_wire_timeout_us(baud_rate_kbps, wire_timeout_bit_times) converts Table 51's own uart_timeout register (a raw UART bit-time count measured from the last received stop bit, TC18's own origin) into a wall-clock microsecond duration a caller can actually use -- one bit period is 1000/baud_rate_kbps microseconds, so wire_timeout_bit_times bit periods is wire_timeout_bit_times*1000/baud_rate_kbps microseconds, rounded UP (ceiling) so a caller never underestimates the configured timeout. Fails open (returns 0) when baud_rate_kbps == 0 -- this library never invents a clock rate it has no way to know, the same discipline REQ-ADC-033's own base_clk_hz parameter already establishes. Purely additive: no existing field, setter, or function signature changed. Both the ceiling-rounding and the fail-open guard were mutation-tested and caught cleanly.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51, TC18.txt L5342, L5364, L5366, L5369", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-038", + "title": "uart_rts_enable, uart_cts_enable, uart_half_duplex, and uart_trail (Table 51) are now modeled", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I): TC18 §13.7.8.2 Table 51's four R/W fields rcp_ep_uart_functional_cfg_t previously carried no counterpart for at all -- uart_rts_enable (relative address 0x0009.2, 1 bit), uart_cts_enable (0x0009.3, 1 bit), uart_half_duplex (0x0009.4, 1 bit), and uart_trail (0x000C, 8 bit) -- are now modeled as rts_enable/cts_enable/half_duplex/trail, alongside the whole Table 51 register block (rcp_ep_uart_render_registers()/_apply_reconfig()/_reconfig_strerror()/_encode_reconfig_request(), REQ-UART-039/040) implementing TC18 §12.7.1's generic evt[2:0]=111b configuration-write mechanism for this endpoint type for the first time (the same class of fix SPI's/I2C's own earlier fixes in this issue delivered). Unlike GPIO's/I2C's own source tables, Table 51 has no address-collision editorial defect -- its printed addresses are internally consistent.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51, TC18.txt L5354-5362 (uart_rts_enable/uart_cts_enable/uart_half_duplex), L5369 (uart_trail)", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-039", + "title": "rcp_ep_uart_render_registers()/_encode_reconfig_request() implement the generic §12.7.1 configuration request for UART", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I): TC18 §12.7.1 Figure 18 defines one generic configuration request -- evt[2:0] = 111b, byte_msg_payload = a relative register start address within the addressed endpoint's EP_func section followed by configuration data -- usable against every endpoint type. rcp_ep_uart_decode_write_request()/_decode_read_request() already correctly rejected evt[2:0] = 111b as RCP_EP_UART_ERR_BAD_EVT (via acf.h's rcp_acf_evt_row2_is_plain()), but no counterpart function implemented that path at all. rcp_ep_uart_render_registers() serializes cfg's whole Table 51 block; rcp_ep_uart_encode_reconfig_request() encodes an ACF_ABB write request (op=WRITE, evt=111b) carrying a 16-bit big-endian start address followed by data, matching PWM_OUT's/GPIO's/SPI's/I2C's own encode_reconfig_request() shape.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 Configuration of endpoints + Figure 19 (renumbered from Figure 18 by the RC5 rebaseline), TC18.txt L2844-2860", + "tc18_master_id": "TC18-12.7.1-002" + }, + { + "id": "REQ-UART-040", + "title": "rcp_ep_uart_apply_reconfig()/_reconfig_strerror() apply the addressed configuration write and never return NULL for a status message", + "text": "FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I): rcp_ep_uart_apply_reconfig() decodes the address+data payload TC18 §12.7.1 defines and patches cfg's Table 51 register block at octet granularity, then adopts the whole block atomically -- a write whose start_address+length exceeds RCP_EP_UART_EP_FUNC_LEN is rejected and cfg left entirely unchanged (RCP_EP_UART_RECONFIG_ERR_OUT_OF_RANGE), matching §12.7.1's own 'such a payload is to be ignored' rule; octets landing on a read-only register (EP_LEN or the reserved octet) are silently skipped while the rest of the span is still applied. rcp_ep_uart_reconfig_strerror() never returns NULL, including for an unrecognized error code.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 Configuration of endpoints, TC18.txt L2844-2860", + "tc18_master_id": "TC18-12.7.1-002" + }, + { + "id": "REQ-UART-041", + "title": "rcp_ep_uart_trigger_fires() never fires for RCP_EP_UART_TRIGGER_NONE", + "text": "ADDED 2026-08-14 (c-RCP-AUDIT-14, issue #425): TC18 §13.7.8.4 Table 52 (\"uart trigger signals\") defines a real UART HW trigger event with two output signals that this module previously modeled nowhere at all. rcp_ep_uart_trigger_fires() shall return false for trigger == RCP_EP_UART_TRIGGER_NONE regardless of event -- NONE is this module's own off/none state, the same shape as ep_spi.h's own RCP_EP_SPI_TRIGGER_NONE (see REQ-SPI-006) and ep_lin.h's RCP_EP_LIN_TRIGGER_NONE, neither of which Table 52 (nor Table 41, nor this endpoint type's own original LIN trigger concept) itself defines a wire value for.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.4 Table 52 (\"A UART EP optionally generates HW trigger event\"), TC18.txt L5414-5421", + "tc18_master_id": "TC18-13.7.8.4-001" + }, + { + "id": "REQ-UART-042", + "title": "rcp_ep_uart_trigger_fires() implements RCP_EP_UART_TRIGGER_TX_FINALIZED", + "text": "ADDED 2026-08-14 (c-RCP-AUDIT-14, issue #425): rcp_ep_uart_trigger_fires() shall return true for trigger == RCP_EP_UART_TRIGGER_TX_FINALIZED iff event == RCP_EP_UART_EVENT_TX_REQUEST_FINALIZED (and false for the other defined event, RCP_EP_UART_EVENT_READ_REQUEST_FINALIZED, i.e. no spurious firing for the sibling signal's own event) -- TC18 Table 52's trigger signal 0, \"Transmit request finalized\".", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.4 Table 52 (trigger signal 0, \"Transmit request finalized\"), TC18.txt L5417", + "tc18_master_id": "TC18-13.7.8.4-002" + }, + { + "id": "REQ-UART-043", + "title": "rcp_ep_uart_trigger_fires() implements RCP_EP_UART_TRIGGER_RX_FINALIZED", + "text": "ADDED 2026-08-14 (c-RCP-AUDIT-14, issue #425): rcp_ep_uart_trigger_fires() shall return true for trigger == RCP_EP_UART_TRIGGER_RX_FINALIZED iff event == RCP_EP_UART_EVENT_READ_REQUEST_FINALIZED (and false for the other defined event, RCP_EP_UART_EVENT_TX_REQUEST_FINALIZED, i.e. no spurious firing for the sibling signal's own event) -- TC18 Table 52's trigger signal 1, \"Read request finalized\". Not to be conflated with rcp_ep_uart_read_completion_decision() (REQ-UART-033), which arbitrates §13.7.8.1's unrelated read-completion race (fifo-satisfied / timeout-expired / fifo-full-fragmentation) rather than this Table 52 HW trigger signal.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.4 Table 52 (trigger signal 1, \"Read request finalized\"), TC18.txt L5418", + "tc18_master_id": "TC18-13.7.8.4-002" + }, + { + "id": "REQ-UART-044", + "title": "rcp_ep_uart_set_trigger() rejects an unauthorized write without mutating cfg", + "text": "ADDED 2026-08-14 (c-RCP-AUDIT-14, issue #425): rcp_ep_uart_set_trigger() shall return false and leave cfg->trigger unchanged when the write is not authorized by rcp_ep_uart_functional_cfg_writable() -- the same §12.3.1.3 W* marker convention every other rcp_ep_uart_set_*() mutator already enforces (REQ-UART-008/010/013/015).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- governs the write-authorization behavior; §13.7.8.4 Table 52, TC18.txt L5414-5421, is the trigger-signal basis cfg->trigger models (see REQ-UART-041/042/043).", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-UART-045", + "title": "rcp_ep_uart_set_trigger() applies the write when authorized, and never touches the wire register block", + "text": "ADDED 2026-08-14 (c-RCP-AUDIT-14, issue #425): rcp_ep_uart_set_trigger() shall return true and set cfg->trigger to the requested trigger when the write is authorized. cfg->trigger has no counterpart in Table 51's own EP_func register block (RCP_EP_UART_REG_*) -- the same \"no wire-format consequence\" status ep_spi.h's own channels[i].trigger and ep_pwm.h's PWM_OUT/PWM_IN trigger fields already have (see ep_spi.h's own file header) -- so rcp_ep_uart_render_registers()/rcp_ep_uart_apply_reconfig() are correctly left untouched by this field's addition.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.3.1.3, TC18.txt L2601-2602 (W* marker convention) -- same basis as REQ-UART-044", + "tc18_master_id": "TC18-12.3.1.3-005" + }, + { + "id": "REQ-UART-046", + "title": "rcp_ep_uart_decode_write_response() rejects a too-short frame or a mismatched byte_bus_id", + "text": "Split 2026-08-18 (c-RCP-18-tracker REQ-UART batch, issue #533) from this clause's former home under REQ-UART-022's own bundled text -- the malformed-frame rejection contract is independently testable from REQ-UART-022's own OK-path round-trip contract, and this codebase's own decode_write_request()/decode_read_request()/decode_read_response() siblings (REQ-UART-019/020, REQ-UART-024/025, REQ-UART-027/028) already keep their own OK-path and error-path clauses as separate ids; decode_write_response() had simply not followed that pattern yet. rcp_ep_uart_decode_write_response() shall return RCP_EP_UART_ERR_SHORT_FRAME for a frame too short for its applicable ACF fixed header and RCP_EP_UART_ERR_WRONG_BUS when byte_bus_id != expected_bus_id.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.1 (\"A write request leads to a transmission of data to an external connected device.\"), TC18.txt L5296", + "tc18_master_id": "TC18-13.7.8.1-003" + }, + { + "id": "REQ-UART-047", + "title": "rcp_ep_uart_decode_read_response_fragment() returns the same frame-validation error codes, under the same conditions, as rcp_ep_uart_decode_read_response()", + "text": "Split 2026-08-18 (c-RCP-18-tracker REQ-UART batch, issue #533) from this clause's former home under REQ-UART-031's own bundled text, for the same reason REQ-UART-046 was split from REQ-UART-022: an OK-path contract and an error-path contract are two independently-testable behaviours of one decode function, and this module's own sibling decode functions already keep them as separate ids. rcp_ep_uart_decode_read_response_fragment() shall return the same RCP_EP_UART_ERR_SHORT_FRAME/_ERR_BAD_MSG_TYPE/_ERR_WRONG_BUS error codes, under the same conditions, that rcp_ep_uart_decode_read_response() returns them for.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.5 Table 33 (ADC/PWM_IN/I²C/LIN/CAN/UART/ISELED/MDIO row), TC18.txt L4083-4093", + "tc18_master_id": "TC18-13.5-001" + }, + { + "id": "REQ-UART-048", + "title": "uart_baud_rate is in kbit/s and uart_timeout is in bit times measured from the last received stop bit -- distinct from this module's pre-existing, differently-unitted fields", + "text": "Split 2026-08-18 (c-RCP-18-tracker REQ-UART batch, issue #533) from this batch's former REQ-UART-037 bundled text; originally FIXED 2026-08-11 (c-RCP-AUDIT-06, issue #256 Group I, REQ-UART-038): the register block (rcp_ep_uart_render_registers()/_apply_reconfig()) carries these two registers at TC18's own units, as new, distinct struct fields kept separate from this module's pre-existing, differently-unitted fields of a similar name (the same \"don't silently redefine an existing public field\" caution SPI's own baud_rate_kbps-vs-clock_divider split already established): baud_rate_kbps (uint16_t, kbit/s, the wire's uart_baud_rate) is distinct from the pre-existing baud_rate (uint32_t, unit unspecified, untouched); wire_timeout_bit_times (uint8_t, bit times, the wire's uart_timeout) is distinct from the pre-existing uart_timeout_ms (milliseconds, a different layer entirely -- see ep_uart.h's own file header). STILL PARTIAL, unchanged: rcp_ep_uart_set_baud_rate()/_set_timeout() still let a caller store a baud_rate/uart_timeout_ms value no 16-bit kbit/s register or 8-bit bit-time register could represent -- a genuine, honestly-documented residual limitation of the legacy fields, untouched by baud_rate_kbps/wire_timeout_bit_times existing alongside them.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "partial", + "tc18": "§13.7.8.2 Table 51, TC18.txt L5342, L5364, L5366, L5369", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-UART-049", + "title": "uart_stop_bits counts HALF stop bits, exactly representable via RCP_EP_UART_STOP_BITS_ONE_HALF", + "text": "Split 2026-08-18 (c-RCP-18-tracker REQ-UART batch, issue #533) from this batch's former REQ-UART-037 bundled text; originally CLOSED 2026-08-14 (tc18-gap post-backlog audit): rcp_ep_uart_stop_bits_t (ep_uart.h) has a real third member, RCP_EP_UART_STOP_BITS_ONE_HALF (2, appended -- TWO's own existing numeric value 1 is unchanged for source compatibility), representing Table 51's own uart_stop_bits register value 3 (1.5 stop bits) exactly instead of rounding it up to TWO on parse. stop_bits_to_half_units()/half_units_to_stop_bits() (ep_uart.c) shall map all three legal register values (2/3/4) exactly; an out-of-range value still fails safe toward the same conservative defaults as before (< 2 -> ONE, > 4 -> TWO). No existing call site in this codebase used a switch over this enum (grep-confirmed before adding the new member), so this addition is source-compatible everywhere the enum was already used by direct comparison or assignment. Both the parse-side and render-side three-way mapping were mutation-tested and caught cleanly.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.8.2 Table 51, TC18.txt L5342, L5364, L5366, L5369", + "tc18_master_id": "TC18-13.7.8.2-001" + }, + { + "id": "REQ-WAKEUP-006", + "title": "rcp_ep_wakeup_wup_status_latch_source() sets one source's own bit in the wup_status latch", + "text": "rcp_ep_wakeup_wup_status_latch_source(s, source_index) shall set bit source_index in s->mask when source_index < RCP_EP_WAKEUP_MAX_SOURCES, and shall be a no-op for source_index >= RCP_EP_WAKEUP_MAX_SOURCES.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39 (ep1 - functional configuration), TC18.txt L4496-4515 (wup_status register), TC18.txt L4505-4507 -- text corrected 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch): prior text described the retired index-free rcp_ep_wakeup_wup_status_latch()/single-bit s->latched field; the function is now index-based over a bitmask (REQ-WAKEUP-021, issue #341 lineage). See REQ-WAKEUP-027/-028 for the sibling clear_source()/source_is_latched() clauses this same redesign introduced, and REQ-WAKEUP-021 for the register-block rendering clause.", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-007", + "title": "rcp_ep_wakeup_wup_status_clear() clears the wup_status latch", + "text": "rcp_ep_wakeup_wup_status_clear() shall set s->latched to false.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39 (ep1 - functional configuration), TC18.txt L4496-4515 (wup_status, \"writing '1' clears the flag\"), TC18.txt L4505-4507 -- see the pre-existing gap REQ-WAKEUP-021", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-008", + "title": "rcp_ep_wakeup_wup_status_is_clear() reports the wup_status latch's state", + "text": "rcp_ep_wakeup_wup_status_is_clear() shall return !s->latched.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39 (ep1 - functional configuration), TC18.txt L4496-4515 (wup_status register), TC18.txt L4505-4507 -- see the pre-existing gap REQ-WAKEUP-021", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-009", + "title": "rcp_ep_wakeup_strerror() returns a non-NULL message for every error code", + "text": "rcp_ep_wakeup_strerror() shall return a non-NULL, non-empty message for each rcp_ep_wakeup_errc_t value, and a non-NULL message for any unrecognized value.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented" + }, + { + "id": "REQ-WAKEUP-010", + "title": "rcp_ep_wakeup_encode_sleepcmd_request() encodes a fixed-opcode SleepCMD request", + "text": "rcp_ep_wakeup_encode_sleepcmd_request() shall encode an ACF_ABB message with op RCP_ACF_OP_NONE whose 1-byte payload is RCP_EP_WAKEUP_SLEEPCMD_OPCODE, padded to the next quadlet by rcp_acf_encode_abb() itself; the request carries no target-mode field and unconditionally means Sleep.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.3 Figure 23 (Endpoint sleep request), TC18.txt L4558-4563, directly confirmed against the rendered PDF page image: a 1-byte SleepCMD opcode followed by an undifferentiated padding region with no target-mode field; \"SleepCMD is coded as 0xA5.\", TC18.txt L4565; \"bring the RC Server implementation to sleep mode\" (never Standby), TC18.txt L4555 -- corrected 2026-08-10, c-RCP-AUDIT-06, issue #256 Group E, superseding this entry's prior (incorrect) reading of a 2-byte, target_mode-selecting payload", + "tc18_master_id": "TC18-13.7.2.3-003" + }, + { + "id": "REQ-WAKEUP-011", + "title": "rcp_ep_wakeup_decode_sleepcmd_request() validates and decodes a SleepCMD request", + "text": "rcp_ep_wakeup_decode_sleepcmd_request() shall return RCP_EP_WAKEUP_ERR_SHORT_FRAME for a frame shorter than the ACF_ABB header or its declared 1-byte payload; RCP_EP_WAKEUP_ERR_BAD_MSG_TYPE for a non-ACF_ABB frame; RCP_EP_WAKEUP_ERR_WRONG_BUS for a mismatched byte_bus_id; RCP_EP_WAKEUP_ERR_BAD_OPCODE when the payload byte is not RCP_EP_WAKEUP_SLEEPCMD_OPCODE; and otherwise RCP_EP_WAKEUP_OK with the transaction number populated, ignoring any bytes past the opcode (undifferentiated padding, not a validated field).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.3 Figure 23 (Endpoint sleep request), TC18.txt L4558-4563, directly confirmed against the rendered PDF page image; \"SleepCMD is coded as 0xA5.\", TC18.txt L4565 -- corrected 2026-08-10, c-RCP-AUDIT-06, issue #256 Group E, superseding this entry's prior (incorrect) RCP_EP_WAKEUP_ERR_BAD_TARGET_MODE validation path against a field TC18 never defines", + "tc18_master_id": "TC18-13.7.2.3-003" + }, + { + "id": "REQ-WAKEUP-012", + "title": "rcp_ep_wakeup_encode_sleepcmd_response() encodes a fixed-opcode SleepCMD response", + "text": "rcp_ep_wakeup_encode_sleepcmd_response() shall encode an ACF_ABB message with op RCP_ACF_OP_NONE whose 2-byte payload is RCP_EP_WAKEUP_SLEEPCMD_OPCODE followed by result's raw value, echoing transaction_num.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.3 (\"send an acknowledge to sleep request\" / \"bring the RC Server implementation to sleep mode\"), TC18.txt L4554-4555; §13.7.2.3 Figure 23 (Endpoint sleep request), TC18.txt L4558-4563; \"SleepCMD is coded as 0xA5.\", TC18.txt L4565 -- refusal signalled as a positive-form response rather than an error response, see the pre-existing gap REQ-WAKEUP-019", + "tc18_master_id": "TC18-13.7.2.3-002" + }, + { + "id": "REQ-WAKEUP-013", + "title": "rcp_ep_wakeup_decode_sleepcmd_response() applies the shared frame-validation failure modes", + "text": "rcp_ep_wakeup_decode_sleepcmd_response() shall, for a non-error-response frame, apply the same short-frame/wrong-message-type/wrong-bus/bad-opcode failure modes as rcp_ep_wakeup_decode_sleepcmd_request().", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.3 (\"send an acknowledge to sleep request\" / \"bring the RC Server implementation to sleep mode\"), TC18.txt L4554-4555 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit): this id's prior text also bundled the OK-path result-byte-to-enum mapping (now REQ-WAKEUP-023) and overlapped REQ-WAKEUP-019's own error-response-recognition clause (now REQ-WAKEUP-025); this id now covers only the shared non-error-response validation-failure-mode clause.", + "tc18_master_id": "TC18-13.7.2.3-002" + }, + { + "id": "REQ-WAKEUP-014", + "title": "rcp_ep_wakeup_encode_wakeup_message() encodes a fixed-opcode WakeUp message", + "text": "rcp_ep_wakeup_encode_wakeup_message() shall encode an ACF_ABB message with op RCP_ACF_OP_NONE whose 1-byte payload is RCP_EP_WAKEUP_WAKEUP_OPCODE.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.1 (\"After establishing a network connection, the WakeUp endpoint sends repetitive messages.\"), TC18.txt L4488-4489 -- carries no wake-up source of its own, see the pre-existing gap REQ-WAKEUP-017", + "tc18_master_id": "TC18-13.7.2.1-002" + }, + { + "id": "REQ-WAKEUP-015", + "title": "rcp_ep_wakeup_decode_wakeup_message() validates and decodes a WakeUp message", + "text": "rcp_ep_wakeup_decode_wakeup_message() shall return RCP_EP_WAKEUP_ERR_SHORT_FRAME for a frame shorter than the ACF_ABB header or its declared 1-byte payload; RCP_EP_WAKEUP_ERR_BAD_MSG_TYPE for a non-ACF_ABB frame; RCP_EP_WAKEUP_ERR_WRONG_BUS for a mismatched byte_bus_id; RCP_EP_WAKEUP_ERR_BAD_OPCODE when the payload byte is not RCP_EP_WAKEUP_WAKEUP_OPCODE; and otherwise RCP_EP_WAKEUP_OK with the transaction number populated.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.1, TC18.txt L4488-4489 -- see the pre-existing gap REQ-WAKEUP-017", + "tc18_master_id": "TC18-13.7.2.1-002" + }, + { + "id": "REQ-WAKEUP-016", + "title": "rcp_ep_wakeup_is_wakeup_echo() recognizes a matching WakeUp echo", + "text": "rcp_ep_wakeup_is_wakeup_echo() shall return true iff rcp_ep_wakeup_decode_wakeup_message() succeeds on b[0..len) against expected_bus_id and the decoded transaction number equals sent_transaction_num, and false otherwise.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented" + }, + { + "id": "REQ-WAKEUP-017", + "title": "rcp_ep_wakeup_encode_wakeup_message_with_source() encodes a WakeUp message carrying its wake source", + "text": "rcp_ep_wakeup_encode_wakeup_message_with_source() shall encode an ACF_ABB message with op RCP_ACF_OP_NONE whose 3-byte payload is RCP_EP_WAKEUP_WAKEUP_OPCODE followed by source's raw value and source_index.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.4.1, TC18.txt L2674-L2676 -- FIXED 2026-08-12 (issue #201 batch 8): this additive, 3-byte-payload extension (opcode + a rcp_ep_wakeup_source_t classification byte + a source_index byte) sits alongside the pre-existing, unchanged 1-byte plain pair -- zero blast radius on any existing caller, since the plain rcp_ep_wakeup_decode_wakeup_message()/rcp_ep_wakeup_is_wakeup_echo() still tolerate (though do not require) the longer payload. Covers all 3 wake-source classes TC18 §12.4.1's own text names: a configured wake-source pin (RCP_EP_WAKEUP_SOURCE_IO, with a source_index into rcp_ep_wakeup_functional_cfg_t::sources[]), 'the dedicated wakepin' (RCP_EP_WAKEUP_SOURCE_WAKEPIN, named separately in that text from the configured pin table), and a TC14/TC10 network wake-up request (RCP_EP_WAKEUP_SOURCE_NETWORK), plus RCP_EP_WAKEUP_SOURCE_UNKNOWN for a caller with no source information to report -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit): this id's prior text also bundled the decoder's own separate validate-and-decode contract, now REQ-WAKEUP-024; this id now covers only the encode-direction clause.", + "tc18_master_id": "TC18-12.4.1-003" + }, + { + "id": "REQ-WAKEUP-018", + "title": "The WakeUp endpoint's functional config carries the WakeUp repetition time", + "text": "IMPLEMENTED 2026-08-14 (issue #341 lineage): the real, wire-derived repetition interval is now available. This requirement's own prior text correctly named TC18 §13.7.2.1's own '(flush_time)' parenthetical as the actual mechanism, and correctly identified that reusing rcp_regmap_response_queue_cfg_t::flush_time_us (a DIFFERENT table's field, TC18 §12.7.9 Table 27, REQ-RMAP-064) required a cross-endpoint architectural decision this codebase would not make unilaterally -- that decision is now made, following this session's own established composition pattern (mirroring rcp_mock_server_check_response_queue_heartbeat(), REQ-RMAP-065/SRV-017): new rcp_mock_server_wakeup_repetition_interval_us() (mock.h/mock.c) resolves a WakeUp endpoint's own 1-based request_stream_index through srv->request_stream_cfg[]'s own rx_resp_stream_index (REQ-RMAP-049's already-authoritative request-stream -> response-stream association) to the associated response_queue_cfg[] row's own flush_time_us, composed entirely from existing primitives -- no new wire field, no new table. Kept in mock.c rather than ep_wakeup.h itself, preserving that module's own 'nothing... is touched here' layering promise (its own file header) -- the same boundary every other cross-endpoint composition this codebase already respects. ep_wakeup.h's own in-memory repetition_time_us field is unchanged -- it remains a caller-settable fallback for when no request/response stream is configured yet, not the authoritative source once one is. Mutation-tested: the response-row resolution and the request_stream_index range guard were each independently weakened and confirmed to fail the new tests, then restored.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.4.1, TC18.txt L2676-L2677", + "tc18_master_id": "TC18-12.4.1-003" + }, + { + "id": "REQ-WAKEUP-019", + "title": "rcp_ep_wakeup_encode_sleepcmd_response() signals a refused entry as a genuine ACF error response", + "text": "rcp_ep_wakeup_encode_sleepcmd_response(..., RCP_PWRMODE_ENTRY_REFUSED, ...) shall return an ACF Error Response (via rcp_acf_build_error_response()) carrying RCP_ERROR_REQUEST_CANCELED, instead of its own ordinary positive-form SleepCMD-opcode-plus-result-byte payload.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.5, TC18.txt L2703-L2708 -- FIXED 2026-08-12 (issue #201 batch 6): TC18 §12.5 requires a refused sleep/standby request to be signalled as an error message with error code REQUEST_CANCELED (RCP_ERROR_REQUEST_CANCELED, include/rcp/errors.h:55), not the old positive-form SleepCMD response carrying the module-local RCP_PWRMODE_ENTRY_REFUSED value -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit): this id's prior text also bundled the decode-side recognition of that error response, now REQ-WAKEUP-025; this id now covers only the encode-direction clause.", + "tc18_master_id": "TC18-12.5-005" + }, + { + "id": "REQ-WAKEUP-020", + "title": "rcp_regmap_ep_id_map_ep_type_has_fixed_ep_id() diagnoses a fixed-ep_id violation in an existing table", + "text": "rcp_regmap_ep_id_map_ep_type_has_fixed_ep_id() shall return false iff some row i has ep_types[i] == target_ep_type and entries[i].ep_id != required_ep_id, and true otherwise (including the vacuous case of no matching row).", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.1, TC18.txt L4482-4483 -- TC18 fixes the WakeUp endpoint's own EP_Nr (regmap.h's EP_ID_config row field, rcp_regmap_ep_id_map_entry_t::ep_id, TC18 §12.7.8 Table 25) to 1, distinct from RCP_EP_WAKEUP_EP_TYPE (this codebase's own internal ep_type tag on a different table -- their numeric value both being 1 is coincidental, not a TC18 identity); RCP_EP_WAKEUP_ENDPOINT_NUM (ep_wakeup.h) names the required value. This diagnostic is the same shape and same disposition as REQ-RMAP-057/058's own sibling diagnostics for this table's other two TC18 §12.7.8 recommendations: read-only, not enforcement -- see REQ-WAKEUP-026 for the write-time enforcement this diagnostic's own finding motivated (issue #336). Split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit): this id's prior text also bundled that enforcement mechanism's own contract under one id; this id now covers only the read-only diagnostic function's own contract.", + "tc18_master_id": "TC18-13.7.2.1-001" + }, + { + "id": "REQ-WAKEUP-021", + "title": "rcp_ep_wakeup_render_registers() renders wup_status as a per-source bitmask", + "text": "rcp_ep_wakeup_render_registers() shall render cfg->wup_status.mask into the WUP_STATUS register's 16-bit field with bits [15:RCP_EP_WAKEUP_MAX_SOURCES] masked to 0, each bit representing one source's own latched state.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39, TC18.txt L4494-4514; address-collision resolution confirmed against both the 0.5.1_RC baseline PDF and the 0.5.1_RC5 revision PDF (identical, unfixed by the spec committee, unlike MDIO's own Table 56/59 collision) -- IMPLEMENTED 2026-08-14 (issue #341 lineage): rcp_ep_wakeup_wup_status_t redesigned from a single aggregate latch bit to a genuine per-source 16-bit bitmask -- BREAKING CHANGE, matching TC18 §13.7.2.2 Table 36/39's own 'Indication of wake-up source, writing \"1\" clears the flag. Each bit represents a wake-up source' exactly. Split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit): this id's prior text bundled 7 different functions' own behavior (rcp_ep_wakeup_wup_status_latch_source() now REQ-WAKEUP-006 updated text; _clear_source() now REQ-WAKEUP-027; _source_is_latched() now REQ-WAKEUP-028; rcp_ep_wakeup_apply_reconfig()'s own write-1-to-clear parsing now REQ-WAKEUP-029; its own general short/out-of-range validation now REQ-WAKEUP-036; rcp_ep_wakeup_reconfig_strerror() now REQ-WAKEUP-030; rcp_ep_wakeup_encode_reconfig_request() now REQ-WAKEUP-031, which is not really about wup_status at all) under one id; this id now covers only rcp_ep_wakeup_render_registers()'s own wup_status-rendering clause.", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-022", + "title": "rcp_ep_wakeup_render_registers() renders a source's own IO_SRC field with edge modes taking precedence over level modes", + "text": "rcp_ep_wakeup_render_registers() shall render each source's own IO_SRC field as RCP_EP_WAKEUP_IO_SRC_BOTH_EDGES/_RISING_EDGE/_FALLING_EDGE whenever either trigger_on_rising_edge or trigger_on_falling_edge is set, taking precedence over the LEVEL-mode enabled/active_high pair, which is rendered as INACTIVE/HIGH_LEVEL/LOW_LEVEL only when neither trigger bit is set.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 40, TC18.txt L4528-4541 -- CORRECTED 2026-08-14, citation-drift fix (issue #341 lineage): the previous citation (\"Table 37, TC18.txt L4128-4139\") pointed at an unrelated section (§13.5.1's own compound-wait evt-field text) -- a genuine citation-drift artifact, not re-verified since this requirement's own 2026-08-11 text was last touched. Re-verified directly against the current RC5 TC18.txt before trusting it. IMPLEMENTED 2026-08-14 (issue #341 lineage): all 6 of TC18 Table 40's own IO_SRC[15:11] values are now representable. rcp_ep_wakeup_source_cfg_t gains two new, purely-additive fields, trigger_on_rising_edge/trigger_on_falling_edge (both false by default -- every pre-existing LEVEL-mode caller's own behavior is completely unchanged). Split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit): this id's prior text bundled 4 different functions' own behavior (rcp_ep_wakeup_source_edge_state_init() now REQ-WAKEUP-032; rcp_ep_wakeup_source_edge_asserted() now REQ-WAKEUP-033; rcp_ep_wakeup_any_source_edge_asserted() now REQ-WAKEUP-034; rcp_ep_wakeup_apply_reconfig()'s own IO_SRC-parsing clause now REQ-WAKEUP-035) under one id; this id now covers only rcp_ep_wakeup_render_registers()'s own IO_SRC rendering-precedence clause.", + "tc18_master_id": "TC18-13.7.2.2-003" + }, + { + "id": "REQ-WAKEUP-023", + "title": "rcp_ep_wakeup_decode_sleepcmd_response() maps a successfully decoded payload byte to a pwrmode entry result", + "text": "rcp_ep_wakeup_decode_sleepcmd_response() shall, on RCP_EP_WAKEUP_OK for a non-error-response frame, set *out_result to RCP_PWRMODE_ENTRY_OK only when the second payload byte equals RCP_PWRMODE_ENTRY_OK's own raw value, and to RCP_PWRMODE_ENTRY_REFUSED for every other byte value.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.3, TC18.txt L4554-4565 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-013's own prior bundled text; a fail-safe result-byte mapping, independently testable from the shared frame-validation clause REQ-WAKEUP-013 still owns.", + "tc18_master_id": "TC18-13.7.2.3-002" + }, + { + "id": "REQ-WAKEUP-024", + "title": "rcp_ep_wakeup_decode_wakeup_message_with_source() validates and decodes a WakeUp-with-source message", + "text": "rcp_ep_wakeup_decode_wakeup_message_with_source() shall return RCP_EP_WAKEUP_ERR_SHORT_FRAME for a frame shorter than the ACF_ABB header or its declared 3-byte payload; RCP_EP_WAKEUP_ERR_BAD_MSG_TYPE for a non-ACF_ABB frame; RCP_EP_WAKEUP_ERR_WRONG_BUS for a mismatched byte_bus_id; RCP_EP_WAKEUP_ERR_BAD_OPCODE when the payload byte is not RCP_EP_WAKEUP_WAKEUP_OPCODE or the source byte is not one of RCP_EP_WAKEUP_SOURCE_{UNKNOWN,IO,WAKEPIN,NETWORK}; and otherwise RCP_EP_WAKEUP_OK with the transaction number, source, and source_index populated.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.4.1, TC18.txt L2674-L2676 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-017's own prior bundled text, mirroring every other encode/decode pair in this module (REQ-WAKEUP-010/-011, -012/-013, -014/-015) already having separate ids.", + "tc18_master_id": "TC18-12.4.1-003" + }, + { + "id": "REQ-WAKEUP-025", + "title": "rcp_ep_wakeup_decode_sleepcmd_response() recognizes a REQUEST_CANCELED error response as a refused entry", + "text": "rcp_ep_wakeup_decode_sleepcmd_response() shall, for a frame whose header carries an ACF error response, return RCP_EP_WAKEUP_OK with *out_result set to RCP_PWRMODE_ENTRY_REFUSED when the error payload's code equals RCP_ERROR_REQUEST_CANCELED, and RCP_EP_WAKEUP_ERR_BAD_OPCODE for any other error code or a missing error payload.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.5, TC18.txt L2703-L2708 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-019's own prior bundled text; the decode-direction counterpart to REQ-WAKEUP-019's own encode-direction clause, and a distinct behavior from REQ-WAKEUP-013's own non-error-response validation clause on the same function.", + "tc18_master_id": "TC18-12.5-005" + }, + { + "id": "REQ-WAKEUP-027", + "title": "rcp_ep_wakeup_wup_status_clear_source() clears one source's own bit in the wup_status latch", + "text": "rcp_ep_wakeup_wup_status_clear_source(s, source_index) shall clear bit source_index in s->mask when source_index < RCP_EP_WAKEUP_MAX_SOURCES, leaving every other bit unchanged, and shall be a no-op for source_index >= RCP_EP_WAKEUP_MAX_SOURCES.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39, TC18.txt L4496-4515 (wup_status, \"writing '1' clears the flag. Each bit represents a wake-up source\") -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-021's own prior bundled text (issue #341 lineage).", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-028", + "title": "rcp_ep_wakeup_wup_status_source_is_latched() reports one source's own bit in the wup_status latch", + "text": "rcp_ep_wakeup_wup_status_source_is_latched(s, source_index) shall return whether bit source_index is set in s->mask, and shall return false for source_index >= RCP_EP_WAKEUP_MAX_SOURCES.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39, TC18.txt L4496-4515 (wup_status register) -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-021's own prior bundled text (issue #341 lineage).", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-029", + "title": "rcp_ep_wakeup_apply_reconfig() applies wup_status's own write-1-to-clear semantics bit-by-bit", + "text": "rcp_ep_wakeup_apply_reconfig() shall, for the WUP_STATUS register's own written 16-bit value, clear source i's own latched bit in cfg->wup_status.mask for each i whose corresponding written bit is 1, and shall leave every other source's own latched bit unchanged, independently of every other bit.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 39, TC18.txt L4505-4507 (\"writing '1' clears the flag. Each bit represents a wake-up source\") -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-021's own prior bundled text (issue #341 lineage); the decode-direction counterpart to REQ-WAKEUP-021's own render-direction clause.", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-030", + "title": "rcp_ep_wakeup_reconfig_strerror() returns a non-NULL message for every reconfig error code", + "text": "rcp_ep_wakeup_reconfig_strerror() shall return a non-NULL, non-empty message for each rcp_ep_wakeup_reconfig_errc_t value, and a non-NULL message for any unrecognized value.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-021's own prior bundled text; mirrors REQ-WAKEUP-009's own strerror() contract for the sibling errc_t type.", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-031", + "title": "rcp_ep_wakeup_encode_reconfig_request() encodes an EP_func configuration write", + "text": "rcp_ep_wakeup_encode_reconfig_request() shall encode an ACF_ABB message with op RCP_ACF_OP_WRITE and evt[2:0] == 111b whose payload is a 2-byte start_address followed by data[0..data_len), and shall return an empty rcp_bytes_t when data is NULL, data_len is 0, or the resulting payload would exceed RCP_ACF_MAX_PAYLOAD.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-021's own prior bundled text; a generic EP_func write-request encoder, not specific to wup_status at all -- its inclusion under REQ-WAKEUP-021 was itself a mistagging this split corrects.", + "tc18_master_id": "TC18-13.7.2.2-002" + }, + { + "id": "REQ-WAKEUP-032", + "title": "rcp_ep_wakeup_source_edge_state_init() clears an edge-detection state", + "text": "rcp_ep_wakeup_source_edge_state_init() shall set s->has_previous to false and s->previous_level to false.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 40, TC18.txt L4528-4541 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-022's own prior bundled text (issue #341 lineage); mirrors REQ-WAKEUP-005's own wup_status_init() contract for the sibling stateful type.", + "tc18_master_id": "TC18-13.7.2.2-003" + }, + { + "id": "REQ-WAKEUP-033", + "title": "rcp_ep_wakeup_source_edge_asserted() detects a configured rising/falling/both edge on one source", + "text": "rcp_ep_wakeup_source_edge_asserted() shall, in LEVEL mode (neither trigger_on_rising_edge nor trigger_on_falling_edge set), delegate to rcp_ep_wakeup_source_asserted() without touching state; and in EDGE mode, shall return false and only seed state->previous_level on the first observation (state->has_previous was false), and on every subsequent call shall update state->previous_level to pin_level and return true iff cfg.enabled and pin_level transitioned in a direction cfg's own trigger_on_rising_edge/trigger_on_falling_edge configures.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 40, TC18.txt L4528-4541 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-022's own prior bundled text (issue #341 lineage); mirrors REQ-WAKEUP-003's own level-mode rcp_ep_wakeup_source_asserted() contract for the sibling edge-mode predicate.", + "tc18_master_id": "TC18-13.7.2.2-003" + }, + { + "id": "REQ-WAKEUP-034", + "title": "rcp_ep_wakeup_any_source_edge_asserted() reports whether any configured source has a qualifying edge, updating every source's own state", + "text": "rcp_ep_wakeup_any_source_edge_asserted() shall return false when fcfg is NULL, states is NULL, or pin_levels is NULL with pin_level_count > 0; and otherwise shall call rcp_ep_wakeup_source_edge_asserted() for every one of the first min(pin_level_count, RCP_EP_WAKEUP_MAX_SOURCES) source/state/pin_level triples without short-circuiting on an early hit, returning true iff at least one call returned true.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 40, TC18.txt L4528-4541 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-022's own prior bundled text (issue #341 lineage); mirrors REQ-WAKEUP-004's own rcp_ep_wakeup_any_source_asserted() contract for the sibling edge-mode aggregate predicate, including its own deliberate no-short-circuit contract.", + "tc18_master_id": "TC18-13.7.2.2-003" + }, + { + "id": "REQ-WAKEUP-035", + "title": "rcp_ep_wakeup_apply_reconfig() parses a source's own IO_SRC field, including the 3 edge-trigger encodings", + "text": "rcp_ep_wakeup_apply_reconfig() shall, from a source's own parsed IO_SRC field, set enabled/active_high/trigger_on_rising_edge/trigger_on_falling_edge for each of the 6 defined RCP_EP_WAKEUP_IO_SRC_* values (INACTIVE/RISING_EDGE/FALLING_EDGE/BOTH_EDGES/HIGH_LEVEL/LOW_LEVEL), and shall leave those 4 fields entirely unchanged for a reserved (0x06-0x1F) value while still updating pin_number.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§13.7.2.2 Table 40, TC18.txt L4528-4541 -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-022's own prior bundled text (issue #341 lineage); the decode-direction counterpart to REQ-WAKEUP-022's own render-direction clause.", + "tc18_master_id": "TC18-13.7.2.2-003" + }, + { + "id": "REQ-WAKEUP-036", + "title": "rcp_ep_wakeup_apply_reconfig() validates and applies a functional-config write", + "text": "rcp_ep_wakeup_apply_reconfig() shall return RCP_EP_WAKEUP_RECONFIG_ERR_SHORT when payload_len does not exceed RCP_EP_WAKEUP_RECONFIG_ADDR_LEN, RCP_EP_WAKEUP_RECONFIG_ERR_OUT_OF_RANGE when start_address plus the write's own data length would exceed RCP_EP_WAKEUP_EP_FUNC_LEN, and otherwise RCP_EP_WAKEUP_RECONFIG_OK after applying every addressed octet except EP_LEN/NR_IO_PINS_MAX (read-only, silently skipped) to the current register image and re-parsing it.", + "standard": "iso26262", + "level": "ASIL-B", + "asil": "ASIL-B", + "scope": "tc18", + "status": "implemented", + "tc18": "§12.7.1 (\"Any payload whose length plus the start address exceeds EP_LEN is to be ignored\") -- split 2026-08-18 (issue #533 tracker, [c-RCP-18-tracker] REQ-WAKEUP batch, atomicity audit) from REQ-WAKEUP-021's own prior bundled text; this id's own general write-validation/orchestration contract had no dedicated id at all before this split, its coverage having been carried only incidentally by REQ-WAKEUP-021/-022's own (now-narrowed) tags on the same function.", + "tc18_master_id": "TC18-13.7.2.2-002" } ] } diff --git a/include/rcp/uart.hpp b/include/rcp/uart.hpp index bc7f207..51052fe 100644 --- a/include/rcp/uart.hpp +++ b/include/rcp/uart.hpp @@ -7,6 +7,46 @@ // fusa:req REQ-UART-007 // fusa:req REQ-UART-008 // fusa:req REQ-UART-009 +// fusa:req REQ-UART-010 +// fusa:req REQ-UART-011 +// fusa:req REQ-UART-012 +// fusa:req REQ-UART-013 +// fusa:req REQ-UART-014 +// fusa:req REQ-UART-015 +// fusa:req REQ-UART-016 +// fusa:req REQ-UART-017 +// fusa:req REQ-UART-018 +// fusa:req REQ-UART-019 +// fusa:req REQ-UART-020 +// fusa:req REQ-UART-021 +// fusa:req REQ-UART-022 +// fusa:req REQ-UART-023 +// fusa:req REQ-UART-024 +// fusa:req REQ-UART-025 +// fusa:req REQ-UART-026 +// fusa:req REQ-UART-027 +// fusa:req REQ-UART-028 +// fusa:req REQ-UART-029 +// fusa:req REQ-UART-030 +// fusa:req REQ-UART-031 +// fusa:req REQ-UART-032 +// fusa:req REQ-UART-033 +// fusa:req REQ-UART-034 +// fusa:req REQ-UART-035 +// fusa:req REQ-UART-036 +// fusa:req REQ-UART-037 +// fusa:req REQ-UART-038 +// fusa:req REQ-UART-039 +// fusa:req REQ-UART-040 +// fusa:req REQ-UART-041 +// fusa:req REQ-UART-042 +// fusa:req REQ-UART-043 +// fusa:req REQ-UART-044 +// fusa:req REQ-UART-045 +// fusa:req REQ-UART-046 +// fusa:req REQ-UART-047 +// fusa:req REQ-UART-048 +// fusa:req REQ-UART-049 // UART endpoint (ep_type 0x05) — independent TX/RX request families sharing // one functional-config block (baud rate, word format, flow control), its @@ -870,6 +910,24 @@ inline std::error_code decode_read_response(const uint8_t* b, size_t len, avtp:: return {}; } +// ── Compound-wait against a UART endpoint (REQ-UART-035) ──────────────────── +// c-RCP's own REQ-UART-035 disposition (v0.110.0/v0.111.0): acf.h's +// rcp_acf_compound_wait_match() is a universal TC18 §13.5.1 comparison +// surface for every endpoint type, UART included — no UART-specific +// comparison logic is needed. §13.7.8.1's own "compared length bounded above +// by uart_rx_fifo_size" rule follows directly from §13.5.1's shared length +// rule (status capped to the request's own byte_msg_payload length) once the +// RX FIFO's real contents — which can never exceed uart_rx_fifo_size octets — +// are supplied as the comparison's own "status" buffer: an expected +// byte_msg_payload longer than the FIFO could ever hold never matches, since +// a status shorter than payload never matches. This header carries no +// compound-wait logic of its own, exactly like rcp/spi.hpp's own identical +// disclaimer for the same generic mechanism — a caller evaluating a +// compound-wait request against this endpoint goes through +// rcp/acf.hpp's own endpoint-type-independent compound_wait_evt_valid()/ +// compound_wait_match() directly, using this endpoint's own RX FIFO contents +// as the comparison buffer. + // ── Read-completion arbitration (REQ-UART-033) ────────────────────────────── // TC18 §13.7.8.1's own three read-completion triggers, verbatim: a read // request completes as soon as the fifo-rx-buffer holds read_size bytes, OR diff --git a/tests/test_uart.cpp b/tests/test_uart.cpp index a2ebefc..89bdef4 100644 --- a/tests/test_uart.cpp +++ b/tests/test_uart.cpp @@ -7,6 +7,46 @@ // fusa:test REQ-UART-007 // fusa:test REQ-UART-008 // fusa:test REQ-UART-009 +// fusa:test REQ-UART-010 +// fusa:test REQ-UART-011 +// fusa:test REQ-UART-012 +// fusa:test REQ-UART-013 +// fusa:test REQ-UART-014 +// fusa:test REQ-UART-015 +// fusa:test REQ-UART-016 +// fusa:test REQ-UART-017 +// fusa:test REQ-UART-018 +// fusa:test REQ-UART-019 +// fusa:test REQ-UART-020 +// fusa:test REQ-UART-021 +// fusa:test REQ-UART-022 +// fusa:test REQ-UART-023 +// fusa:test REQ-UART-024 +// fusa:test REQ-UART-025 +// fusa:test REQ-UART-026 +// fusa:test REQ-UART-027 +// fusa:test REQ-UART-028 +// fusa:test REQ-UART-029 +// fusa:test REQ-UART-030 +// fusa:test REQ-UART-031 +// fusa:test REQ-UART-032 +// fusa:test REQ-UART-033 +// fusa:test REQ-UART-034 +// fusa:test REQ-UART-035 +// fusa:test REQ-UART-036 +// fusa:test REQ-UART-037 +// fusa:test REQ-UART-038 +// fusa:test REQ-UART-039 +// fusa:test REQ-UART-040 +// fusa:test REQ-UART-041 +// fusa:test REQ-UART-042 +// fusa:test REQ-UART-043 +// fusa:test REQ-UART-044 +// fusa:test REQ-UART-045 +// fusa:test REQ-UART-046 +// fusa:test REQ-UART-047 +// fusa:test REQ-UART-048 +// fusa:test REQ-UART-049 // Tests for rcp/uart.hpp — the UART endpoint type (ROADMAP.md milestone 48, // "Basic Endpoint Types II — I2C, UART, ADC, PWM_OUT, PWM_IN", v2.4.0). @@ -538,7 +578,14 @@ TEST_CASE("set_trigger applies when authorized", "[uart][REQ-UART-045]") { // ── The EP_func register block (§13.7.8.2 Table 51) ────────────────────────── -TEST_CASE("render_registers matches Table 51's own offsets", "[uart][REQ-UART-036][REQ-UART-038]") { +// Also covers REQ-UART-048's own "implemented" half: baud_rate_kbps/ +// wire_timeout_bit_times round-trip through Table 51's own kbit/s and +// bit-time units, kept as separate fields from the pre-existing baud_rate/ +// uart_timeout_ms (see functional_cfg_init's own coverage above, and the +// struct's own file comment for the "STILL PARTIAL" residual limitation +// this dual-tag does not itself re-demonstrate). +TEST_CASE("render_registers matches Table 51's own offsets", + "[uart][REQ-UART-036][REQ-UART-038][REQ-UART-048]") { UartFunctionalCfg cfg; functional_cfg_init(cfg); cfg.ep_enable = true; @@ -572,6 +619,30 @@ TEST_CASE("render_registers matches Table 51's own offsets", "[uart][REQ-UART-03 REQUIRE(kEpFuncLen == 0x000Du); } +// REQ-UART-032: uart_ep_status (kRegEpStatus, Table 51 0x0004, 16 bit R/W) +// exists and round-trips through both halves of the register block, matching +// every other endpoint type's own status-register precedent (e.g. SPI's +// spi_ep_status, WAKEUP's wup_ep_status). render_registers()'s own coverage +// of this register is already exercised (dual-tagged) by "render_registers +// matches Table 51's own offsets" above; this TEST_CASE closes the other +// half — apply_reconfig()'s own parse path — which no existing TEST_CASE +// exercised for this specific register before. +TEST_CASE("apply_reconfig writes ep_status, matching every other endpoint type's own " + "status-register precedent", + "[uart][REQ-UART-032]") { + UartFunctionalCfg cfg; + functional_cfg_init(cfg); + + const uint8_t payload[4] = {0x00, static_cast(kRegEpStatus), 0xBE, 0xEF}; + REQUIRE_FALSE(apply_reconfig(cfg, payload, sizeof(payload))); + REQUIRE(cfg.ep_status == 0xBEEF); + + EpFuncBlock out{}; + render_registers(cfg, out); + REQUIRE(out[kRegEpStatus] == 0xBE); + REQUIRE(out[kRegEpStatus + 1] == 0xEF); +} + TEST_CASE("apply_reconfig writes a multi-register span", "[uart][REQ-UART-039][REQ-UART-040]") { UartFunctionalCfg cfg; functional_cfg_init(cfg); @@ -945,6 +1016,38 @@ TEST_CASE("decode_read_response rejects wrong_bus and short_frame", "[uart][REQ- make_error_code(UartErrc::short_frame)); } +// ── Compound-wait against a UART endpoint (REQ-UART-035) ──────────────────── +// c-RCP's own disposition: no UART-specific compound-wait logic exists — a +// caller goes through acf::compound_wait_match() directly, supplying the RX +// FIFO's own real contents as the comparison's "status" buffer. Exercises +// that mechanism against a UART-flavored scenario mirroring +// tests/test_spi.cpp's own identical demonstration for SPI: the RX FIFO can +// never hold more than uart_rx_fifo_size octets, so an expected +// byte_msg_payload longer than the FIFO's own current contents never +// matches, and a payload no longer than the FIFO's contents is compared only +// against that same-length prefix (TC18 §13.5.1's shared length rule). +TEST_CASE("compound-wait against a UART RX FIFO goes through acf::compound_wait_match, bounded " + "by the FIFO's own real contents", + "[uart][REQ-UART-035]") { + std::vector payload{0x01, 0x02, 0x03, 0x04}; // the request's own 4-byte byte_msg_payload + std::vector rx_fifo_contents{0x01, 0x02, 0x03, 0x04, 0xAA, 0xBB}; // 6 bytes currently buffered + + REQUIRE(rcp::acf::compound_wait_evt_valid(0x0)); // exact-match mode + REQUIRE(rcp::acf::compound_wait_match(0x0, payload.data(), payload.size(), rx_fifo_contents.data(), + rx_fifo_contents.size())); + + // A byte_msg_payload longer than the FIFO's own current contents can + // never match — the FIFO's own contents length caps the comparison, per + // uart_rx_fifo_size's own bound. + std::vector longer_payload{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + REQUIRE_FALSE(rcp::acf::compound_wait_match(0x0, longer_payload.data(), longer_payload.size(), + rx_fifo_contents.data(), rx_fifo_contents.size())); + + rx_fifo_contents[2] = 0x99; // now differs within the payload's own 4-byte window + REQUIRE_FALSE(rcp::acf::compound_wait_match(0x0, payload.data(), payload.size(), rx_fifo_contents.data(), + rx_fifo_contents.size())); +} + // ── Read-completion arbitration (REQ-UART-033) ────────────────────────────── // Not covered by c-RCP's own tests/test_ep_uart.c (that coverage lives in // c-RCP's tests/test_tc18_gaps_ep2.c's test_uart_read_completion_decision());