{ "$schema": "../../../tools/card-layouts/schemas/card-source.schema.json", "schema": "esc-card-source.v1", "card": { "id": "mpabi-freertos-c-15-integration", "series": "freertos-c", "series_title": "FreeRTOS C", "number": "15", "count": "15", "slug": "integration", "title": "Integrated deterministic FreeRTOS C application", "topic": "real IRQ, typed pipeline, heartbeat rendezvous and bounded diagnostics", "project": "Freestanding C nad FreeRTOS", "subject": "Informatyka", "level": "Rok 2 · L15 · RV32I/Hazard3", "revision_date": "2026-07-19T00:00:00+02:00", "status": "Gotowa", "version": "v00.01", "uuid": "0092481f-af7c-517a-87f7-e0d7af7e5a0e", "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": "end-to-end boundaries", "status": "enabled", "target_label": "fig:a1-context" }, { "id": "A2", "label": "STRUCTURE", "subtitle": "typed objects and static storage", "status": "enabled", "target_label": "fig:a2-structure" }, { "id": "A3", "label": "DISPATCH", "subtitle": "IRQ and timer bindings", "status": "enabled", "target_label": "fig:a3-dispatch" }, { "id": "A4", "label": "APPLICATION", "subtitle": "task and primitive topology", "status": "enabled", "target_label": "fig:a4-application" }, { "id": "A5", "label": "FLOW", "subtitle": "E01-E14 replay", "status": "enabled", "target_label": "fig:a5-flow" }, { "id": "A6", "label": "STATE", "subtitle": "payload and readiness lifetime", "status": "enabled", "target_label": "fig:a6-state" }, { "id": "A7", "label": "RUNTIME", "subtitle": "deadline, heap, stacks and ELF", "status": "enabled", "target_label": "fig:a7-runtime" }, { "id": "A8", "label": "PATTERNS", "subtitle": "smallest justified mechanism", "status": "enabled", "target_label": "fig:a8-patterns" } ], "debug_strategies": { "code.architecture": { "id": "code.architecture", "kind": "code", "action": "open", "expected_observations": [ "each primitive has one role", "application objects are static" ], "assertions": [ "notification carries no payload", "shared state is accessed under mutex" ], "evidence_fields": [ "type", "owner", "priority", "storage", "code_ref" ], "prerequisites": [ "FC01-FC14 complete" ], "layout": [ "typed payloads", "object owners", "callbacks", "static storage" ], "commands": [ "rg -n 'CreateStatic|FromISR|Queue|EventGroup|Semaphore|Timer' include src" ] }, "run.startup": { "id": "run.startup", "kind": "run", "action": "replay", "expected_observations": [ "E01-E05 block in strict priority order", "E06 publishes one input" ], "assertions": [ "heap delta is zero", "every handle and stack pointer is nonzero" ], "evidence_fields": [ "handle", "SP", "heap", "priority", "event" ], "prerequisites": [ "clean Hazard3 RAM", "static object creation complete" ], "layout": [ "five task stacks", "two queues", "event group", "mutex", "timer" ], "commands": [ "break fc15_checkpoint_committed if $a0 <= 6", "print g_fc15" ] }, "run.pipeline": { "id": "run.pipeline", "kind": "run", "action": "replay", "expected_observations": [ "E07-E10 form one uninterrupted priority chain", "sum_squares=140" ], "assertions": [ "source clears before notify", "E10 precedes stimulus E11" ], "evidence_fields": [ "mcause", "wake", "payload", "checksum", "tick", "SP" ], "prerequisites": [ "E02-E05 waiting", "input status ready" ], "layout": [ "external IRQ", "notification", "Sample queue", "Result queue", "publication" ], "commands": [ "make sim", "print g_fc15_events", "print g_fc15.result_seen" ] }, "run.rendezvous": { "id": "run.rendezvous", "kind": "run", "action": "replay", "expected_observations": [ "heartbeat at start+5", "supervisor receives mask 0x3" ], "assertions": [ "mutex entered three times", "completion is within eight ticks" ], "evidence_fields": [ "timer tick", "event mask", "revision", "heartbeat", "heap", "HWM" ], "prerequisites": [ "result bit set", "one-shot timer active" ], "layout": [ "timer daemon", "mutex snapshot", "event bits", "diagnostics" ], "commands": [ "break fc15_checkpoint_committed if $a0 >= 12", "print g_fc15" ] }, "code.identity": { "id": "code.identity", "kind": "code", "action": "open", "expected_observations": [ "every selected primitive is linked", "no C++ or unwind metadata" ], "assertions": [ "external trap and daemon task are present", "static memory hooks are present" ], "evidence_fields": [ "symbol", "source blob", "ELF SHA256", "image SHA256" ], "prerequisites": [ "built ELF" ], "layout": [ "C callbacks", "kernel primitives", "static hooks", "artifact hashes" ], "commands": [ "make check-abi", "riscv64-unknown-elf-nm build/task01_integration/prog.elf" ] }, "run.identity": { "id": "run.identity", "kind": "run", "action": "replay", "expected_observations": [ "one PASS per run", "digest 8f767299 three times" ], "assertions": [ "event order is exact", "all terminal invariants are true" ], "evidence_fields": [ "digest", "event count", "PASS", "artifact identity" ], "prerequisites": [ "built image" ], "layout": [ "fourteen events", "three clean processes", "terminal" ], "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": "Integrated deterministic FreeRTOS C application", "url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/fe92efeb-3c38-5975-86d8-ed630e1ad3bb", "repository_url": "https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-c-integration", "url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84", "url_domain": "mpabi.pl", "doc_uuid": "fe92efeb-3c38-5975-86d8-ed630e1ad3bb", "revision": "v00.01", "issued_on": "2026-07-19T00:00:00+02:00", "series": "FREERTOS-C-15", "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ń składa kompletną aplikację FreeRTOS C i uzasadnia każdy użyty mechanizm przez payload, własność, fan-in albo czas, a następnie dowodzi całego kontraktu jednym deterministycznym śladem.", "scope_title": "Zakres karty", "scope_content_tex": "Prawdziwy external IRQ budzi acquisition. Dwie kolejki prowadzą Sample przez obliczenie sumy kwadratów do publikacji. Timer daemon dodaje heartbeat; event group i mutex tworzą spójny snapshot. Wszystkie obiekty aplikacji mają pamięć statyczną.", "scope_table": { "headers": [ "Lekcja", "Task", "Najważniejsza idea", "Priorytet", "Status", "Version" ], "rows": [ { "chapter": "FC15", "task": "Task01", "idea_tex": "real IRQ, typed pipeline, heartbeat rendezvous and bounded diagnostics", "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": { "FC15.EN01": { "bloom_level": "Analiza", "label": "Justified RTOS architecture", "text": "Uczeń dobiera notification, queue, mutex, event group and timer by ownership and synchronization need.", "assessment_criteria": [ "FC15.KW01" ] }, "FC15.EK01": { "bloom_level": "Zastosowanie", "label": "Deterministic end-to-end proof", "text": "Uczeń odtwarza E01–E14 from hardware input through result, heartbeat, diagnostics and PASS.", "assessment_criteria": [ "FC15.KW01" ] } }, "assessment_criteria": { "FC15.KW01": { "text": "PASS; real MEI; pipeline before stimulus resume; sum 140; result and heartbeat ALL-mask; completion by tick 8; zero application heap delta; positive stack HWM; deterministic digest.", "learning_effects": [ "FC15.EN01", "FC15.EK01" ] } }, "educational_requirements": { "FC15.WE01": { "text": "Samodzielne zaprojektowanie, implementacja i diagnostyka deterministycznej aplikacji FreeRTOS C.", "label": "real IRQ, typed pipeline, heartbeat rendezvous and bounded diagnostics", "learning_effects": [ "FC15.EN01", "FC15.EK01" ], "learning_tree": { "schema": "we-learning-tree.v1", "policy": "Każda aktywna kotwica wskazuje kod lub checkpoint.", "ogolne": [ { "effect_ref": "FC15.EN01", "display": "EN LOCAL RTOS.15", "source": "LOCAL", "official": "RTOS", "local": "15", "kind": "EN", "tree_id": "FC15.WE01.OG.LOCAL.RTOS.15", "text": "Uczeń dobiera notification, queue, mutex, event group and timer by ownership and synchronization need.", "kw": [ { "criterion_ref": "FC15.KW01", "display": "KW LOCAL RTOS.15", "source": "LOCAL", "kind": "KW", "official": "RTOS", "local": "15", "text": "Łączy kod, diagram i zweryfikowany dowód." } ] } ], "zawodowe": [ { "effect_ref": "FC15.EK01", "display": "EK LOCAL RTOS.15", "source": "LOCAL", "official": "RTOS", "local": "15", "kind": "EK", "tree_id": "FC15.WE01.TECH.LOCAL.RTOS.15", "text": "Uczeń odtwarza E01–E14 from hardware input through result, heartbeat, diagnostics and PASS.", "kw": [ { "criterion_ref": "FC15.KW01", "display": "KW LOCAL RTOS.15", "source": "LOCAL", "kind": "KW", "official": "RTOS", "local": "15", "text": "Łączy kod, diagram i zweryfikowany dowód." } ] } ] } } }, "debug_checkpoints": { "schema": "stem-debug-checkpoints.v1", "semantics": "deterministic-replay", "artifact": { "source": "src/tasks/task01_integration.c", "source_git_blob": "b53b089d45e31108123aff657619dfc1603fe0b3", "elf": "build/task01_integration/prog.elf", "hazard3_elf_sha256": "9ebc2e032d20cf55c43b862e60936b26df0de0899cab6fca65ba032b4de77695", "hazard3_image": "build/task01_integration/prog.bin", "hazard3_image_sha256": "fd46dd3a71a4c0b5d9c5fe9c1c62a5201eed4c229331d207d97fec658f6e7570" }, "targets": { "hazard3-sim": { "adapter": "hazard3-reset-load-replay.v1", "baseline": "restart-backend", "clean_ram": true } }, "items": { "task01.configured": { "event_id": "E01", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 1" }, "verify": { "expressions": [ { "expr": "g_fc15_event_count", "equals": 1 }, { "expr": "g_fc15.heap_before == g_fc15.heap_after", "equals": 1 }, { "expr": "g_fc15.sample_queue != 0 && g_fc15.result_queue != 0", "equals": 1 } ] } }, "task01.acquisition-ready": { "event_id": "E02", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 2" }, "verify": { "expressions": [ { "expr": "g_fc15.acquisition_sp != 0", "equals": 1 }, { "expr": "g_fc15.acquired", "equals": 0 } ] } }, "task01.processor-ready": { "event_id": "E03", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 3" }, "verify": { "expressions": [ { "expr": "g_fc15.processor_sp != 0", "equals": 1 }, { "expr": "g_fc15.processed", "equals": 0 } ] } }, "task01.publisher-ready": { "event_id": "E04", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 4" }, "verify": { "expressions": [ { "expr": "g_fc15.publisher_sp != 0", "equals": 1 }, { "expr": "g_fc15.published", "equals": 0 } ] } }, "task01.supervisor-ready": { "event_id": "E05", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 5" }, "verify": { "expressions": [ { "expr": "g_fc15.supervisor_sp != 0", "equals": 1 }, { "expr": "g_fc15.returned_bits", "equals": 0 } ] } }, "task01.input-ready": { "event_id": "E06", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 6" }, "verify": { "expressions": [ { "expr": "g_fc15.input.status", "equals": 1 }, { "expr": "g_fc15.input.sequence", "equals": 42 }, { "expr": "g_fc15.input.value", "equals": 7 } ] } }, "task01.irq": { "event_id": "E07", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 7" }, "verify": { "expressions": [ { "expr": "g_fc15.mcause", "equals": 2147483659 }, { "expr": "g_fc15.irq_after_clear", "equals": 0 }, { "expr": "g_fc15.higher_priority_task_woken", "equals": 1 } ] } }, "task01.acquired": { "event_id": "E08", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 8" }, "verify": { "expressions": [ { "expr": "g_fc15.acquired", "equals": 1 }, { "expr": "g_fc15.sample_seen.value", "equals": 7 }, { "expr": "g_fc15.acquisition_saw_stimulus_after", "equals": 0 } ] } }, "task01.processed": { "event_id": "E09", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 9" }, "verify": { "expressions": [ { "expr": "g_fc15.processed", "equals": 1 }, { "expr": "g_fc15.result_seen.sum_squares", "equals": 140 } ] } }, "task01.published": { "event_id": "E10", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 10" }, "verify": { "expressions": [ { "expr": "g_fc15.published", "equals": 1 }, { "expr": "g_fc15.shared.revision", "equals": 1 }, { "expr": "g_fc15.result_ready", "equals": 1 } ] } }, "task01.stimulus-resumed": { "event_id": "E11", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 11" }, "verify": { "expressions": [ { "expr": "g_fc15.pipeline_done_at_stimulus_resume", "equals": 1 }, { "expr": "g_fc15.stimulus_after_irq", "equals": 1 } ] } }, "task01.heartbeat": { "event_id": "E12", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 12" }, "verify": { "expressions": [ { "expr": "g_fc15.heartbeat_calls", "equals": 1 }, { "expr": "g_fc15.shared.heartbeat", "equals": 1 }, { "expr": "g_fc15.heartbeat_tick == g_fc15.start_tick + 5", "equals": 1 } ] } }, "task01.diagnostics": { "event_id": "E13", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 13" }, "verify": { "expressions": [ { "expr": "(g_fc15.returned_bits & 3) == 3", "equals": 1 }, { "expr": "g_fc15.mutex_entries", "equals": 3 }, { "expr": "g_fc15.heap_before == g_fc15.heap_terminal", "equals": 1 } ] } }, "task01.pass": { "event_id": "E14", "stop": { "symbol": "fc15_checkpoint_committed", "offset": 0, "condition": "$a0 == 14" }, "verify": { "expressions": [ { "expr": "g_fc15_pass", "equals": 1 }, { "expr": "g_fc15_event_count", "equals": 14 }, { "expr": "g_fc15.snapshot.result.sum_squares", "equals": 140 } ] } } } }, "sections": [ { "title": "A1 — End-to-end responsibility boundary", "order": 10, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "Each boundary has one transport and one owner. The ISR carries no payload; the queues carry values; the event group carries readiness; the mutex protects a consistent shared snapshot.", "assets": [ { "path": "assets/a1-context.png", "html_path": "assets/a1-context.svg", "source_path": "assets/a1-context.puml", "caption": "A1 CONTEXT — device, ISR, pipeline, heartbeat and supervision.", "label": "fig:a1-context", "alt": "A1 · integrated responsibility boundary", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "device": 1, "isr": 1, "pipeline": 1, "daemon": 1, "supervisor": 1, "terminal": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a1-context", "title": "A1 · integrated responsibility boundary", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a1", "label": "A1 CONTEXT", "description": "The external device, ISR, data pipeline, timer daemon, shared publication and supervisor are independent responsibility zones." }, "phases": [ { "id": "boundary", "label": "END-TO-END BOUNDARIES", "steps": [ { "id": "device", "number": 1, "label": "input register bank owns raw sample", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "01", "code_ref": "include/task01_integration.h:28", "description": "input register bank owns raw sample", "evidence": "status, sequence, value" }, { "id": "isr", "number": 2, "label": "external ISR only clears and notifies", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:154", "description": "external ISR only clears and notifies", "evidence": "no payload copy" }, { "id": "pipeline", "number": 3, "label": "three tasks transform typed values", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:170", "description": "three tasks transform typed values", "evidence": "Sample to Result to publication" }, { "id": "daemon", "number": 4, "label": "software timer owns independent heartbeat", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:288", "description": "software timer owns independent heartbeat", "evidence": "timer daemon context" }, { "id": "supervisor", "number": 5, "label": "supervisor joins and diagnoses", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:319", "description": "supervisor joins and diagnoses", "evidence": "result plus heartbeat" }, { "id": "terminal", "number": 6, "label": "one trace proves the whole boundary", "mode": "RUN", "event_id": "E14", "strategy_ref": "run.identity", "svg_label": "06", "code_ref": "src/tasks/task01_integration.c:404", "snapshot_ref": "task01.pass", "description": "one trace proves the whole boundary", "evidence": "PASS and deterministic digest" } ] } ] } } ] }, { "title": "A2 — Typed objects and static ownership", "order": 20, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "A Sample has two words, a Result has four, and PublishedState adds revision and heartbeat. Queue storage copies the typed payload; notification and event bits never impersonate it.", "assets": [ { "path": "assets/a2-structure.png", "html_path": "assets/a2-structure.svg", "source_path": "assets/a2-structure.puml", "caption": "A2 STRUCTURE — typed messages, kernel objects and static storage.", "label": "fig:a2-structure", "alt": "A2 · static object graph", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "types": 1, "state": 1, "handles": 1, "storage": 1, "heap": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a2-structure", "title": "A2 · static object graph", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a2", "label": "A2 STRUCTURE", "description": "All application tasks and kernel objects use named static storage; payload and synchronization records remain distinct." }, "phases": [ { "id": "objects", "label": "TYPES / OBJECTS / STORAGE", "steps": [ { "id": "types", "number": 1, "label": "Sample and Result have explicit value layouts", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "01", "code_ref": "include/task01_integration_model.h:12", "description": "Sample and Result have explicit value layouts", "evidence": "2-word and 4-word payloads" }, { "id": "state", "number": 2, "label": "PublishedState is one mutex snapshot", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "02", "code_ref": "include/task01_integration_model.h:26", "description": "PublishedState is one mutex snapshot", "evidence": "result, revision, heartbeat" }, { "id": "handles", "number": 3, "label": "experiment names every task and object handle", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "03", "code_ref": "include/task01_integration.h:35", "description": "experiment names every task and object handle", "evidence": "five tasks, two queues, event, mutex, timer" }, { "id": "storage", "number": 4, "label": "TCBs, stacks and control blocks are static", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:36", "description": "TCBs, stacks and control blocks are static", "evidence": "bounded application storage" }, { "id": "heap", "number": 5, "label": "object creation leaves current heap unchanged", "mode": "RUN", "event_id": "E01", "strategy_ref": "run.startup", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:477", "snapshot_ref": "task01.configured", "description": "object creation leaves current heap unchanged", "evidence": "before equals after" } ] } ] } } ] }, { "title": "A3 — Two asynchronous bindings", "order": 30, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "FromISR notification selects acquisition immediately. The timer service later calls the heartbeat callback in task context; neither path calls the other's API family.", "assets": [ { "path": "assets/a3-dispatch.png", "html_path": "assets/a3-dispatch.svg", "source_path": "assets/a3-dispatch.puml", "caption": "A3 DISPATCH — external IRQ to acquisition and timer expiry to daemon.", "label": "fig:a3-dispatch", "alt": "A3 · IRQ and timer dispatch", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "external-vector": 1, "notify": 1, "immediate": 1, "timer-binding": 1, "heartbeat": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a3-dispatch", "title": "A3 · IRQ and timer dispatch", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a3", "label": "A3 DISPATCH", "description": "The application has two unrelated asynchronous entries: a real external ISR and a software timer callback on the daemon task." }, "phases": [ { "id": "dispatch", "label": "TWO ASYNCHRONOUS ENTRIES", "steps": [ { "id": "external-vector", "number": 1, "label": "external trap enters application ISR", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "01", "code_ref": "src/common/hazard3_freertos_traps.S:24", "description": "external trap enters application ISR", "evidence": "full context save" }, { "id": "notify", "number": 2, "label": "ISR clears and wakes acquisition", "mode": "RUN", "event_id": "E07", "strategy_ref": "run.pipeline", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:158", "snapshot_ref": "task01.irq", "description": "ISR clears and wakes acquisition", "evidence": "MEI, source zero, wake true" }, { "id": "immediate", "number": 3, "label": "acquisition runs before stimulus resumes", "mode": "RUN", "event_id": "E08", "strategy_ref": "run.pipeline", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:186", "snapshot_ref": "task01.acquired", "description": "acquisition runs before stimulus resumes", "evidence": "stimulus_after=0" }, { "id": "timer-binding", "number": 4, "label": "timer object binds one callback and context", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:491", "description": "timer object binds one callback and context", "evidence": "one-shot period five" }, { "id": "heartbeat", "number": 5, "label": "timer daemon publishes independent readiness", "mode": "RUN", "event_id": "E12", "strategy_ref": "run.rendezvous", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:297", "snapshot_ref": "task01.heartbeat", "description": "timer daemon publishes independent readiness", "evidence": "heartbeat=1 at tick+5" } ] } ] } } ] }, { "title": "A4 — Task and primitive topology", "order": 40, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "Priorities 6, 5 and 4 let the data pipeline finish before returning to stimulus priority 1. Supervisor priority 2 remains blocked until both result and heartbeat exist.", "assets": [ { "path": "assets/a4-application.png", "html_path": "assets/a4-application.svg", "source_path": "assets/a4-application.puml", "caption": "A4 APPLICATION — priorities, transports and one rendezvous.", "label": "fig:a4-application", "alt": "A4 · application topology", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "acq-ready": 1, "proc-ready": 1, "pub-ready": 1, "supervisor-ready": 1, "heartbeat-role": 1, "stimulus-role": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a4-application", "title": "A4 · application topology", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a4", "label": "A4 APPLICATION", "description": "Five application tasks and the timer daemon form one acyclic data path plus one independent control path." }, "phases": [ { "id": "topology", "label": "TASK / OBJECT TOPOLOGY", "steps": [ { "id": "acq-ready", "number": 1, "label": "acquisition priority 6 waits on notification", "mode": "RUN", "event_id": "E02", "strategy_ref": "run.startup", "svg_label": "01", "code_ref": "src/tasks/task01_integration.c:179", "snapshot_ref": "task01.acquisition-ready", "description": "acquisition priority 6 waits on notification", "evidence": "one-to-one wake" }, { "id": "proc-ready", "number": 2, "label": "processor priority 5 waits on Sample queue", "mode": "RUN", "event_id": "E03", "strategy_ref": "run.startup", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:217", "snapshot_ref": "task01.processor-ready", "description": "processor priority 5 waits on Sample queue", "evidence": "typed copy" }, { "id": "pub-ready", "number": 3, "label": "publisher priority 4 waits on Result queue", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.startup", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:256", "snapshot_ref": "task01.publisher-ready", "description": "publisher priority 4 waits on Result queue", "evidence": "typed copy" }, { "id": "supervisor-ready", "number": 4, "label": "supervisor waits for both event bits", "mode": "RUN", "event_id": "E05", "strategy_ref": "run.startup", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:327", "snapshot_ref": "task01.supervisor-ready", "description": "supervisor waits for both event bits", "evidence": "ALL mask" }, { "id": "heartbeat-role", "number": 5, "label": "daemon priority 3 provides heartbeat", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "05", "code_ref": "include/FreeRTOSConfig.h:26", "description": "daemon priority 3 provides heartbeat", "evidence": "independent control path" }, { "id": "stimulus-role", "number": 6, "label": "stimulus priority 1 injects one input", "mode": "RUN", "event_id": "E06", "strategy_ref": "run.pipeline", "svg_label": "06", "code_ref": "src/tasks/task01_integration.c:430", "snapshot_ref": "task01.input-ready", "description": "stimulus priority 1 injects one input", "evidence": "sequence 42, value 7" } ] } ] } } ] }, { "title": "A5 — Fourteen-event replay", "order": 50, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "E07–E11 prove that notification plus strict priorities complete acquisition, calculation and publication before the interrupted stimulus resumes. E12–E14 prove the independent rendezvous and deadline.", "assets": [ { "path": "assets/a5-flow.png", "html_path": "assets/a5-flow.svg", "source_path": "assets/a5-flow.puml", "caption": "A5 FLOW — E01–E14 from static configuration to PASS.", "label": "fig:a5-flow", "alt": "A5 · integrated deterministic replay", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "e01": 1, "e02": 1, "e03": 1, "e04": 1, "e05": 1, "e06": 1, "e07": 1, "e08": 1, "e09": 1, "e10": 1, "e11": 1, "e12": 1, "e13": 1, "e14": 1 } }, "interactive": { "kind": "uml-sequence", "storage_key": "fc15-a5-flow", "title": "A5 · integrated deterministic replay", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a5", "label": "A5 FLOW", "description": "The trace separates startup, the immediate IRQ-driven data chain, delayed heartbeat and final diagnostic terminal." }, "phases": [ { "id": "startup", "label": "STARTUP E01–E06", "steps": [ { "id": "e01", "number": 1, "label": "static objects and timer configured", "mode": "RUN", "event_id": "E01", "strategy_ref": "run.startup", "svg_label": "01", "code_ref": "src/tasks/task01_integration.c:475", "snapshot_ref": "task01.configured", "description": "static objects and timer configured", "evidence": "heap delta zero" }, { "id": "e02", "number": 2, "label": "acquisition blocks", "mode": "RUN", "event_id": "E02", "strategy_ref": "run.startup", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:180", "snapshot_ref": "task01.acquisition-ready", "description": "acquisition blocks", "evidence": "priority 6" }, { "id": "e03", "number": 3, "label": "processor blocks", "mode": "RUN", "event_id": "E03", "strategy_ref": "run.startup", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:218", "snapshot_ref": "task01.processor-ready", "description": "processor blocks", "evidence": "priority 5" }, { "id": "e04", "number": 4, "label": "publisher blocks", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.startup", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:257", "snapshot_ref": "task01.publisher-ready", "description": "publisher blocks", "evidence": "priority 4" }, { "id": "e05", "number": 5, "label": "supervisor waits ALL", "mode": "RUN", "event_id": "E05", "strategy_ref": "run.startup", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:328", "snapshot_ref": "task01.supervisor-ready", "description": "supervisor waits ALL", "evidence": "mask 0x3" }, { "id": "e06", "number": 6, "label": "stimulus publishes input", "mode": "RUN", "event_id": "E06", "strategy_ref": "run.pipeline", "svg_label": "06", "code_ref": "src/tasks/task01_integration.c:432", "snapshot_ref": "task01.input-ready", "description": "stimulus publishes input", "evidence": "42 and 7" } ] }, { "id": "runtime", "label": "PIPELINE E07–E14", "steps": [ { "id": "e07", "number": 7, "label": "ISR notifies acquisition", "mode": "RUN", "event_id": "E07", "strategy_ref": "run.pipeline", "svg_label": "07", "code_ref": "src/tasks/task01_integration.c:162", "snapshot_ref": "task01.irq", "description": "ISR notifies acquisition", "evidence": "wake true" }, { "id": "e08", "number": 8, "label": "acquisition queues Sample", "mode": "RUN", "event_id": "E08", "strategy_ref": "run.pipeline", "svg_label": "08", "code_ref": "src/tasks/task01_integration.c:192", "snapshot_ref": "task01.acquired", "description": "acquisition queues Sample", "evidence": "value 7" }, { "id": "e09", "number": 9, "label": "processor queues Result", "mode": "RUN", "event_id": "E09", "strategy_ref": "run.pipeline", "svg_label": "09", "code_ref": "src/tasks/task01_integration.c:225", "snapshot_ref": "task01.processed", "description": "processor queues Result", "evidence": "sum 140" }, { "id": "e10", "number": 10, "label": "publisher commits result bit", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.pipeline", "svg_label": "10", "code_ref": "src/tasks/task01_integration.c:266", "snapshot_ref": "task01.published", "description": "publisher commits result bit", "evidence": "revision 1" }, { "id": "e11", "number": 11, "label": "stimulus resumes after pipeline", "mode": "RUN", "event_id": "E11", "strategy_ref": "run.pipeline", "svg_label": "11", "code_ref": "src/tasks/task01_integration.c:442", "snapshot_ref": "task01.stimulus-resumed", "description": "stimulus resumes after pipeline", "evidence": "result already ready" }, { "id": "e12", "number": 12, "label": "daemon commits heartbeat bit", "mode": "RUN", "event_id": "E12", "strategy_ref": "run.rendezvous", "svg_label": "12", "code_ref": "src/tasks/task01_integration.c:299", "snapshot_ref": "task01.heartbeat", "description": "daemon commits heartbeat bit", "evidence": "tick +5" }, { "id": "e13", "number": 13, "label": "supervisor joins and measures", "mode": "RUN", "event_id": "E13", "strategy_ref": "run.rendezvous", "svg_label": "13", "code_ref": "src/tasks/task01_integration.c:332", "snapshot_ref": "task01.diagnostics", "description": "supervisor joins and measures", "evidence": "bits, heap, HWM" }, { "id": "e14", "number": 14, "label": "all contracts reach PASS", "mode": "RUN", "event_id": "E14", "strategy_ref": "run.identity", "svg_label": "14", "code_ref": "src/tasks/task01_integration.c:404", "snapshot_ref": "task01.pass", "description": "all contracts reach PASS", "evidence": "digest 8f767299" } ] } ] } } ] }, { "title": "A6 — Data, readiness and lifetime states", "order": 60, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "Queues become empty after each transfer; the shared state becomes valid at revision one; the event group releases only after both independent bits are present and then clears them on exit.", "assets": [ { "path": "assets/a6-state.png", "html_path": "assets/a6-state.svg", "source_path": "assets/a6-state.puml", "caption": "A6 STATE — device, queues, shared state and ALL-bit rendezvous.", "label": "fig:a6-state", "alt": "A6 · integrated state machine", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "device-ready": 1, "sample-copy": 1, "result-copy": 1, "result-bit": 1, "both-bits": 1, "snapshot": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a6-state", "title": "A6 · integrated state machine", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a6", "label": "A6 STATE", "description": "Payload lifetime, task blocking and readiness bits evolve on separate state axes." }, "phases": [ { "id": "state", "label": "STATE AXES", "steps": [ { "id": "device-ready", "number": 1, "label": "device changes empty to ready", "mode": "RUN", "event_id": "E06", "strategy_ref": "run.pipeline", "svg_label": "01", "code_ref": "src/tasks/task01_integration.c:435", "snapshot_ref": "task01.input-ready", "description": "device changes empty to ready", "evidence": "status=1" }, { "id": "sample-copy", "number": 2, "label": "Sample queue transfers and returns empty", "mode": "RUN", "event_id": "E08", "strategy_ref": "run.pipeline", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:192", "snapshot_ref": "task01.acquired", "description": "Sample queue transfers and returns empty", "evidence": "acquired=1" }, { "id": "result-copy", "number": 3, "label": "Result queue transfers and returns empty", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.pipeline", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:258", "snapshot_ref": "task01.published", "description": "Result queue transfers and returns empty", "evidence": "published=1" }, { "id": "result-bit", "number": 4, "label": "result bit waits for heartbeat bit", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.pipeline", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:276", "snapshot_ref": "task01.published", "description": "result bit waits for heartbeat bit", "evidence": "mask incomplete" }, { "id": "both-bits", "number": 5, "label": "heartbeat completes ALL mask", "mode": "RUN", "event_id": "E12", "strategy_ref": "run.rendezvous", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:311", "snapshot_ref": "task01.heartbeat", "description": "heartbeat completes ALL mask", "evidence": "mask 0x3" }, { "id": "snapshot", "number": 6, "label": "supervisor locks one complete snapshot", "mode": "RUN", "event_id": "E13", "strategy_ref": "run.rendezvous", "svg_label": "06", "code_ref": "src/tasks/task01_integration.c:338", "snapshot_ref": "task01.diagnostics", "description": "supervisor locks one complete snapshot", "evidence": "three mutex entries" } ] } ] } } ] }, { "title": "A7 — Deadline, memory and context proof", "order": 70, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "All application objects are static, so current heap is equal before creation, after creation and at the terminal. Historical minimum remains a separate diagnostic value.", "assets": [ { "path": "assets/a7-runtime.png", "html_path": "assets/a7-runtime.svg", "source_path": "assets/a7-runtime.puml", "caption": "A7 RUNTIME — cause, timing, heap, stacks and artifact identity.", "label": "fig:a7-runtime", "alt": "A7 · final 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, "ordering": 1, "deadline": 1, "heap": 1, "watermarks": 1, "abi": 1, "digest": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a7-runtime", "title": "A7 · final runtime proof", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a7", "label": "A7 RUNTIME", "description": "The terminal connects hardware cause, scheduling order, queue state, stack watermarks, heap invariance and exact artifact identity." }, "phases": [ { "id": "runtime", "label": "RUNTIME ACCEPTANCE", "steps": [ { "id": "cause", "number": 1, "label": "real MEI uses separate ISR stack", "mode": "RUN", "event_id": "E07", "strategy_ref": "run.pipeline", "svg_label": "01", "code_ref": "src/tasks/task01_integration.c:158", "snapshot_ref": "task01.irq", "description": "real MEI uses separate ISR stack", "evidence": "0x8000000b" }, { "id": "ordering", "number": 2, "label": "pipeline finishes before ISR return target resumes", "mode": "RUN", "event_id": "E11", "strategy_ref": "run.pipeline", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:443", "snapshot_ref": "task01.stimulus-resumed", "description": "pipeline finishes before ISR return target resumes", "evidence": "done=1" }, { "id": "deadline", "number": 3, "label": "heartbeat and completion stay within eight ticks", "mode": "RUN", "event_id": "E13", "strategy_ref": "run.rendezvous", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:349", "snapshot_ref": "task01.diagnostics", "description": "heartbeat and completion stay within eight ticks", "evidence": "completion tick <= start+8" }, { "id": "heap", "number": 4, "label": "static app objects preserve current heap", "mode": "RUN", "event_id": "E13", "strategy_ref": "run.rendezvous", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:351", "snapshot_ref": "task01.diagnostics", "description": "static app objects preserve current heap", "evidence": "three equal heap readings" }, { "id": "watermarks", "number": 5, "label": "six task contexts retain positive HWM", "mode": "RUN", "event_id": "E14", "strategy_ref": "run.identity", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:392", "snapshot_ref": "task01.pass", "description": "six task contexts retain positive HWM", "evidence": "acq/proc/pub/sup/stim/daemon" }, { "id": "abi", "number": 6, "label": "ELF requires every selected primitive", "mode": "CODE", "strategy_ref": "code.identity", "svg_label": "06", "code_ref": "scripts/check_abi.sh:18", "description": "ELF requires every selected primitive", "evidence": "C only; exact symbols" }, { "id": "digest", "number": 7, "label": "three clean images agree", "mode": "RUN", "event_id": "E14", "strategy_ref": "run.identity", "svg_label": "07", "code_ref": "scripts/check_determinism.sh:14", "snapshot_ref": "task01.pass", "description": "three clean images agree", "evidence": "8f767299" } ] } ] } } ] }, { "title": "A8 — Smallest justified mechanism", "order": 80, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "portrait", "content_tex": "Notification carries a one-to-one wake, queues carry typed values, mutex protects a multi-writer snapshot, event bits join independent conditions, and the software timer supplies time-based control work.", "assets": [ { "path": "assets/a8-patterns.png", "html_path": "assets/a8-patterns.svg", "source_path": "assets/a8-patterns.puml", "caption": "A8 PATTERNS — choose by payload, fan-in, ownership and time.", "label": "fig:a8-patterns", "alt": "A8 · mechanism selection map", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 660, "page_height": 760, "overview": true, "step_tiles": { "notification": 1, "queue": 1, "mutex": 1, "event-group": 1, "timer": 1, "proof": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc15-a8-patterns", "title": "A8 · mechanism selection map", "task": { "id": "task01", "label": "Task01 · integrated deterministic application" }, "block": { "id": "a8", "label": "A8 PATTERNS", "description": "The architecture uses several primitives because each solves a different ownership problem, not because every learned API must appear." }, "phases": [ { "id": "choices", "label": "PROBLEM → SMALLEST MECHANISM", "steps": [ { "id": "notification", "number": 1, "label": "one ISR wakes one acquisition task", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "01", "code_ref": "src/tasks/task01_integration.c:162", "description": "one ISR wakes one acquisition task", "evidence": "notification; no payload" }, { "id": "queue", "number": 2, "label": "typed ownership crosses task boundaries", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "02", "code_ref": "src/tasks/task01_integration.c:192", "description": "typed ownership crosses task boundaries", "evidence": "two value queues" }, { "id": "mutex", "number": 3, "label": "two writers build one consistent snapshot", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "03", "code_ref": "src/tasks/task01_integration.c:261", "description": "two writers build one consistent snapshot", "evidence": "publisher and daemon" }, { "id": "event-group", "number": 4, "label": "supervisor joins independent conditions", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "04", "code_ref": "src/tasks/task01_integration.c:332", "description": "supervisor joins independent conditions", "evidence": "wait ALL" }, { "id": "timer", "number": 5, "label": "control work is scheduled by time", "mode": "CODE", "strategy_ref": "code.architecture", "svg_label": "05", "code_ref": "src/tasks/task01_integration.c:491", "description": "control work is scheduled by time", "evidence": "one-shot heartbeat" }, { "id": "proof", "number": 6, "label": "one terminal validates all choices together", "mode": "RUN", "event_id": "E14", "strategy_ref": "run.identity", "svg_label": "06", "code_ref": "src/tasks/task01_integration.c:358", "snapshot_ref": "task01.pass", "description": "one terminal validates all choices together", "evidence": "no redundant transport" } ] } ] } } ] }, { "title": "Task01 — integrated deterministic application", "order": 90, "content_kind": "tasks", "task_refs": [ "task01" ] } ], "tasks": { "task01": { "title": "Prove one complete FreeRTOS C architecture", "uuid": "fe92efeb-3c38-5975-86d8-ed630e1ad3bb", "prompt_tex": "Odtwórz E01--E14 i dla każdego mechanizmu zapisz jedną odpowiedzialność. Następnie udowodnij ciąg input 7, suma kwadratów 140, publikacja, heartbeat w ticku 5 i terminal przed tickiem 8.", "criterion": "PASS; real MEI; pipeline before stimulus resume; sum 140; result and heartbeat ALL-mask; completion by tick 8; zero application heap delta; positive stack HWM; deterministic digest.", "conclusion_tex": "Poprawna architektura RTOS nie maksymalizuje liczby prymitywów. Każdy obiekt ma rozwiązywać inną granicę własności lub synchronizacji, a cały wybór musi być widoczny w jednym mierzalnym śladzie.", "flow": [ { "kind": "block", "id": "architecture", "title": "A — architektura", "content_tex": "Przypisz każdemu prymitywowi dokładnie jedną rolę.", "steps": [ { "id": "owners", "title": "Zapisz tabelę własności.", "content_tex": "Payload, wake, shared snapshot, fan-in i time trigger nie są tym samym." }, { "id": "predict", "title": "Przewidź E07--E12.", "content_tex": "Użyj priorytetów 6, 5, 4, 3, 2 i 1 do wyznaczenia kolejności." } ] }, { "kind": "block", "id": "replay", "title": "B — replay", "content_tex": "Zbierz jeden spójny dowód od sprzętu do diagnostyki.", "steps": [ { "id": "startup", "title": "Sprawdź E01--E06.", "content_tex": "Statyczna pamięć, taski zablokowane i input gotowy." }, { "id": "pipeline", "title": "Sprawdź E07--E11.", "content_tex": "IRQ, notification, dwie kolejki, wynik i natychmiastowy chain." }, { "id": "health", "title": "Sprawdź E12--E14.", "content_tex": "Timer daemon, mutex, ALL-mask, deadline, HWM, heap i digest." } ] }, { "kind": "exercise", "id": "policy", "title": "Ćwiczenie — zmiana polityki", "prompt_tex": "Zmień wejście z 7 na 9 bez zmiany topologii. Wyznacz nową sumę kwadratów i checksum, zachowaj heartbeat oraz wszystkie kontrakty pamięci i kolejności.", "evidence_tex": "Nowy typed payload, przewidywany Result, E06/E09/E10/E14 oraz niezmienione heap, HWM i deadline gates.", "criterion": "Zmienia się wyłącznie polityka danych; architektura, własność, liczba zdarzeń i bramki bezpieczeństwa pozostają spójne.", "based_on": [ "architecture", "replay" ] } ], "educational_requirement_refs": [ "FC15.WE01" ], "learning_effect_refs": [ "FC15.EN01", "FC15.EK01" ], "assessment_criterion_ref": "FC15.KW01" } }, "tasks_order": [ "task01" ] }