1549 lines
52 KiB
JSON
1549 lines
52 KiB
JSON
{
|
||
"$schema": "../../../tools/card-layouts/schemas/card-source.schema.json",
|
||
"schema": "esc-card-source.v1",
|
||
"card": {
|
||
"id": "mpabi-freertos-c-13-uart-pipeline",
|
||
"series": "freertos-c",
|
||
"series_title": "FreeRTOS C",
|
||
"number": "13",
|
||
"count": "15",
|
||
"slug": "uart-pipeline",
|
||
"title": "UART interrupt-to-task pipeline",
|
||
"topic": "bounded RX ISR, SPSC ring, task notification and frame ownership",
|
||
"project": "Freestanding C nad FreeRTOS",
|
||
"subject": "Informatyka",
|
||
"level": "Rok 2 · L13 · RV32I/Hazard3",
|
||
"revision_date": "2026-07-19T00:00:00+02:00",
|
||
"status": "Gotowa",
|
||
"version": "v00.01",
|
||
"uuid": "90a3638b-63f8-5a9c-8b5e-5de4b72ac534",
|
||
"author": "M. Pabiszczak",
|
||
"year": "2026"
|
||
},
|
||
"generated": {
|
||
"tex": "doc/generated/main.tex",
|
||
"html": "web/index.html",
|
||
"html_css": "web/style.css",
|
||
"html_tree_inspector": false,
|
||
"react_app": true
|
||
},
|
||
"render_dictionary": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"label": "CONTEXT",
|
||
"subtitle": "peripheral/ISR/task boundary",
|
||
"status": "enabled",
|
||
"target_label": "fig:a1-context"
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"label": "STRUCTURE",
|
||
"subtitle": "registers, ring and frame",
|
||
"status": "enabled",
|
||
"target_label": "fig:a2-structure"
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"label": "DISPATCH",
|
||
"subtitle": "FromISR notification",
|
||
"status": "enabled",
|
||
"target_label": "fig:a3-dispatch"
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"label": "APPLICATION",
|
||
"subtitle": "single pipeline",
|
||
"status": "unavailable",
|
||
"reason": "The concrete topology is already explicit in A1 and its ordered behavior is complete in A5."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"label": "FLOW",
|
||
"subtitle": "valid and overflow replays",
|
||
"status": "enabled",
|
||
"target_label": "fig:a5-flow"
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"label": "STATE",
|
||
"subtitle": "ring and receiver states",
|
||
"status": "enabled",
|
||
"target_label": "fig:a6-state"
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"label": "RUNTIME",
|
||
"subtitle": "MMIO, indices, stacks and ELF",
|
||
"status": "enabled",
|
||
"target_label": "fig:a7-runtime"
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"label": "PATTERNS",
|
||
"subtitle": "SPSC is part of the mechanism",
|
||
"status": "unavailable",
|
||
"reason": "The SPSC decision is fully proved by A2 and A6; a separate pattern page would duplicate that contract."
|
||
}
|
||
],
|
||
"debug_strategies": {
|
||
"code.contract": {
|
||
"id": "code.contract",
|
||
"kind": "code",
|
||
"action": "open",
|
||
"expected_observations": [
|
||
"one producer and one consumer",
|
||
"parsing absent from ISR"
|
||
],
|
||
"assertions": [
|
||
"byte is visible before head",
|
||
"TX has one task owner"
|
||
],
|
||
"evidence_fields": [
|
||
"code_ref",
|
||
"owner",
|
||
"capacity",
|
||
"budget"
|
||
],
|
||
"prerequisites": [
|
||
"FC07 and FC10 complete"
|
||
],
|
||
"layout": [
|
||
"register bank",
|
||
"SPSC ring",
|
||
"ISR",
|
||
"receiver"
|
||
],
|
||
"commands": [
|
||
"rg -n 'FromISR|ring_|UART|tx_task_only' include src"
|
||
]
|
||
},
|
||
"run.pipeline": {
|
||
"id": "run.pipeline",
|
||
"kind": "run",
|
||
"action": "replay",
|
||
"expected_observations": [
|
||
"OK newline produces ACK",
|
||
"receiver runs before stimulus resumes"
|
||
],
|
||
"assertions": [
|
||
"ISR processes three bytes",
|
||
"wake request is true",
|
||
"TX count is four"
|
||
],
|
||
"evidence_fields": [
|
||
"mcause",
|
||
"processed",
|
||
"head",
|
||
"tail",
|
||
"task state"
|
||
],
|
||
"prerequisites": [
|
||
"clean Hazard3 RAM",
|
||
"IRQ5 enabled"
|
||
],
|
||
"layout": [
|
||
"UART registers",
|
||
"ring",
|
||
"notification",
|
||
"events"
|
||
],
|
||
"commands": [
|
||
"make sim",
|
||
"print g_fc13",
|
||
"print g_fc13_events"
|
||
]
|
||
},
|
||
"run.overflow": {
|
||
"id": "run.overflow",
|
||
"kind": "run",
|
||
"action": "replay",
|
||
"expected_observations": [
|
||
"seven bytes queued",
|
||
"three newest bytes dropped"
|
||
],
|
||
"assertions": [
|
||
"indices stay in range",
|
||
"task discards partial frame"
|
||
],
|
||
"evidence_fields": [
|
||
"processed",
|
||
"queued",
|
||
"dropped",
|
||
"frame_length"
|
||
],
|
||
"prerequisites": [
|
||
"first frame completed",
|
||
"empty ring"
|
||
],
|
||
"layout": [
|
||
"ten RX bytes",
|
||
"seven usable slots",
|
||
"drop counter"
|
||
],
|
||
"commands": [
|
||
"break fc13_checkpoint_committed if $a0 == 8",
|
||
"print g_fc13.ring"
|
||
]
|
||
},
|
||
"code.identity": {
|
||
"id": "code.identity",
|
||
"kind": "code",
|
||
"action": "open",
|
||
"expected_observations": [
|
||
"C ISR and task symbols are present",
|
||
"no C++ runtime"
|
||
],
|
||
"assertions": [
|
||
"notification implementation is linked",
|
||
"external trap is linked"
|
||
],
|
||
"evidence_fields": [
|
||
"symbol",
|
||
"source blob",
|
||
"ELF SHA256",
|
||
"image SHA256"
|
||
],
|
||
"prerequisites": [
|
||
"built ELF"
|
||
],
|
||
"layout": [
|
||
"symbols",
|
||
"sections",
|
||
"artifact hashes"
|
||
],
|
||
"commands": [
|
||
"make check-abi",
|
||
"riscv64-unknown-elf-nm build/task01_uart/prog.elf"
|
||
]
|
||
},
|
||
"run.identity": {
|
||
"id": "run.identity",
|
||
"kind": "run",
|
||
"action": "replay",
|
||
"expected_observations": [
|
||
"three identical logs",
|
||
"digest 6089cfff"
|
||
],
|
||
"assertions": [
|
||
"PASS occurs once",
|
||
"eleven events are ordered"
|
||
],
|
||
"evidence_fields": [
|
||
"digest",
|
||
"event count",
|
||
"SP",
|
||
"artifact identity"
|
||
],
|
||
"prerequisites": [
|
||
"built image"
|
||
],
|
||
"layout": [
|
||
"three clean processes",
|
||
"terminal digest"
|
||
],
|
||
"commands": [
|
||
"make check-determinism"
|
||
]
|
||
}
|
||
},
|
||
"template": "templates/karta-klasyczna.json",
|
||
"title_block": {
|
||
"category": "KARTA PRACY · INFORMATYKA",
|
||
"prepared_by": "M. Pabiszczak",
|
||
"prepared_on": "2026-07-19T00:00:00+02:00",
|
||
"title": "UART interrupt-to-task pipeline",
|
||
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/6a838fd1-ab1b-52b6-baaf-659120a4d60a",
|
||
"repository_url": "https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-c-uart",
|
||
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
|
||
"url_domain": "mpabi.pl",
|
||
"doc_uuid": "6a838fd1-ab1b-52b6-baaf-659120a4d60a",
|
||
"revision": "v00.01",
|
||
"issued_on": "2026-07-19T00:00:00+02:00",
|
||
"series": "FREERTOS-C-13",
|
||
"document_type": "karta pracy",
|
||
"tool": "card-layouts",
|
||
"show_qr": true,
|
||
"show_repository_qr": true,
|
||
"height_cm": 2.6,
|
||
"repeat_on_every_page": true,
|
||
"replace_front_matter": true
|
||
},
|
||
"front_page_scope": {
|
||
"title": "Cel karty",
|
||
"content_tex": "Uczeń buduje ograniczoną ścieżkę UART RX: ISR przenosi bajty do ringa i budzi zadanie, a zadanie składa ramki i jako jedyne posiada TX.",
|
||
"scope_title": "Zakres karty",
|
||
"scope_content_tex": "Dwa prawdziwe external IRQ pokazują poprawną ramkę OK oraz przepełnienie: ring o ośmiu slotach udostępnia siedem, ISR odrzuca trzy najnowsze bajty, a zadanie kasuje niepełną ramkę.",
|
||
"scope_table": {
|
||
"headers": [
|
||
"Lekcja",
|
||
"Task",
|
||
"Najważniejsza idea",
|
||
"Priorytet",
|
||
"Status",
|
||
"Version"
|
||
],
|
||
"rows": [
|
||
{
|
||
"chapter": "FC13",
|
||
"task": "Task01",
|
||
"idea_tex": "bounded RX ISR, SPSC ring, task notification and frame ownership",
|
||
"priority": "główny",
|
||
"status": "ready",
|
||
"version": "v00.01",
|
||
"key": true
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"side_margin_tree_layout": {
|
||
"columns": [
|
||
{
|
||
"id": "zawodowe",
|
||
"label": "TECH",
|
||
"side": "left",
|
||
"tree": "WE -> EK -> KW",
|
||
"description": "Dowody runtime."
|
||
},
|
||
{
|
||
"id": "ogolne",
|
||
"label": "OG",
|
||
"side": "right",
|
||
"tree": "WE -> EN -> KW",
|
||
"description": "Model FreeRTOS C."
|
||
}
|
||
]
|
||
},
|
||
"learning_effects": {
|
||
"FC13.EN01": {
|
||
"bloom_level": "Analiza",
|
||
"label": "UART handoff ownership",
|
||
"text": "Uczeń rozdziela bounded ISR, SPSC data transport, notification, task parsing and TX ownership.",
|
||
"assessment_criteria": [
|
||
"FC13.KW01"
|
||
]
|
||
},
|
||
"FC13.EK01": {
|
||
"bloom_level": "Zastosowanie",
|
||
"label": "Valid frame and overflow replay",
|
||
"text": "Uczeń odtwarza E01–E11 and proves publication order, immediate wake and drop-newest recovery.",
|
||
"assessment_criteria": [
|
||
"FC13.KW01"
|
||
]
|
||
}
|
||
},
|
||
"assessment_criteria": {
|
||
"FC13.KW01": {
|
||
"text": "PASS; two real IRQs; ISR budget <= 10; valid ACK; seven accepted and three dropped on overflow; no index or TX ownership violation; deterministic digest.",
|
||
"learning_effects": [
|
||
"FC13.EN01",
|
||
"FC13.EK01"
|
||
]
|
||
}
|
||
},
|
||
"educational_requirements": {
|
||
"FC13.WE01": {
|
||
"text": "Projektowanie i badanie ograniczonej ścieżki UART od przerwania do zadania FreeRTOS C.",
|
||
"label": "bounded RX ISR, SPSC ring, task notification and frame ownership",
|
||
"learning_effects": [
|
||
"FC13.EN01",
|
||
"FC13.EK01"
|
||
],
|
||
"learning_tree": {
|
||
"schema": "we-learning-tree.v1",
|
||
"policy": "Każda aktywna kotwica wskazuje kod lub checkpoint.",
|
||
"ogolne": [
|
||
{
|
||
"effect_ref": "FC13.EN01",
|
||
"display": "EN LOCAL RTOS.13",
|
||
"source": "LOCAL",
|
||
"official": "RTOS",
|
||
"local": "13",
|
||
"kind": "EN",
|
||
"tree_id": "FC13.WE01.OG.LOCAL.RTOS.13",
|
||
"text": "Uczeń rozdziela bounded ISR, SPSC data transport, notification, task parsing and TX ownership.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "FC13.KW01",
|
||
"display": "KW LOCAL RTOS.13",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "RTOS",
|
||
"local": "13",
|
||
"text": "Łączy kod, diagram i zweryfikowany dowód."
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"zawodowe": [
|
||
{
|
||
"effect_ref": "FC13.EK01",
|
||
"display": "EK LOCAL RTOS.13",
|
||
"source": "LOCAL",
|
||
"official": "RTOS",
|
||
"local": "13",
|
||
"kind": "EK",
|
||
"tree_id": "FC13.WE01.TECH.LOCAL.RTOS.13",
|
||
"text": "Uczeń odtwarza E01–E11 and proves publication order, immediate wake and drop-newest recovery.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "FC13.KW01",
|
||
"display": "KW LOCAL RTOS.13",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "RTOS",
|
||
"local": "13",
|
||
"text": "Łączy kod, diagram i zweryfikowany dowód."
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"debug_checkpoints": {
|
||
"schema": "stem-debug-checkpoints.v1",
|
||
"semantics": "deterministic-replay",
|
||
"artifact": {
|
||
"source": "src/tasks/task01_uart.c",
|
||
"source_git_blob": "7b446e7bd4b77a01171791c15d6f534476465c46",
|
||
"elf": "build/task01_uart/prog.elf",
|
||
"hazard3_elf_sha256": "8a74313a087efb2b0626d5134af0c1289d21761733aba3ad4c31a837c2ab4768",
|
||
"hazard3_image": "build/task01_uart/prog.bin",
|
||
"hazard3_image_sha256": "2d3d44fbf0485bd4169d52ad203d50607eebfa70784f9899e20df5ad8dfb08de"
|
||
},
|
||
"targets": {
|
||
"hazard3-sim": {
|
||
"adapter": "hazard3-reset-load-replay.v1",
|
||
"baseline": "restart-backend",
|
||
"clean_ram": true
|
||
}
|
||
},
|
||
"items": {
|
||
"task01.configured": {
|
||
"event_id": "E01",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 1"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13_event_count",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13_events[0].value",
|
||
"equals": 8
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.receiver-ready": {
|
||
"event_id": "E02",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 2"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.receiver_sp != 0",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13.good_frames",
|
||
"equals": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.good-injected": {
|
||
"event_id": "E03",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 3"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.uart.rx_count",
|
||
"equals": 3
|
||
},
|
||
{
|
||
"expr": "g_fc13.first_done",
|
||
"equals": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.isr-entry": {
|
||
"event_id": "E04",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 4"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.mcause",
|
||
"equals": 2147483659
|
||
},
|
||
{
|
||
"expr": "g_fc13.isr_sp != g_fc13.stimulus_sp",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.good-isr": {
|
||
"event_id": "E05",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 5"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.processed[0]",
|
||
"equals": 3
|
||
},
|
||
{
|
||
"expr": "g_fc13.wake_requested[0]",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13.ring.head",
|
||
"equals": 3
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.frame": {
|
||
"event_id": "E06",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 6"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.good_frames",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13.uart.tx_count",
|
||
"equals": 4
|
||
},
|
||
{
|
||
"expr": "g_fc13.stimulus_after_first",
|
||
"equals": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.overlong-injected": {
|
||
"event_id": "E07",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 7"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.uart.rx_count",
|
||
"equals": 10
|
||
},
|
||
{
|
||
"expr": "g_fc13.first_done",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.overflow-isr": {
|
||
"event_id": "E08",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 8"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.processed[1]",
|
||
"equals": 10
|
||
},
|
||
{
|
||
"expr": "g_fc13.ring.dropped",
|
||
"equals": 3
|
||
},
|
||
{
|
||
"expr": "fc13_ring_used(&g_fc13.ring)",
|
||
"equals": 7
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.overflow-task": {
|
||
"event_id": "E09",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 9"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.overflow_frames",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13.frame_length",
|
||
"equals": 0
|
||
},
|
||
{
|
||
"expr": "g_fc13.ring.head == g_fc13.ring.tail",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.stimulus-resumed": {
|
||
"event_id": "E10",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 10"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13.second_done_at_resume",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13.stimulus_after_second",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.pass": {
|
||
"event_id": "E11",
|
||
"stop": {
|
||
"symbol": "fc13_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 11"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc13_pass",
|
||
"equals": 1
|
||
},
|
||
{
|
||
"expr": "g_fc13_event_count",
|
||
"equals": 11
|
||
},
|
||
{
|
||
"expr": "g_fc13.ring.dropped",
|
||
"equals": 3
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"sections": [
|
||
{
|
||
"title": "A1 — Peripheral-to-task boundary",
|
||
"order": 10,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "The ISR moves available bytes and wakes a task. Framing and TX remain outside interrupt context.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a1-context.png",
|
||
"html_path": "assets/a1-context.svg",
|
||
"source_path": "assets/a1-context.puml",
|
||
"caption": "A1 CONTEXT — peripheral, ISR, ring, notification and receiver.",
|
||
"label": "fig:a1-context",
|
||
"alt": "A1 · UART responsibility boundary",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"registers": 1,
|
||
"isr": 1,
|
||
"ring": 1,
|
||
"receiver": 1,
|
||
"pass": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc13-a1-context",
|
||
"title": "A1 · UART responsibility boundary",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · UART ISR to frame task"
|
||
},
|
||
"block": {
|
||
"id": "a1",
|
||
"label": "A1 CONTEXT",
|
||
"description": "UART registers, the interrupt path, a bounded handoff and task-only parsing have separate owners."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "boundary",
|
||
"label": "PERIPHERAL / ISR / TASK",
|
||
"steps": [
|
||
{
|
||
"id": "registers",
|
||
"number": 1,
|
||
"label": "UART register bank exposes RX state",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "01",
|
||
"code_ref": "include/task01_uart.h:27",
|
||
"description": "UART register bank exposes RX state",
|
||
"evidence": "status, data and indices"
|
||
},
|
||
{
|
||
"id": "isr",
|
||
"number": 2,
|
||
"label": "ISR owns bounded byte transfer",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_uart.c:159",
|
||
"description": "ISR owns bounded byte transfer",
|
||
"evidence": "at most ten bytes"
|
||
},
|
||
{
|
||
"id": "ring",
|
||
"number": 3,
|
||
"label": "ring connects one producer and one consumer",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "03",
|
||
"code_ref": "include/task01_uart_model.h:40",
|
||
"description": "ring connects one producer and one consumer",
|
||
"evidence": "publish byte before head"
|
||
},
|
||
{
|
||
"id": "receiver",
|
||
"number": 4,
|
||
"label": "receiver owns parsing and TX",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "04",
|
||
"code_ref": "src/tasks/task01_uart.c:207",
|
||
"description": "receiver owns parsing and TX",
|
||
"evidence": "no parser in ISR"
|
||
},
|
||
{
|
||
"id": "pass",
|
||
"number": 5,
|
||
"label": "runtime validates the boundary",
|
||
"mode": "RUN",
|
||
"event_id": "E11",
|
||
"strategy_ref": "run.identity",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_uart.c:346",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "runtime validates the boundary",
|
||
"evidence": "PASS and stable digest"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A2 — Register, ring and task state",
|
||
"order": 20,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "An eight-slot ring keeps one slot empty. Head belongs to the ISR, tail to the receiver, and dropped counts rejected newest bytes.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a2-structure.png",
|
||
"html_path": "assets/a2-structure.svg",
|
||
"source_path": "assets/a2-structure.puml",
|
||
"caption": "A2 STRUCTURE — register bank, seven usable ring slots and frame state.",
|
||
"label": "fig:a2-structure",
|
||
"alt": "A2 · bounded UART storage",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"uart": 1,
|
||
"capacity": 1,
|
||
"push": 1,
|
||
"pop": 1,
|
||
"overflow": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc13-a2-structure",
|
||
"title": "A2 · bounded UART storage",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · UART ISR to frame task"
|
||
},
|
||
"block": {
|
||
"id": "a2",
|
||
"label": "A2 STRUCTURE",
|
||
"description": "The register bank, SPSC ring, frame scratch space and evidence trace have explicit storage and ownership."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "storage",
|
||
"label": "BOUNDED STORAGE",
|
||
"steps": [
|
||
{
|
||
"id": "uart",
|
||
"number": 1,
|
||
"label": "volatile UART fields model device state",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "01",
|
||
"code_ref": "include/task01_uart.h:27",
|
||
"description": "volatile UART fields model device state",
|
||
"evidence": "RX capacity twelve"
|
||
},
|
||
{
|
||
"id": "capacity",
|
||
"number": 2,
|
||
"label": "ring has eight slots and seven usable",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "02",
|
||
"code_ref": "include/task01_uart_model.h:7",
|
||
"description": "ring has eight slots and seven usable",
|
||
"evidence": "empty slot disambiguates full"
|
||
},
|
||
{
|
||
"id": "push",
|
||
"number": 3,
|
||
"label": "producer publishes data before head",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "03",
|
||
"code_ref": "include/task01_uart_model.h:43",
|
||
"description": "producer publishes data before head",
|
||
"evidence": "single ISR producer"
|
||
},
|
||
{
|
||
"id": "pop",
|
||
"number": 4,
|
||
"label": "consumer retires data before tail",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "04",
|
||
"code_ref": "include/task01_uart_model.h:58",
|
||
"description": "consumer retires data before tail",
|
||
"evidence": "single task consumer"
|
||
},
|
||
{
|
||
"id": "overflow",
|
||
"number": 5,
|
||
"label": "second IRQ fills seven and drops three",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.overflow",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_uart.c:202",
|
||
"snapshot_ref": "task01.overflow-isr",
|
||
"description": "second IRQ fills seven and drops three",
|
||
"evidence": "used=7, dropped=3"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A3 — ISR-to-notification binding",
|
||
"order": 30,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Only the FromISR notification API appears in the handler; the receiver blocks with the matching task-context take.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a3-dispatch.png",
|
||
"html_path": "assets/a3-dispatch.svg",
|
||
"source_path": "assets/a3-dispatch.puml",
|
||
"caption": "A3 DISPATCH — MEI, bounded drain, notify and immediate task restore.",
|
||
"label": "fig:a3-dispatch",
|
||
"alt": "A3 · interrupt dispatch",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"vector": 1,
|
||
"entry": 1,
|
||
"budget": 1,
|
||
"notify": 1,
|
||
"yield": 1,
|
||
"receiver-first": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc13-a3-dispatch",
|
||
"title": "A3 · interrupt dispatch",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · UART ISR to frame task"
|
||
},
|
||
"block": {
|
||
"id": "a3",
|
||
"label": "A3 DISPATCH",
|
||
"description": "The real external interrupt enters the FreeRTOS trap path, clears its source, notifies once and yields once."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "dispatch",
|
||
"label": "IRQ / FROMISR / RESTORE",
|
||
"steps": [
|
||
{
|
||
"id": "vector",
|
||
"number": 1,
|
||
"label": "external vector enters the port trap",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "01",
|
||
"code_ref": "src/common/hazard3_freertos_traps.S:24",
|
||
"description": "external vector enters the port trap",
|
||
"evidence": "full context save"
|
||
},
|
||
{
|
||
"id": "entry",
|
||
"number": 2,
|
||
"label": "first IRQ records MEI and ISR stack",
|
||
"mode": "RUN",
|
||
"event_id": "E04",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_uart.c:166",
|
||
"snapshot_ref": "task01.isr-entry",
|
||
"description": "first IRQ records MEI and ISR stack",
|
||
"evidence": "mcause is machine external interrupt"
|
||
},
|
||
{
|
||
"id": "budget",
|
||
"number": 3,
|
||
"label": "loop obeys a ten-byte budget",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_uart.c:174",
|
||
"description": "loop obeys a ten-byte budget",
|
||
"evidence": "bounded ISR work"
|
||
},
|
||
{
|
||
"id": "notify",
|
||
"number": 4,
|
||
"label": "one FromISR give merges wake request",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "04",
|
||
"code_ref": "src/tasks/task01_uart.c:189",
|
||
"description": "one FromISR give merges wake request",
|
||
"evidence": "higher-priority task ready"
|
||
},
|
||
{
|
||
"id": "yield",
|
||
"number": 5,
|
||
"label": "port performs one requested yield",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.contract",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_uart.c:202",
|
||
"description": "port performs one requested yield",
|
||
"evidence": "receiver restored first"
|
||
},
|
||
{
|
||
"id": "receiver-first",
|
||
"number": 6,
|
||
"label": "receiver completes before stimulus resumes",
|
||
"mode": "RUN",
|
||
"event_id": "E06",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "06",
|
||
"code_ref": "src/tasks/task01_uart.c:256",
|
||
"snapshot_ref": "task01.frame",
|
||
"description": "receiver completes before stimulus resumes",
|
||
"evidence": "stimulus_after_first=0"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A5 — Two-frame replay",
|
||
"order": 50,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "The first interrupt delivers OK plus newline and produces ACK. The second presents ten bytes, accepts seven, drops three and discards the partial frame in task context.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a5-flow.png",
|
||
"html_path": "assets/a5-flow.svg",
|
||
"source_path": "assets/a5-flow.puml",
|
||
"caption": "A5 FLOW — E01–E11 from configuration to verified PASS.",
|
||
"label": "fig:a5-flow",
|
||
"alt": "A5 · UART pipeline replay",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"config": 1,
|
||
"wait": 1,
|
||
"inject": 1,
|
||
"isr-entry-flow": 1,
|
||
"isr-good": 1,
|
||
"frame": 1,
|
||
"overlong": 1,
|
||
"drop": 1,
|
||
"discard": 1,
|
||
"resume": 1,
|
||
"verified": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-sequence",
|
||
"storage_key": "fc13-a5-flow",
|
||
"title": "A5 · UART pipeline replay",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · UART ISR to frame task"
|
||
},
|
||
"block": {
|
||
"id": "a5",
|
||
"label": "A5 FLOW",
|
||
"description": "Eleven committed events cover one valid frame and one deterministic overflow fixture."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "flow",
|
||
"label": "VALID FRAME / OVERFLOW / PASS",
|
||
"steps": [
|
||
{
|
||
"id": "config",
|
||
"number": 1,
|
||
"label": "configure IRQ and eight-slot ring",
|
||
"mode": "RUN",
|
||
"event_id": "E01",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_uart.c:411",
|
||
"snapshot_ref": "task01.configured",
|
||
"description": "configure IRQ and eight-slot ring",
|
||
"evidence": "capacity=8"
|
||
},
|
||
{
|
||
"id": "wait",
|
||
"number": 2,
|
||
"label": "receiver reaches notification wait",
|
||
"mode": "RUN",
|
||
"event_id": "E02",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_uart.c:219",
|
||
"snapshot_ref": "task01.receiver-ready",
|
||
"description": "receiver reaches notification wait",
|
||
"evidence": "receiver priority 3"
|
||
},
|
||
{
|
||
"id": "inject",
|
||
"number": 3,
|
||
"label": "stimulus publishes OK newline",
|
||
"mode": "RUN",
|
||
"event_id": "E03",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_uart.c:294",
|
||
"snapshot_ref": "task01.good-injected",
|
||
"description": "stimulus publishes OK newline",
|
||
"evidence": "three RX bytes"
|
||
},
|
||
{
|
||
"id": "isr-entry-flow",
|
||
"number": 4,
|
||
"label": "external IRQ enters handler",
|
||
"mode": "RUN",
|
||
"event_id": "E04",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "04",
|
||
"code_ref": "src/tasks/task01_uart.c:166",
|
||
"snapshot_ref": "task01.isr-entry",
|
||
"description": "external IRQ enters handler",
|
||
"evidence": "MEI and ISR SP"
|
||
},
|
||
{
|
||
"id": "isr-good",
|
||
"number": 5,
|
||
"label": "ISR queues three and requests wake",
|
||
"mode": "RUN",
|
||
"event_id": "E05",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_uart.c:197",
|
||
"snapshot_ref": "task01.good-isr",
|
||
"description": "ISR queues three and requests wake",
|
||
"evidence": "processed=3"
|
||
},
|
||
{
|
||
"id": "frame",
|
||
"number": 6,
|
||
"label": "task validates frame and owns ACK",
|
||
"mode": "RUN",
|
||
"event_id": "E06",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "06",
|
||
"code_ref": "src/tasks/task01_uart.c:238",
|
||
"snapshot_ref": "task01.frame",
|
||
"description": "task validates frame and owns ACK",
|
||
"evidence": "good_frames=1"
|
||
},
|
||
{
|
||
"id": "overlong",
|
||
"number": 7,
|
||
"label": "stimulus publishes ten X bytes",
|
||
"mode": "RUN",
|
||
"event_id": "E07",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "07",
|
||
"code_ref": "src/tasks/task01_uart.c:306",
|
||
"snapshot_ref": "task01.overlong-injected",
|
||
"description": "stimulus publishes ten X bytes",
|
||
"evidence": "receiver already done"
|
||
},
|
||
{
|
||
"id": "drop",
|
||
"number": 8,
|
||
"label": "ISR accepts seven and drops three",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "08",
|
||
"code_ref": "src/tasks/task01_uart.c:202",
|
||
"snapshot_ref": "task01.overflow-isr",
|
||
"description": "ISR accepts seven and drops three",
|
||
"evidence": "drop-newest"
|
||
},
|
||
{
|
||
"id": "discard",
|
||
"number": 9,
|
||
"label": "task discards partial overflow frame",
|
||
"mode": "RUN",
|
||
"event_id": "E09",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "09",
|
||
"code_ref": "src/tasks/task01_uart.c:249",
|
||
"snapshot_ref": "task01.overflow-task",
|
||
"description": "task discards partial overflow frame",
|
||
"evidence": "overflow_frames=1"
|
||
},
|
||
{
|
||
"id": "resume",
|
||
"number": 10,
|
||
"label": "stimulus resumes after receiver",
|
||
"mode": "RUN",
|
||
"event_id": "E10",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "10",
|
||
"code_ref": "src/tasks/task01_uart.c:315",
|
||
"snapshot_ref": "task01.stimulus-resumed",
|
||
"description": "stimulus resumes after receiver",
|
||
"evidence": "second_done=1"
|
||
},
|
||
{
|
||
"id": "verified",
|
||
"number": 11,
|
||
"label": "verifier commits deterministic PASS",
|
||
"mode": "RUN",
|
||
"event_id": "E11",
|
||
"strategy_ref": "run.identity",
|
||
"svg_label": "11",
|
||
"code_ref": "src/tasks/task01_uart.c:376",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "verifier commits deterministic PASS",
|
||
"evidence": "digest 6089cfff"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A6 — Ring and receiver states",
|
||
"order": 60,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Notification is a wake signal, not the byte container. The ring carries data; the receiver drains all published bytes after each wake.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a6-state.png",
|
||
"html_path": "assets/a6-state.svg",
|
||
"source_path": "assets/a6-state.puml",
|
||
"caption": "A6 STATE — empty, filling, notified, draining and overflow recovery.",
|
||
"label": "fig:a6-state",
|
||
"alt": "A6 · ring and task state",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"empty": 1,
|
||
"filled": 1,
|
||
"drained": 1,
|
||
"full": 1,
|
||
"recovered": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc13-a6-state",
|
||
"title": "A6 · ring and task state",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · UART ISR to frame task"
|
||
},
|
||
"block": {
|
||
"id": "a6",
|
||
"label": "A6 STATE",
|
||
"description": "Ring occupancy and receiver state change independently but obey one publication contract."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "state",
|
||
"label": "RING / NOTIFICATION / FRAME",
|
||
"steps": [
|
||
{
|
||
"id": "empty",
|
||
"number": 1,
|
||
"label": "empty ring and blocked receiver",
|
||
"mode": "RUN",
|
||
"event_id": "E03",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_uart.c:297",
|
||
"snapshot_ref": "task01.good-injected",
|
||
"description": "empty ring and blocked receiver",
|
||
"evidence": "head=tail before IRQ"
|
||
},
|
||
{
|
||
"id": "filled",
|
||
"number": 2,
|
||
"label": "three bytes published before notify",
|
||
"mode": "RUN",
|
||
"event_id": "E05",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_uart.c:174",
|
||
"snapshot_ref": "task01.good-isr",
|
||
"description": "three bytes published before notify",
|
||
"evidence": "used=3"
|
||
},
|
||
{
|
||
"id": "drained",
|
||
"number": 3,
|
||
"label": "receiver drains and returns to wait",
|
||
"mode": "RUN",
|
||
"event_id": "E06",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_uart.c:229",
|
||
"snapshot_ref": "task01.frame",
|
||
"description": "receiver drains and returns to wait",
|
||
"evidence": "head=tail"
|
||
},
|
||
{
|
||
"id": "full",
|
||
"number": 4,
|
||
"label": "second IRQ reaches seven usable slots",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "04",
|
||
"code_ref": "include/task01_uart_model.h:47",
|
||
"snapshot_ref": "task01.overflow-isr",
|
||
"description": "second IRQ reaches seven usable slots",
|
||
"evidence": "dropped=3"
|
||
},
|
||
{
|
||
"id": "recovered",
|
||
"number": 5,
|
||
"label": "receiver resets partial frame",
|
||
"mode": "RUN",
|
||
"event_id": "E09",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_uart.c:249",
|
||
"snapshot_ref": "task01.overflow-task",
|
||
"description": "receiver resets partial frame",
|
||
"evidence": "frame length zero"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A7 — Runtime and artifact proof",
|
||
"order": 70,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Three clean simulator processes must produce the same terminal digest. ABI checks reject C++ and require the trap, notification and task boundaries.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a7-runtime.png",
|
||
"html_path": "assets/a7-runtime.svg",
|
||
"source_path": "assets/a7-runtime.puml",
|
||
"caption": "A7 RUNTIME — cause, stacks, indices, symbols and deterministic identity.",
|
||
"label": "fig:a7-runtime",
|
||
"alt": "A7 · runtime proof",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"cause": 1,
|
||
"indices": 1,
|
||
"stacks": 1,
|
||
"abi": 1,
|
||
"determinism": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc13-a7-runtime",
|
||
"title": "A7 · runtime proof",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · UART ISR to frame task"
|
||
},
|
||
"block": {
|
||
"id": "a7",
|
||
"label": "A7 RUNTIME",
|
||
"description": "The proof combines register values, ring indices, three stack contexts, event order and exact C artifact identity."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "runtime",
|
||
"label": "RUNTIME EVIDENCE",
|
||
"steps": [
|
||
{
|
||
"id": "cause",
|
||
"number": 1,
|
||
"label": "mcause proves a real external IRQ",
|
||
"mode": "RUN",
|
||
"event_id": "E04",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_uart.c:167",
|
||
"snapshot_ref": "task01.isr-entry",
|
||
"description": "mcause proves a real external IRQ",
|
||
"evidence": "0x8000000b"
|
||
},
|
||
{
|
||
"id": "indices",
|
||
"number": 2,
|
||
"label": "head and tail stay inside capacity",
|
||
"mode": "RUN",
|
||
"event_id": "E09",
|
||
"strategy_ref": "run.pipeline",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_uart.c:266",
|
||
"snapshot_ref": "task01.overflow-task",
|
||
"description": "head and tail stay inside capacity",
|
||
"evidence": "ring empty after drain"
|
||
},
|
||
{
|
||
"id": "stacks",
|
||
"number": 3,
|
||
"label": "ISR, receiver and stimulus stacks differ",
|
||
"mode": "RUN",
|
||
"event_id": "E11",
|
||
"strategy_ref": "run.identity",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_uart.c:373",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "ISR, receiver and stimulus stacks differ",
|
||
"evidence": "three SP values"
|
||
},
|
||
{
|
||
"id": "abi",
|
||
"number": 4,
|
||
"label": "ELF exposes C and FromISR boundaries",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.identity",
|
||
"svg_label": "04",
|
||
"code_ref": "scripts/check_abi.sh:18",
|
||
"description": "ELF exposes C and FromISR boundaries",
|
||
"evidence": "no C++ or unwind"
|
||
},
|
||
{
|
||
"id": "determinism",
|
||
"number": 5,
|
||
"label": "three clean runs agree",
|
||
"mode": "RUN",
|
||
"event_id": "E11",
|
||
"strategy_ref": "run.identity",
|
||
"svg_label": "05",
|
||
"code_ref": "scripts/check_determinism.sh:14",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "three clean runs agree",
|
||
"evidence": "identical digest"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "Task01 — UART ISR to frame task",
|
||
"order": 90,
|
||
"content_kind": "tasks",
|
||
"task_refs": [
|
||
"task01"
|
||
]
|
||
}
|
||
],
|
||
"tasks": {
|
||
"task01": {
|
||
"title": "Build and prove a bounded UART RX pipeline",
|
||
"uuid": "6a838fd1-ab1b-52b6-baaf-659120a4d60a",
|
||
"prompt_tex": "Odtwórz E01--E11. Udowodnij, że ISR tylko przenosi bajty i budzi zadanie, a parser oraz TX działają wyłącznie w kontekście zadania.",
|
||
"criterion": "PASS; two real IRQs; ISR budget <= 10; valid ACK; seven accepted and three dropped on overflow; no index or TX ownership violation; deterministic digest.",
|
||
"conclusion_tex": "Notyfikacja przenosi informację o pracy, nie bajty. Dane mają osobny ograniczony ring; kolejność publikacji, budżet ISR i jawna polityka przepełnienia są częścią kontraktu.",
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "contract",
|
||
"title": "A — kontrakt",
|
||
"content_tex": "Rozdziel właścicieli rejestrów, indeksów, parsera i TX.",
|
||
"steps": [
|
||
{
|
||
"id": "owners",
|
||
"title": "Zapisz tabelę własności.",
|
||
"content_tex": "ISR zapisuje head; zadanie zapisuje tail i stan ramki."
|
||
},
|
||
{
|
||
"id": "predict",
|
||
"title": "Przewidź dwa przebiegi.",
|
||
"content_tex": "Wyznacz zajętość ringa dla trzech i dziesięciu bajtów."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "replay",
|
||
"title": "B — replay",
|
||
"content_tex": "Powiąż każdy RUN z jednym zatwierdzonym eventem.",
|
||
"steps": [
|
||
{
|
||
"id": "valid",
|
||
"title": "Sprawdź E03--E06.",
|
||
"content_tex": "Trzy bajty, wake request, ACK i natychmiastowy receiver."
|
||
},
|
||
{
|
||
"id": "overflow",
|
||
"title": "Sprawdź E07--E10.",
|
||
"content_tex": "Siedem zaakceptowanych, trzy odrzucone i reset ramki."
|
||
},
|
||
{
|
||
"id": "identity",
|
||
"title": "Sprawdź E11.",
|
||
"content_tex": "ABI, trzy stosy, kolejność i digest."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "policy",
|
||
"title": "Ćwiczenie — polityka przepełnienia",
|
||
"prompt_tex": "Zmień wyłącznie politykę z drop-newest na drop-oldest. Zapisz nowy kontrakt indeksów i przewidź, które siedem z dziesięciu bajtów odczyta zadanie.",
|
||
"evidence_tex": "Tabela bajtów wejściowych, head/tail przed i po IRQ, drop counter oraz ślad zadania.",
|
||
"criterion": "Uczeń zachowuje bounded ISR, nie publikuje indeksu przed bajtem i potrafi wskazać utracone dane.",
|
||
"based_on": [
|
||
"contract",
|
||
"replay"
|
||
]
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"FC13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"FC13.EN01",
|
||
"FC13.EK01"
|
||
],
|
||
"assessment_criterion_ref": "FC13.KW01"
|
||
}
|
||
},
|
||
"tasks_order": [
|
||
"task01"
|
||
]
|
||
}
|