Files

1439 lines
49 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "../../../tools/card-layouts/schemas/card-source.schema.json",
"schema": "esc-card-source.v1",
"card": {
"id": "mpabi-freertos-c-14-gpio-timer-deferred",
"series": "freertos-c",
"series_title": "FreeRTOS C",
"number": "14",
"count": "15",
"slug": "gpio-timer-deferred",
"title": "GPIO, hardware timer and deferred work",
"topic": "mtime tick ISR, pended daemon callback and one bounded GPIO transition",
"project": "Freestanding C nad FreeRTOS",
"subject": "Informatyka",
"level": "Rok 2 · L14 · RV32I/Hazard3",
"revision_date": "2026-07-19T00:00:00+02:00",
"status": "Gotowa",
"version": "v00.01",
"uuid": "7de92b94-df89-5c00-be47-d85523ad02ac",
"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": "hardware/ISR/daemon boundary",
"status": "enabled",
"target_label": "fig:a1-context"
},
{
"id": "A2",
"label": "STRUCTURE",
"subtitle": "event and register records",
"status": "enabled",
"target_label": "fig:a2-structure"
},
{
"id": "A3",
"label": "DISPATCH",
"subtitle": "pended callback binding",
"status": "enabled",
"target_label": "fig:a3-dispatch"
},
{
"id": "A4",
"label": "APPLICATION",
"subtitle": "single event topology",
"status": "unavailable",
"reason": "A1 already identifies every application participant and A5 provides the complete concrete topology in time."
},
{
"id": "A5",
"label": "FLOW",
"subtitle": "E01-E06 hardware replay",
"status": "enabled",
"target_label": "fig:a5-flow"
},
{
"id": "A6",
"label": "STATE",
"subtitle": "pending and applied states",
"status": "enabled",
"target_label": "fig:a6-state"
},
{
"id": "A7",
"label": "RUNTIME",
"subtitle": "mtime, stacks and ELF",
"status": "enabled",
"target_label": "fig:a7-runtime"
},
{
"id": "A8",
"label": "PATTERNS",
"subtitle": "deferred interrupt processing",
"status": "unavailable",
"reason": "Deferred interrupt processing is the mechanism proved in A3 and A6; a separate page would repeat the same decision."
}
],
"debug_strategies": {
"code.contract": {
"id": "code.contract",
"kind": "code",
"action": "open",
"expected_observations": [
"ISR and callback are separate functions",
"one GPIO owner"
],
"assertions": [
"hook never blocks",
"callback arguments outlive the ISR"
],
"evidence_fields": [
"code_ref",
"priority",
"register",
"API"
],
"prerequisites": [
"FC06 and FC07 complete"
],
"layout": [
"mtime port",
"tick hook",
"timer queue",
"daemon callback",
"GPIO"
],
"commands": [
"rg -n 'TickHook|PendFunction|MTIME|gpio' include src Makefile"
]
},
"run.timer": {
"id": "run.timer",
"kind": "run",
"action": "replay",
"expected_observations": [
"E03 at target tick",
"pend returns pdPASS and wake true"
],
"assertions": [
"mcause is MTI",
"compare was reloaded",
"one command accepted"
],
"evidence_fields": [
"tick",
"mtime",
"mtimecmp",
"mcause",
"pend result",
"ISR SP"
],
"prerequisites": [
"clean Hazard3 RAM",
"target tick armed"
],
"layout": [
"mtime",
"mtimecmp",
"mcause",
"timer command queue"
],
"commands": [
"make sim",
"print g_fc14",
"print g_fc14_events"
]
},
"run.daemon": {
"id": "run.daemon",
"kind": "run",
"action": "replay",
"expected_observations": [
"callback at same tick",
"GPIO low-to-high once"
],
"assertions": [
"daemon handle matches",
"E04 precedes E05",
"callback stack differs from ISR"
],
"evidence_fields": [
"TaskHandle_t",
"SP",
"tick",
"GPIO before/after",
"transition count"
],
"prerequisites": [
"E03 command queued",
"daemon priority 3"
],
"layout": [
"daemon handle",
"callback arguments",
"GPIO bank",
"event order"
],
"commands": [
"break fc14_checkpoint_committed if $a0 == 4",
"print g_fc14"
]
},
"code.identity": {
"id": "code.identity",
"kind": "code",
"action": "open",
"expected_observations": [
"all C boundaries are linked",
"no C++ metadata"
],
"assertions": [
"timer task implementation is present",
"pended function API is present"
],
"evidence_fields": [
"symbol",
"source blob",
"ELF SHA256",
"image SHA256"
],
"prerequisites": [
"built ELF"
],
"layout": [
"trap",
"tick",
"timer daemon",
"application symbols"
],
"commands": [
"make check-abi",
"riscv64-unknown-elf-nm build/task01_gpio_timer/prog.elf"
]
},
"run.identity": {
"id": "run.identity",
"kind": "run",
"action": "replay",
"expected_observations": [
"one PASS",
"digest bf66bc48 three times"
],
"assertions": [
"six ordered events",
"exactly one GPIO transition"
],
"evidence_fields": [
"digest",
"event count",
"SP values",
"artifact identity"
],
"prerequisites": [
"built image"
],
"layout": [
"six-event trace",
"three clean processes"
],
"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": "GPIO, hardware timer and deferred work",
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/0cc561df-bf81-5bba-9df1-c872d5b42eb8",
"repository_url": "https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-c-gpio-timer",
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
"url_domain": "mpabi.pl",
"doc_uuid": "0cc561df-bf81-5bba-9df1-c872d5b42eb8",
"revision": "v00.01",
"issued_on": "2026-07-19T00:00:00+02:00",
"series": "FREERTOS-C-14",
"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ń odróżnia hardware timer interrupt od callbacku software timera: ISR tylko zatwierdza zdarzenie i odkłada pracę, a timer daemon wykonuje ograniczoną zmianę GPIO.",
"scope_title": "Zakres karty",
"scope_content_tex": "Stimulus uzbraja tick +3. Machine timer ISR zapisuje mtime, mtimecmp, mcause i stos, po czym wywołuje xTimerPendFunctionCallFromISR. Daemon priority 3 przełącza GPIO przed powrotem do przerwanego taska priority 2.",
"scope_table": {
"headers": [
"Lekcja",
"Task",
"Najważniejsza idea",
"Priorytet",
"Status",
"Version"
],
"rows": [
{
"chapter": "FC14",
"task": "Task01",
"idea_tex": "mtime tick ISR, pended daemon callback and one bounded GPIO transition",
"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": {
"FC14.EN01": {
"bloom_level": "Analiza",
"label": "Hardware timer versus deferred callback",
"text": "Uczeń rozdziela machine timer ISR, tick hook, timer command queue, daemon task and GPIO owner.",
"assessment_criteria": [
"FC14.KW01"
]
},
"FC14.EK01": {
"bloom_level": "Zastosowanie",
"label": "One-event deferred-work replay",
"text": "Uczeń odtwarza E01E06 i dowodzi kolejności ISR → daemon → interrupted task.",
"assessment_criteria": [
"FC14.KW01"
]
}
},
"assessment_criteria": {
"FC14.KW01": {
"text": "PASS; mcause=MTI; mtimecmp>mtime; one successful pend; daemon callback in target tick; one GPIO transition; three distinct stacks; deterministic digest.",
"learning_effects": [
"FC14.EN01",
"FC14.EK01"
]
}
},
"educational_requirements": {
"FC14.WE01": {
"text": "Projektowanie i badanie deferred interrupt processing dla timera sprzętowego i GPIO w FreeRTOS C.",
"label": "mtime tick ISR, pended daemon callback and one bounded GPIO transition",
"learning_effects": [
"FC14.EN01",
"FC14.EK01"
],
"learning_tree": {
"schema": "we-learning-tree.v1",
"policy": "Każda aktywna kotwica wskazuje kod lub checkpoint.",
"ogolne": [
{
"effect_ref": "FC14.EN01",
"display": "EN LOCAL RTOS.14",
"source": "LOCAL",
"official": "RTOS",
"local": "14",
"kind": "EN",
"tree_id": "FC14.WE01.OG.LOCAL.RTOS.14",
"text": "Uczeń rozdziela machine timer ISR, tick hook, timer command queue, daemon task and GPIO owner.",
"kw": [
{
"criterion_ref": "FC14.KW01",
"display": "KW LOCAL RTOS.14",
"source": "LOCAL",
"kind": "KW",
"official": "RTOS",
"local": "14",
"text": "Łączy kod, diagram i zweryfikowany dowód."
}
]
}
],
"zawodowe": [
{
"effect_ref": "FC14.EK01",
"display": "EK LOCAL RTOS.14",
"source": "LOCAL",
"official": "RTOS",
"local": "14",
"kind": "EK",
"tree_id": "FC14.WE01.TECH.LOCAL.RTOS.14",
"text": "Uczeń odtwarza E01E06 i dowodzi kolejności ISR → daemon → interrupted task.",
"kw": [
{
"criterion_ref": "FC14.KW01",
"display": "KW LOCAL RTOS.14",
"source": "LOCAL",
"kind": "KW",
"official": "RTOS",
"local": "14",
"text": "Łączy kod, diagram i zweryfikowany dowód."
}
]
}
]
}
}
},
"debug_checkpoints": {
"schema": "stem-debug-checkpoints.v1",
"semantics": "deterministic-replay",
"artifact": {
"source": "src/tasks/task01_gpio_timer.c",
"source_git_blob": "ec2e552d61694b31bbe65af1ec361442980de23b",
"elf": "build/task01_gpio_timer/prog.elf",
"hazard3_elf_sha256": "dde14e1ccc2ad816883b45a7cd9a1b431f157c1509abe02b9f6559e53365d619",
"hazard3_image": "build/task01_gpio_timer/prog.bin",
"hazard3_image_sha256": "3ffeec5e5e362efdd714ef9d354b1e3592a183bda582c6fb21be63736fb7a92d"
},
"targets": {
"hazard3-sim": {
"adapter": "hazard3-reset-load-replay.v1",
"baseline": "restart-backend",
"clean_ram": true
}
},
"items": {
"task01.configured": {
"event_id": "E01",
"stop": {
"symbol": "fc14_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 1"
},
"verify": {
"expressions": [
{
"expr": "g_fc14_event_count",
"equals": 1
},
{
"expr": "g_fc14.gpio.direction",
"equals": 1
},
{
"expr": "g_fc14_events[0].value",
"equals": 3
}
]
}
},
"task01.armed": {
"event_id": "E02",
"stop": {
"symbol": "fc14_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 2"
},
"verify": {
"expressions": [
{
"expr": "g_fc14.armed",
"equals": 1
},
{
"expr": "g_fc14.pended",
"equals": 0
},
{
"expr": "g_fc14.target_tick == g_fc14_events[1].value",
"equals": 1
}
]
}
},
"task01.tick-isr": {
"event_id": "E03",
"stop": {
"symbol": "fc14_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 3"
},
"verify": {
"expressions": [
{
"expr": "g_fc14.mcause",
"equals": 2147483655
},
{
"expr": "g_fc14.pend_result",
"equals": 1
},
{
"expr": "g_fc14.higher_priority_task_woken",
"equals": 1
},
{
"expr": "g_fc14.mtimecmp_after_reload > g_fc14.mtime_at_isr",
"equals": 1
}
]
}
},
"task01.callback": {
"event_id": "E04",
"stop": {
"symbol": "fc14_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 4"
},
"verify": {
"expressions": [
{
"expr": "g_fc14.callback_calls",
"equals": 1
},
{
"expr": "g_fc14.gpio.data",
"equals": 1
},
{
"expr": "g_fc14.gpio.transitions",
"equals": 1
},
{
"expr": "g_fc14.callback_saw_stimulus_after",
"equals": 0
}
]
}
},
"task01.stimulus-resumed": {
"event_id": "E05",
"stop": {
"symbol": "fc14_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 5"
},
"verify": {
"expressions": [
{
"expr": "g_fc14.applied_at_stimulus_resume",
"equals": 1
},
{
"expr": "g_fc14.stimulus_after",
"equals": 1
}
]
}
},
"task01.pass": {
"event_id": "E06",
"stop": {
"symbol": "fc14_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 6"
},
"verify": {
"expressions": [
{
"expr": "g_fc14_pass",
"equals": 1
},
{
"expr": "g_fc14_event_count",
"equals": 6
},
{
"expr": "g_fc14.pend_calls",
"equals": 1
},
{
"expr": "g_fc14.callback_calls",
"equals": 1
}
]
}
}
}
},
"sections": [
{
"title": "A1 — Hardware, ISR and daemon boundary",
"order": 10,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "The hardware interrupt only records and defers. GPIO changes later in task context; this is not a software-timer expiry callback.",
"assets": [
{
"path": "assets/a1-context.png",
"html_path": "assets/a1-context.svg",
"source_path": "assets/a1-context.puml",
"caption": "A1 CONTEXT — mtime, tick ISR, pend queue, daemon and GPIO.",
"label": "fig:a1-context",
"alt": "A1 · hardware-to-deferred-work boundary",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"mtime": 1,
"port": 1,
"hook": 1,
"daemon": 1,
"gpio": 1,
"pass": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc14-a1-context",
"title": "A1 · hardware-to-deferred-work boundary",
"task": {
"id": "task01",
"label": "Task01 · hardware timer to deferred GPIO"
},
"block": {
"id": "a1",
"label": "A1 CONTEXT",
"description": "The machine timer, kernel tick path, application hook, timer queue, daemon task and GPIO register bank have separate roles."
},
"phases": [
{
"id": "boundary",
"label": "HARDWARE / ISR / DAEMON",
"steps": [
{
"id": "mtime",
"number": 1,
"label": "mtime and mtimecmp generate the kernel tick",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "include/FreeRTOSConfig.h:4",
"description": "mtime and mtimecmp generate the kernel tick",
"evidence": "10 MHz clock, 1 kHz tick"
},
{
"id": "port",
"number": 2,
"label": "port reloads compare and increments tick",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "02",
"code_ref": "vendor/FreeRTOS-Kernel/portable/GCC/RISC-V/portASM.S:368",
"description": "port reloads compare and increments tick",
"evidence": "machine timer trap"
},
{
"id": "hook",
"number": 3,
"label": "tick hook accepts exactly one target event",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "03",
"code_ref": "src/tasks/task01_gpio_timer.c:97",
"description": "tick hook accepts exactly one target event",
"evidence": "minimal ISR path"
},
{
"id": "daemon",
"number": 4,
"label": "pended function runs on timer daemon",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "04",
"code_ref": "src/tasks/task01_gpio_timer.c:127",
"description": "pended function runs on timer daemon",
"evidence": "task context"
},
{
"id": "gpio",
"number": 5,
"label": "daemon owns the GPIO transition",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "05",
"code_ref": "include/task01_gpio_timer_model.h:32",
"description": "daemon owns the GPIO transition",
"evidence": "exactly one toggle"
},
{
"id": "pass",
"number": 6,
"label": "runtime proves every boundary",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.identity",
"svg_label": "06",
"code_ref": "src/tasks/task01_gpio_timer.c:202",
"snapshot_ref": "task01.pass",
"description": "runtime proves every boundary",
"evidence": "PASS and deterministic digest"
}
]
}
]
}
}
]
},
{
"title": "A2 — Event and register records",
"order": 20,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "The callback receives a pointer and a 32-bit event value through the timer command queue. It does not capture ISR stack storage.",
"assets": [
{
"path": "assets/a2-structure.png",
"html_path": "assets/a2-structure.svg",
"source_path": "assets/a2-structure.puml",
"caption": "A2 STRUCTURE — experiment, command, GPIO and evidence records.",
"label": "fig:a2-structure",
"alt": "A2 · deferred event storage",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"experiment": 1,
"gpio-record": 1,
"event-record": 1,
"command": 1,
"identity": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc14-a2-structure",
"title": "A2 · deferred event storage",
"task": {
"id": "task01",
"label": "Task01 · hardware timer to deferred GPIO"
},
"block": {
"id": "a2",
"label": "A2 STRUCTURE",
"description": "One bounded experiment record connects hardware time, trap state, daemon identity, GPIO values and six commit-last events."
},
"phases": [
{
"id": "storage",
"label": "RECORDS AND OWNERSHIP",
"steps": [
{
"id": "experiment",
"number": 1,
"label": "experiment stores timing and context proof",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "include/task01_gpio_timer.h:20",
"description": "experiment stores timing and context proof",
"evidence": "ticks, mtime, SP and result"
},
{
"id": "gpio-record",
"number": 2,
"label": "volatile GPIO bank stores direction and data",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "02",
"code_ref": "include/task01_gpio_timer_model.h:10",
"description": "volatile GPIO bank stores direction and data",
"evidence": "transition counter"
},
{
"id": "event-record",
"number": 3,
"label": "six evidence records commit last",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "03",
"code_ref": "include/task01_gpio_timer_model.h:17",
"description": "six evidence records commit last",
"evidence": "sequence, actor and tick"
},
{
"id": "command",
"number": 4,
"label": "timer queue copies callback and arguments",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "04",
"code_ref": "vendor/FreeRTOS-Kernel/timers.c:1233",
"description": "timer queue copies callback and arguments",
"evidence": "daemon command message"
},
{
"id": "identity",
"number": 5,
"label": "callback handle equals timer daemon handle",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.daemon",
"svg_label": "05",
"code_ref": "src/tasks/task01_gpio_timer.c:135",
"snapshot_ref": "task01.callback",
"description": "callback handle equals timer daemon handle",
"evidence": "same TaskHandle_t"
}
]
}
]
}
}
]
},
{
"title": "A3 — Pended-function dispatch",
"order": 30,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "The port restores the daemon task before the interrupted stimulus continues. The callback and ISR therefore have different stacks and API permissions.",
"assets": [
{
"path": "assets/a3-dispatch.png",
"html_path": "assets/a3-dispatch.svg",
"source_path": "assets/a3-dispatch.puml",
"caption": "A3 DISPATCH — MTI, tick hook, timer queue and daemon restore.",
"label": "fig:a3-dispatch",
"alt": "A3 · timer-to-daemon dispatch",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"trap": 1,
"reload": 1,
"pend": 1,
"yield": 1,
"callback": 1,
"resume": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc14-a3-dispatch",
"title": "A3 · timer-to-daemon dispatch",
"task": {
"id": "task01",
"label": "Task01 · hardware timer to deferred GPIO"
},
"block": {
"id": "a3",
"label": "A3 DISPATCH",
"description": "A real machine timer trap reaches the tick hook, which queues one function and requests a switch to the higher-priority timer daemon."
},
"phases": [
{
"id": "dispatch",
"label": "MTI / PEND / RESTORE",
"steps": [
{
"id": "trap",
"number": 1,
"label": "machine timer enters full trap path",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "vendor/FreeRTOS-Kernel/portable/GCC/RISC-V/portASM.S:368",
"description": "machine timer enters full trap path",
"evidence": "mcause timer interrupt"
},
{
"id": "reload",
"number": 2,
"label": "port reloads mtimecmp before hook",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "02",
"code_ref": "vendor/FreeRTOS-Kernel/portable/GCC/RISC-V/portASM.S:377",
"description": "port reloads mtimecmp before hook",
"evidence": "next compare is in the future"
},
{
"id": "pend",
"number": 3,
"label": "hook records and pends one callback",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.timer",
"svg_label": "03",
"code_ref": "src/tasks/task01_gpio_timer.c:109",
"snapshot_ref": "task01.tick-isr",
"description": "hook records and pends one callback",
"evidence": "pdPASS and wake=true"
},
{
"id": "yield",
"number": 4,
"label": "FromISR result requests daemon restore",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "04",
"code_ref": "src/tasks/task01_gpio_timer.c:117",
"description": "FromISR result requests daemon restore",
"evidence": "one port yield"
},
{
"id": "callback",
"number": 5,
"label": "daemon applies GPIO in the same tick",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.daemon",
"svg_label": "05",
"code_ref": "src/tasks/task01_gpio_timer.c:135",
"snapshot_ref": "task01.callback",
"description": "daemon applies GPIO in the same tick",
"evidence": "daemon stack and GPIO=1"
},
{
"id": "resume",
"number": 6,
"label": "stimulus resumes only after callback",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.daemon",
"svg_label": "06",
"code_ref": "src/tasks/task01_gpio_timer.c:183",
"snapshot_ref": "task01.stimulus-resumed",
"description": "stimulus resumes only after callback",
"evidence": "applied_at_resume=1"
}
]
}
]
}
}
]
},
{
"title": "A5 — One hardware event replay",
"order": 50,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "The decisive order is E03 ISR, E04 daemon, E05 interrupted stimulus. Exactly one accepted event produces exactly one GPIO transition.",
"assets": [
{
"path": "assets/a5-flow.png",
"html_path": "assets/a5-flow.svg",
"source_path": "assets/a5-flow.puml",
"caption": "A5 FLOW — E01E06 from configuration to PASS.",
"label": "fig:a5-flow",
"alt": "A5 · deferred GPIO replay",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"config": 1,
"arm": 1,
"isr": 1,
"apply": 1,
"stimulus": 1,
"verified": 1
}
},
"interactive": {
"kind": "uml-sequence",
"storage_key": "fc14-a5-flow",
"title": "A5 · deferred GPIO replay",
"task": {
"id": "task01",
"label": "Task01 · hardware timer to deferred GPIO"
},
"block": {
"id": "a5",
"label": "A5 FLOW",
"description": "Six events show configuration, arming, timer ISR, daemon callback, interrupted-task resume and final verification."
},
"phases": [
{
"id": "flow",
"label": "ARM / INTERRUPT / DEFER / APPLY",
"steps": [
{
"id": "config",
"number": 1,
"label": "configure daemon priority and GPIO output",
"mode": "RUN",
"event_id": "E01",
"strategy_ref": "run.timer",
"svg_label": "01",
"code_ref": "src/tasks/task01_gpio_timer.c:260",
"snapshot_ref": "task01.configured",
"description": "configure daemon priority and GPIO output",
"evidence": "daemon priority 3"
},
{
"id": "arm",
"number": 2,
"label": "stimulus arms target tick plus three",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.timer",
"svg_label": "02",
"code_ref": "src/tasks/task01_gpio_timer.c:163",
"snapshot_ref": "task01.armed",
"description": "stimulus arms target tick plus three",
"evidence": "armed=1"
},
{
"id": "isr",
"number": 3,
"label": "mtime compare fires at target",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.timer",
"svg_label": "03",
"code_ref": "src/tasks/task01_gpio_timer.c:112",
"snapshot_ref": "task01.tick-isr",
"description": "mtime compare fires at target",
"evidence": "mcause=MTI; pended once"
},
{
"id": "apply",
"number": 4,
"label": "daemon toggles GPIO low to high",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.daemon",
"svg_label": "04",
"code_ref": "src/tasks/task01_gpio_timer.c:141",
"snapshot_ref": "task01.callback",
"description": "daemon toggles GPIO low to high",
"evidence": "transition count 1"
},
{
"id": "stimulus",
"number": 5,
"label": "interrupted task resumes after apply",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.daemon",
"svg_label": "05",
"code_ref": "src/tasks/task01_gpio_timer.c:183",
"snapshot_ref": "task01.stimulus-resumed",
"description": "interrupted task resumes after apply",
"evidence": "applied already true"
},
{
"id": "verified",
"number": 6,
"label": "verifier commits complete proof",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.identity",
"svg_label": "06",
"code_ref": "src/tasks/task01_gpio_timer.c:225",
"snapshot_ref": "task01.pass",
"description": "verifier commits complete proof",
"evidence": "digest bf66bc48"
}
]
}
]
}
}
]
},
{
"title": "A6 — Pending and applied states",
"order": 60,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "Queue acceptance does not mean GPIO has changed. The callback commit is the first point where applied and the output register may be one.",
"assets": [
{
"path": "assets/a6-state.png",
"html_path": "assets/a6-state.svg",
"source_path": "assets/a6-state.puml",
"caption": "A6 STATE — armed, pended, daemon-running, applied and verified.",
"label": "fig:a6-state",
"alt": "A6 · deferred-work state machine",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"armed": 1,
"queued": 1,
"running": 1,
"applied": 1,
"retired": 1,
"terminal": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc14-a6-state",
"title": "A6 · deferred-work state machine",
"task": {
"id": "task01",
"label": "Task01 · hardware timer to deferred GPIO"
},
"block": {
"id": "a6",
"label": "A6 STATE",
"description": "The event moves through armed, accepted, queued, executing and applied states; hardware and software ownership change at explicit boundaries."
},
"phases": [
{
"id": "state",
"label": "EVENT LIFETIME",
"steps": [
{
"id": "armed",
"number": 1,
"label": "armed until target tick",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.timer",
"svg_label": "01",
"code_ref": "src/tasks/task01_gpio_timer.c:169",
"snapshot_ref": "task01.armed",
"description": "armed until target tick",
"evidence": "pended=0"
},
{
"id": "queued",
"number": 2,
"label": "ISR queues one daemon command",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.timer",
"svg_label": "02",
"code_ref": "src/tasks/task01_gpio_timer.c:117",
"snapshot_ref": "task01.tick-isr",
"description": "ISR queues one daemon command",
"evidence": "pended=1"
},
{
"id": "running",
"number": 3,
"label": "daemon consumes callback and arguments",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.daemon",
"svg_label": "03",
"code_ref": "src/tasks/task01_gpio_timer.c:128",
"snapshot_ref": "task01.callback",
"description": "daemon consumes callback and arguments",
"evidence": "callback_calls=1"
},
{
"id": "applied",
"number": 4,
"label": "GPIO records one transition",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.daemon",
"svg_label": "04",
"code_ref": "src/tasks/task01_gpio_timer.c:142",
"snapshot_ref": "task01.callback",
"description": "GPIO records one transition",
"evidence": "data=1"
},
{
"id": "retired",
"number": 5,
"label": "stimulus observes completed work",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.daemon",
"svg_label": "05",
"code_ref": "src/tasks/task01_gpio_timer.c:184",
"snapshot_ref": "task01.stimulus-resumed",
"description": "stimulus observes completed work",
"evidence": "applied=1"
},
{
"id": "terminal",
"number": 6,
"label": "all counts remain exactly one",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.identity",
"svg_label": "06",
"code_ref": "src/tasks/task01_gpio_timer.c:203",
"snapshot_ref": "task01.pass",
"description": "all counts remain exactly one",
"evidence": "PASS"
}
]
}
]
}
}
]
},
{
"title": "A7 — Timer, stacks and artifact proof",
"order": 70,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "The final gate also requires C-only ABI symbols, the exact source and ELF hashes, and three identical simulator processes.",
"assets": [
{
"path": "assets/a7-runtime.png",
"html_path": "assets/a7-runtime.svg",
"source_path": "assets/a7-runtime.puml",
"caption": "A7 RUNTIME — mtime, mtimecmp, cause, three stacks and identity.",
"label": "fig:a7-runtime",
"alt": "A7 · hardware and context proof",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"registers": 1,
"cause": 1,
"same-tick": 1,
"stacks": 1,
"abi": 1,
"determinism": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc14-a7-runtime",
"title": "A7 · hardware and context proof",
"task": {
"id": "task01",
"label": "Task01 · hardware timer to deferred GPIO"
},
"block": {
"id": "a7",
"label": "A7 RUNTIME",
"description": "Runtime evidence distinguishes hardware time, RTOS tick, ISR stack, daemon stack and interrupted-task stack."
},
"phases": [
{
"id": "runtime",
"label": "RUNTIME PROOF",
"steps": [
{
"id": "registers",
"number": 1,
"label": "mtimecmp is reloaded beyond current mtime",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.timer",
"svg_label": "01",
"code_ref": "src/tasks/task01_gpio_timer.c:115",
"snapshot_ref": "task01.tick-isr",
"description": "mtimecmp is reloaded beyond current mtime",
"evidence": "compare > counter"
},
{
"id": "cause",
"number": 2,
"label": "mcause identifies machine timer interrupt",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.timer",
"svg_label": "02",
"code_ref": "src/tasks/task01_gpio_timer.c:113",
"snapshot_ref": "task01.tick-isr",
"description": "mcause identifies machine timer interrupt",
"evidence": "0x80000007"
},
{
"id": "same-tick",
"number": 3,
"label": "ISR and callback share target tick",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.daemon",
"svg_label": "03",
"code_ref": "src/tasks/task01_gpio_timer.c:137",
"snapshot_ref": "task01.callback",
"description": "ISR and callback share target tick",
"evidence": "isr_tick=callback_tick"
},
{
"id": "stacks",
"number": 4,
"label": "ISR, daemon and stimulus SP differ",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.identity",
"svg_label": "04",
"code_ref": "src/tasks/task01_gpio_timer.c:222",
"snapshot_ref": "task01.pass",
"description": "ISR, daemon and stimulus SP differ",
"evidence": "three contexts"
},
{
"id": "abi",
"number": 5,
"label": "ELF exposes tick, pend and daemon symbols",
"mode": "CODE",
"strategy_ref": "code.identity",
"svg_label": "05",
"code_ref": "scripts/check_abi.sh:18",
"description": "ELF exposes tick, pend and daemon symbols",
"evidence": "no C++ runtime"
},
{
"id": "determinism",
"number": 6,
"label": "three processes agree on digest",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.identity",
"svg_label": "06",
"code_ref": "scripts/check_determinism.sh:14",
"snapshot_ref": "task01.pass",
"description": "three processes agree on digest",
"evidence": "bf66bc48"
}
]
}
]
}
}
]
},
{
"title": "Task01 — hardware timer to deferred GPIO",
"order": 90,
"content_kind": "tasks",
"task_refs": [
"task01"
]
}
],
"tasks": {
"task01": {
"title": "Prove one machine-timer event from ISR to daemon GPIO work",
"uuid": "0cc561df-bf81-5bba-9df1-c872d5b42eb8",
"prompt_tex": "Odtwórz E01--E06. Udowodnij, że źródłem jest machine timer interrupt, ISR jedynie odkłada pracę, a GPIO zmienia dopiero callback timer daemon taska.",
"criterion": "PASS; mcause=MTI; mtimecmp>mtime; one successful pend; daemon callback in target tick; one GPIO transition; three distinct stacks; deterministic digest.",
"conclusion_tex": "Hardware timer określa moment przerwania; kolejka timer service określa moment wykonania odroczonej funkcji. Są to dwa konteksty, dwa stosy i dwa różne kontrakty API.",
"flow": [
{
"kind": "block",
"id": "contract",
"title": "A — kontrakt",
"content_tex": "Rozdziel hardware, ISR, daemon i rejestr GPIO.",
"steps": [
{
"id": "contexts",
"title": "Przypisz konteksty i API.",
"content_tex": "Wskaż, co wolno zrobić w tick hooku, a co dopiero w callbacku."
},
{
"id": "predict",
"title": "Przewidź kolejność.",
"content_tex": "Zapisz oczekiwane E03, E04 i E05 dla daemon priority 3."
}
]
},
{
"kind": "block",
"id": "replay",
"title": "B — replay",
"content_tex": "Zbierz dowód hardware i task context.",
"steps": [
{
"id": "timer",
"title": "Sprawdź E02--E03.",
"content_tex": "Target tick, mtime, mtimecmp, mcause i pend result."
},
{
"id": "daemon",
"title": "Sprawdź E04--E05.",
"content_tex": "Daemon handle, callback SP, GPIO i kolejność restore."
},
{
"id": "pass",
"title": "Sprawdź E06.",
"content_tex": "Counts, trzy stosy, ABI i digest."
}
]
},
{
"kind": "exercise",
"id": "select-mechanism",
"title": "Ćwiczenie — wybór mechanizmu",
"prompt_tex": "Dla trzech prac wybierz notification, semaphore albo daemon deferral: inkrementacja licznika, zapis bloku flash i obudzenie konkretnego taska. Uzasadnij właściciela, latency i budżet.",
"evidence_tex": "Tabela workload → mechanizm → odbiorca → dozwolone operacje → ryzyko blokowania.",
"criterion": "Wybór wynika z wymaganej własności i kosztu; uczeń nie przeciąża timer daemon taska nieograniczoną pracą.",
"based_on": [
"contract",
"replay"
]
}
],
"educational_requirement_refs": [
"FC14.WE01"
],
"learning_effect_refs": [
"FC14.EN01",
"FC14.EK01"
],
"assessment_criterion_ref": "FC14.KW01"
}
},
"tasks_order": [
"task01"
]
}