feat: publish FreeRTOS C FC11 card

This commit is contained in:
2026-07-19 16:36:03 +02:00
commit 0464bf759a
196 changed files with 61224 additions and 0 deletions
+863
View File
@@ -0,0 +1,863 @@
{
"card": {
"number": "11",
"slug": "static-allocation",
"title": "Static and dynamic allocation",
"topic": "task, queue and timer with two storage policies",
"status": "Gotowa",
"version": "v00.01"
},
"front": {
"goal": "Uczeń rozdziela semantykę obiektu FreeRTOS od polityki przechowywania i dowodzi jej przez adresy oraz cztery pomiary wolnego heap.",
"scope": "Dynamiczny i statyczny task, queue oraz timer wykonują ten sam eksperyment. H1 jest mniejsze od H0, H2 równa się H1, a H3 równa się H2. Pamięć Idle i timer-service dostarcza aplikacja."
},
"viewpoints": [
{
"id": "A1",
"label": "CONTEXT",
"status": "enabled",
"subtitle": "ownership boundaries"
},
{
"id": "A2",
"label": "STRUCTURE",
"status": "enabled",
"subtitle": "dynamic/static object pairs"
},
{
"id": "A3",
"label": "DISPATCH",
"status": "unavailable",
"subtitle": "same kernel dispatch",
"reason": "Storage policy does not change callback dispatch."
},
{
"id": "A4",
"label": "APPLICATION",
"status": "enabled",
"subtitle": "behavior parity"
},
{
"id": "A5",
"label": "FLOW",
"status": "enabled",
"subtitle": "H0/H1/H2/H3"
},
{
"id": "A6",
"label": "STATE",
"status": "unavailable",
"subtitle": "covered by flow",
"reason": "No new lifecycle state machine; the card compares storage."
},
{
"id": "A7",
"label": "RUNTIME",
"status": "enabled",
"subtitle": "address provenance"
},
{
"id": "A8",
"label": "PATTERNS",
"status": "unavailable",
"subtitle": "policy comparison",
"reason": "No wrapper pattern is introduced in this C card."
}
],
"artifact": {
"source": "src/tasks/task01_static_allocation.c",
"elf": "build/task01_static_allocation/prog.elf",
"image": "build/task01_static_allocation/prog.bin"
},
"strategies": [
{
"id": "code.storage",
"kind": "code",
"action": "open",
"expected_observations": [
"persistent Static* buffers",
"application static Idle/timer task memory"
],
"assertions": [
"no local-lifetime storage",
"both allocation modes enabled"
],
"evidence_fields": [
"symbol",
"section",
"code_ref"
],
"prerequisites": [
"FC11 source"
],
"layout": [
"buffers",
"create APIs",
"FreeRTOSConfig"
],
"commands": [
"rg -n 'x.*CreateStatic|vApplicationGet.*TaskMemory|Static(Task|Queue|Timer)_t' include src"
]
},
{
"id": "run.heap",
"kind": "run",
"action": "replay",
"expected_observations": [
"H1 < H0",
"H2 == H1",
"H3 == H2"
],
"assertions": [
"objects alive at H3",
"no exact delta assumption"
],
"evidence_fields": [
"H0",
"H1",
"H2",
"H3",
"timestamp"
],
"prerequisites": [
"clean Hazard3 RAM"
],
"layout": [
"heap values",
"event order"
],
"commands": [
"print g_fc11.heap_h0",
"print g_fc11.heap_h1",
"print g_fc11.heap_h2",
"print g_fc11.heap_h3"
]
},
{
"id": "run.parity",
"kind": "run",
"action": "replay",
"expected_observations": [
"both receive 0xCAFE",
"both timers callback once"
],
"assertions": [
"distinct stacks",
"PASS and deterministic digest"
],
"evidence_fields": [
"received",
"timer calls",
"SP",
"digest"
],
"prerequisites": [
"scheduler running"
],
"layout": [
"two branches",
"verifier"
],
"commands": [
"print/x g_fc11.dynamic_received",
"print/x g_fc11.static_received",
"print g_fc11_pass"
]
}
],
"checkpoints": {
"task01.h0": {
"event_id": "E01",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 1"
},
"verify": {
"expressions": [
{
"expr": "g_fc11_event_count",
"equals": 1
}
]
}
},
"task01.h1": {
"event_id": "E02",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 2"
},
"verify": {
"expressions": [
{
"expr": "g_fc11.heap_h1 < g_fc11.heap_h0",
"equals": 1
}
]
}
},
"task01.h2": {
"event_id": "E03",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 3"
},
"verify": {
"expressions": [
{
"expr": "g_fc11.heap_h2 == g_fc11.heap_h1",
"equals": 1
}
]
}
},
"task01.dynamic-run": {
"event_id": "E04",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 4"
},
"verify": {
"expressions": [
{
"expr": "g_fc11.dynamic_received",
"equals": 51966
}
]
}
},
"task01.static-run": {
"event_id": "E05",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 5"
},
"verify": {
"expressions": [
{
"expr": "g_fc11.static_received",
"equals": 51966
}
]
}
},
"task01.dynamic-callback": {
"event_id": "E06",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 6"
},
"verify": {
"expressions": [
{
"expr": "g_fc11.dynamic_timer_calls",
"equals": 1
}
]
}
},
"task01.static-callback": {
"event_id": "E07",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 7"
},
"verify": {
"expressions": [
{
"expr": "g_fc11.static_timer_calls",
"equals": 1
}
]
}
},
"task01.pass": {
"event_id": "E08",
"stop": {
"symbol": "fc11_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 8"
},
"verify": {
"expressions": [
{
"expr": "g_fc11_pass",
"equals": 1
}
]
}
}
},
"sections": [
{
"id": "A1",
"label": "CONTEXT",
"title": "Context",
"order": 10,
"orientation": "portrait",
"description": "Application, kernel and RAM responsibilities are explicit.",
"content_tex": "Application, kernel and RAM responsibilities are explicit.",
"assets": [
{
"stem": "a1-context",
"title": "A1 · ownership boundaries",
"caption": "A1 CONTEXT — ownership boundaries.",
"label": "fig:a1-context",
"alt": "ownership boundaries",
"phases": [
{
"id": "context",
"label": "OWNERSHIP BOUNDARIES",
"steps": [
{
"id": "application",
"number": 1,
"label": "application owns experiment",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "01",
"code_ref": "src/tasks/task01_static_allocation.c:20",
"description": "application owns experiment",
"evidence": "global experiment"
},
{
"id": "dynamic",
"number": 2,
"label": "dynamic APIs request storage",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "02",
"code_ref": "src/tasks/task01_static_allocation.c:218",
"description": "dynamic APIs request storage",
"evidence": "xTaskCreate/xQueueCreate/xTimerCreate"
},
{
"id": "static",
"number": 3,
"label": "static APIs receive storage",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "03",
"code_ref": "src/tasks/task01_static_allocation.c:239",
"description": "static APIs receive storage",
"evidence": "named buffers"
},
{
"id": "kernel",
"number": 4,
"label": "kernel owns object semantics",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "04",
"code_ref": "vendor/FreeRTOS-Kernel/tasks.c:1",
"description": "kernel owns object semantics",
"evidence": "same scheduler"
},
{
"id": "ram",
"number": 5,
"label": "both policies coexist in RAM",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "05",
"code_ref": "src/tasks/task01_static_allocation.c:26",
"description": "both policies coexist in RAM",
"evidence": "ucHeap plus static buffers"
}
]
}
]
}
]
},
{
"id": "A2",
"label": "STRUCTURE",
"title": "Structure",
"order": 20,
"orientation": "landscape",
"description": "Task, queue and timer are compared pairwise.",
"content_tex": "Task, queue and timer are compared pairwise.",
"assets": [
{
"stem": "a2-structure",
"title": "A2 · object pairs",
"caption": "A2 STRUCTURE — object pairs.",
"label": "fig:a2-structure",
"alt": "object pairs",
"phases": [
{
"id": "structure",
"label": "OBJECT PAIRS",
"steps": [
{
"id": "dynamic-task",
"number": 1,
"label": "dynamic task handle is in heap",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.heap",
"svg_label": "01",
"code_ref": "src/tasks/task01_static_allocation.c:218",
"snapshot_ref": "task01.h1",
"description": "dynamic task handle is in heap",
"evidence": "heap address"
},
{
"id": "static-task",
"number": 2,
"label": "static task uses TCB and stack buffers",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.heap",
"svg_label": "02",
"code_ref": "src/tasks/task01_static_allocation.c:239",
"snapshot_ref": "task01.h2",
"description": "static task uses TCB and stack buffers",
"evidence": "outside heap"
},
{
"id": "dynamic-queue",
"number": 3,
"label": "dynamic queue object is in heap",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.heap",
"svg_label": "03",
"code_ref": "src/tasks/task01_static_allocation.c:228",
"snapshot_ref": "task01.h1",
"description": "dynamic queue object is in heap",
"evidence": "heap address"
},
{
"id": "static-queue",
"number": 4,
"label": "static queue uses supplied storage",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.heap",
"svg_label": "04",
"code_ref": "src/tasks/task01_static_allocation.c:247",
"snapshot_ref": "task01.h2",
"description": "static queue uses supplied storage",
"evidence": "outside heap"
},
{
"id": "dynamic-timer",
"number": 5,
"label": "dynamic timer object is in heap",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.heap",
"svg_label": "05",
"code_ref": "src/tasks/task01_static_allocation.c:229",
"snapshot_ref": "task01.h1",
"description": "dynamic timer object is in heap",
"evidence": "heap address"
},
{
"id": "static-timer",
"number": 6,
"label": "static timer uses StaticTimer_t",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.heap",
"svg_label": "06",
"code_ref": "src/tasks/task01_static_allocation.c:250",
"snapshot_ref": "task01.h2",
"description": "static timer uses StaticTimer_t",
"evidence": "outside heap"
},
{
"id": "services",
"number": 7,
"label": "Idle and timer-service storage is static",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "07",
"code_ref": "src/tasks/task01_static_allocation.c:45",
"description": "Idle and timer-service storage is static",
"evidence": "two application callbacks"
}
]
}
]
}
]
},
{
"id": "A4",
"label": "APPLICATION",
"title": "Application",
"order": 40,
"orientation": "portrait",
"description": "Storage differs while application behavior remains equal.",
"content_tex": "Storage differs while application behavior remains equal.",
"assets": [
{
"stem": "a4-application",
"title": "A4 · behavior parity",
"caption": "A4 APPLICATION — behavior parity.",
"label": "fig:a4-application",
"alt": "behavior parity",
"phases": [
{
"id": "application",
"label": "BEHAVIOR PARITY",
"steps": [
{
"id": "dynamic-worker",
"number": 1,
"label": "dynamic branch receives message",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.parity",
"svg_label": "01",
"code_ref": "src/tasks/task01_static_allocation.c:121",
"snapshot_ref": "task01.dynamic-run",
"description": "dynamic branch receives message",
"evidence": "0xCAFE"
},
{
"id": "static-worker",
"number": 2,
"label": "static branch receives message",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.parity",
"svg_label": "02",
"code_ref": "src/tasks/task01_static_allocation.c:139",
"snapshot_ref": "task01.static-run",
"description": "static branch receives message",
"evidence": "0xCAFE"
},
{
"id": "daemon",
"number": 3,
"label": "daemon executes both callbacks",
"mode": "RUN",
"event_id": "E07",
"strategy_ref": "run.parity",
"svg_label": "03",
"code_ref": "src/tasks/task01_static_allocation.c:99",
"snapshot_ref": "task01.static-callback",
"description": "daemon executes both callbacks",
"evidence": "1 + 1"
},
{
"id": "verifier",
"number": 4,
"label": "verifier checks behavior parity",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.parity",
"svg_label": "04",
"code_ref": "src/tasks/task01_static_allocation.c:157",
"snapshot_ref": "task01.pass",
"description": "verifier checks behavior parity",
"evidence": "PASS"
}
]
}
]
}
]
},
{
"id": "A5",
"label": "FLOW",
"title": "Flow",
"order": 50,
"orientation": "landscape",
"description": "H0/H1/H2/H3 bracket creation and scheduler startup.",
"content_tex": "H0/H1/H2/H3 bracket creation and scheduler startup.",
"assets": [
{
"stem": "a5-flow",
"title": "A5 · four heap checkpoints",
"caption": "A5 FLOW — four heap checkpoints.",
"label": "fig:a5-flow",
"alt": "four heap checkpoints",
"phases": [
{
"id": "flow",
"label": "FOUR HEAP CHECKPOINTS",
"steps": [
{
"id": "h0",
"number": 1,
"label": "H0 baseline",
"mode": "RUN",
"event_id": "E01",
"strategy_ref": "run.heap",
"svg_label": "01",
"code_ref": "src/tasks/task01_static_allocation.c:214",
"snapshot_ref": "task01.h0",
"description": "H0 baseline",
"evidence": "baseline"
},
{
"id": "h1",
"number": 2,
"label": "dynamic objects make H1 smaller",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.heap",
"svg_label": "02",
"code_ref": "src/tasks/task01_static_allocation.c:236",
"snapshot_ref": "task01.h1",
"description": "dynamic objects make H1 smaller",
"evidence": "H1 < H0"
},
{
"id": "h2",
"number": 3,
"label": "static objects leave heap unchanged",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.heap",
"svg_label": "03",
"code_ref": "src/tasks/task01_static_allocation.c:263",
"snapshot_ref": "task01.h2",
"description": "static objects leave heap unchanged",
"evidence": "H2 = H1"
},
{
"id": "dynamic-run",
"number": 4,
"label": "dynamic worker runs",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.parity",
"svg_label": "04",
"code_ref": "src/tasks/task01_static_allocation.c:121",
"snapshot_ref": "task01.dynamic-run",
"description": "dynamic worker runs",
"evidence": "message"
},
{
"id": "static-run",
"number": 5,
"label": "static worker runs",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.parity",
"svg_label": "05",
"code_ref": "src/tasks/task01_static_allocation.c:139",
"snapshot_ref": "task01.static-run",
"description": "static worker runs",
"evidence": "message"
},
{
"id": "dynamic-callback",
"number": 6,
"label": "dynamic timer callback",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.parity",
"svg_label": "06",
"code_ref": "src/tasks/task01_static_allocation.c:99",
"snapshot_ref": "task01.dynamic-callback",
"description": "dynamic timer callback",
"evidence": "count 1"
},
{
"id": "static-callback",
"number": 7,
"label": "static timer callback",
"mode": "RUN",
"event_id": "E07",
"strategy_ref": "run.parity",
"svg_label": "07",
"code_ref": "src/tasks/task01_static_allocation.c:99",
"snapshot_ref": "task01.static-callback",
"description": "static timer callback",
"evidence": "count 1"
},
{
"id": "pass",
"number": 8,
"label": "H3 unchanged and verifier passes",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.parity",
"svg_label": "08",
"code_ref": "src/tasks/task01_static_allocation.c:157",
"snapshot_ref": "task01.pass",
"description": "H3 unchanged and verifier passes",
"evidence": "H3 = H2"
}
]
}
],
"diagram_kind": "sequence"
}
]
},
{
"id": "A7",
"label": "RUNTIME",
"title": "Runtime",
"order": 70,
"orientation": "portrait",
"description": "Debugger evidence connects handles to heap or named buffers.",
"content_tex": "Debugger evidence connects handles to heap or named buffers.",
"assets": [
{
"stem": "a7-runtime",
"title": "A7 · address provenance",
"caption": "A7 RUNTIME — address provenance.",
"label": "fig:a7-runtime",
"alt": "address provenance",
"phases": [
{
"id": "runtime",
"label": "ADDRESS PROVENANCE",
"steps": [
{
"id": "heap-arena",
"number": 1,
"label": "dynamic handles lie in ucHeap",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.heap",
"svg_label": "01",
"code_ref": "src/tasks/task01_static_allocation.c:174",
"snapshot_ref": "task01.pass",
"description": "dynamic handles lie in ucHeap",
"evidence": "three true predicates"
},
{
"id": "named-buffers",
"number": 2,
"label": "static handles lie outside ucHeap",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.heap",
"svg_label": "02",
"code_ref": "src/tasks/task01_static_allocation.c:177",
"snapshot_ref": "task01.pass",
"description": "static handles lie outside ucHeap",
"evidence": "three false predicates"
},
{
"id": "service-buffers",
"number": 3,
"label": "kernel-service buffers are named",
"mode": "CODE",
"strategy_ref": "code.storage",
"svg_label": "03",
"code_ref": "src/tasks/task01_static_allocation.c:34",
"description": "kernel-service buffers are named",
"evidence": "Idle and daemon buffers"
},
{
"id": "heap-relation",
"number": 4,
"label": "four checkpoints satisfy relation",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.heap",
"svg_label": "04",
"code_ref": "include/task01_static_allocation_model.h:34",
"snapshot_ref": "task01.pass",
"description": "four checkpoints satisfy relation",
"evidence": "H1<H0; H2=H1; H3=H2"
},
{
"id": "evidence",
"number": 5,
"label": "commit-last evidence is deterministic",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.parity",
"svg_label": "05",
"code_ref": "src/tasks/task01_static_allocation.c:72",
"snapshot_ref": "task01.pass",
"description": "commit-last evidence is deterministic",
"evidence": "cdf44a0a"
}
]
}
]
}
]
}
],
"learning": {
"model_label": "Storage ownership",
"model": "Uczeń rozdziela semantykę obiektu i politykę przechowywania.",
"replay_label": "Heap replay",
"replay": "Uczeń odtwarza E01E08 i dowodzi H1<H0, H2=H1, H3=H2.",
"criterion": "PASS; address provenance; message and callback parity; deterministic digest.",
"requirement": "Porównanie dynamicznej i statycznej polityki pamięci obiektów FreeRTOS."
},
"task": {
"short_label": "two storage policies",
"title": "Same behavior, two storage policies",
"prompt_tex": "Przejdź po A1, A2, A4, A5 i A7. Odtwórz E01E08 oraz udowodnij relacje H1<H0, H2=H1 i H3=H2.",
"conclusion_tex": "Statyczne API zmienia własność pamięci, ale nie semantykę taska, kolejki ani timera.",
"flow": [
{
"kind": "block",
"id": "predict",
"title": "A — przewidywanie",
"content_tex": "Przewidź cztery pomiary heap.",
"steps": [
{
"id": "relation",
"title": "Zapisz relacje H0H3.",
"content_tex": "Nie zakładaj dokładnej liczby bajtów."
},
{
"id": "ownership",
"title": "Wskaż właściciela pamięci.",
"content_tex": "Rozdziel ucHeap i named buffers."
}
]
},
{
"kind": "block",
"id": "replay",
"title": "B — replay Hazard3",
"content_tex": "Wykonaj E01E08 z clean RAM.",
"steps": [
{
"id": "heap",
"title": "Zbadaj H0/H1/H2/H3.",
"content_tex": "Zapisz wartości i relacje."
},
{
"id": "parity",
"title": "Zbadaj obie gałęzie.",
"content_tex": "Porównaj message, timer callback i stack."
},
{
"id": "pass",
"title": "Zbadaj E08.",
"content_tex": "Zapisz PASS, digest i timestamp."
}
]
},
{
"kind": "exercise",
"id": "choose-policy",
"title": "Ćwiczenie — wybór polityki",
"prompt_tex": "Dla taska okresowego, kolejki telemetrycznej i timera bezpieczeństwa wybierz dynamiczne albo statyczne tworzenie. Uzasadnij lifetime i ownership.",
"evidence_tex": "Tabela obiekt→API→storage→lifetime oraz ślad H0H3.",
"criterion": "Każdy bufor ma trwałość co najmniej tak długą jak obiekt kernelowy.",
"based_on": [
"predict",
"replay"
]
}
]
}
}