feat: add organization-per-series EDU catalog

This commit is contained in:
2026-07-19 16:38:49 +02:00
parent d18817dca5
commit 964ecba3e3
28 changed files with 1880 additions and 0 deletions
+16
View File
@@ -5,6 +5,22 @@ Publiczny manifest wspólnego workspace EDU.
Repo opisuje serie i karty pracy dostępne dla `stemctl`. Nie przechowuje
tokenów, lokalnych ścieżek użytkownika ani plików roboczych ucznia.
`workspace.json.series` zawiera wyłącznie aktywne serie obsługiwane przez
`stemctl`. `workspace.json.catalog_subjects` zasila drzewo UI także seriami
planowanymi, ale nie udostępnia ich poleceniom pobierania. Pozycję można dodać
do `series` dopiero po utworzeniu repozytoriów kart.
`workspace.json.organizations` jest rejestrem organizacji źródłowych. `edu`
pełni rolę control plane, natomiast każda stabilna seria wskazuje własną
organizację `edu-<series-id>` przez jawne `source_org`. Jedna karta odpowiada
jednemu repozytorium i zachowuje własną historię, tagi oraz wydania.
Sprawdzenie kontraktu katalogu:
```bash
stemctl workspace audit
```
Domyślna lokalizacja lokalnej kopii:
```text
+7
View File
@@ -0,0 +1,7 @@
{
"id": "boost-asio",
"title": "Boost.Asio",
"catalog_only": true,
"status": "scope-reserved",
"cards": []
}
+20
View File
@@ -0,0 +1,20 @@
{
"id": "c",
"title": "C · Freestanding RV32I and K&R",
"catalog_only": true,
"cards": [
{"id": "C01", "repo": "lab-rv32i-strlen-asm-c-gcc", "number": "01", "title": "ASM, C and GCC", "status": "existing"},
{"id": "C02", "repo": "lab-rv32i-strlen-bss-data-stack", "number": "02", "title": ".bss, .data and static storage", "status": "existing"},
{"id": "C03", "repo": "lab-rv32i-strlen-abi-stack", "number": "03", "title": "ABI and Stack Frame", "status": "existing"},
{"id": "C04", "repo": "lab-rv32i-c-types-operators-expressions", "number": "04", "title": "Types, Operators and Expressions", "status": "existing"},
{"id": "C05", "repo": "lab-rv32i-c-control-flow", "number": "05", "title": "Control Flow", "status": "existing"},
{"id": "C06", "repo": "lab-rv32i-c-functions-program-structure", "number": "06", "title": "Functions and Program Structure", "status": "existing"},
{"id": "C07", "repo": "lab-rv32i-c-pointers-arrays", "number": "07", "title": "Pointers, Arrays and Linear Allocator", "status": "existing"},
{"id": "C08", "repo": "lab-rv32i-c-structures", "number": "08", "title": "Structures and Linked State", "status": "existing"},
{"id": "C09", "repo": "lab-rv32i-c-smalloc-sbrk-libc", "number": "09", "title": "smalloc, sbrk and minimal libc", "status": "planned"},
{"id": "C10", "repo": "lab-rv32i-c-interrupts", "number": "10", "title": "RV32I Traps and Interrupt Control", "status": "planned"},
{"id": "C11", "repo": "lab-rv32i-c-timer", "number": "11", "title": "Machine Timer and Periodic Work", "status": "planned"},
{"id": "C12", "repo": "lab-rv32i-c-uart", "number": "12", "title": "UART — polling and interrupts", "status": "planned"},
{"id": "C13", "repo": "lab-rv32i-c-gpio", "number": "13", "title": "GPIO, Edges and Debounce", "status": "planned"}
]
}
+15
View File
@@ -0,0 +1,15 @@
{
"id": "console-bash",
"title": "Bash · Console Tools",
"catalog_only": true,
"cards": [
{"id": "L01", "repo": "lab-console-busybox", "number": "01", "title": "BusyBox — the Swiss Army Knife", "status": "planned"},
{"id": "L02", "repo": "lab-console-tmux", "number": "02", "title": "Tmux — sessions, windows and panes", "status": "planned"},
{"id": "L03", "repo": "lab-console-neovim", "number": "03", "title": "Neovim — navigation and editing", "status": "planned"},
{"id": "L04", "repo": "lab-console-git-basics-1", "number": "04", "title": "Git Basics I — status, add and commit", "status": "planned"},
{"id": "L05", "repo": "lab-console-git-basics-2", "number": "05", "title": "Git Basics II — log, diff and restore", "status": "planned"},
{"id": "L06", "repo": "lab-console-git-branching-1", "number": "06", "title": "Git Branching I — branch, switch and merge", "status": "planned"},
{"id": "L07", "repo": "lab-console-git-branching-2", "number": "07", "title": "Git Branching II — rebase and conflicts", "status": "planned"},
{"id": "L08", "repo": "lab-console-docker", "number": "08", "title": "Docker Fundamentals", "status": "planned"}
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"id": "cpp",
"title": "C++",
"catalog_only": true,
"cards": [
{"id": "CPP01", "repo": "lab-cpp-build-namespaces", "number": "01", "title": "Translation Units, Linkage and Namespaces", "status": "planned"},
{"id": "CPP02", "repo": "lab-cpp-classes-invariants", "number": "02", "title": "Classes, Encapsulation and Invariants", "status": "planned"},
{"id": "CPP03", "repo": "lab-cpp-lifetime-raii", "number": "03", "title": "Construction, Destruction and RAII", "status": "planned"},
{"id": "CPP04", "repo": "lab-cpp-references-const", "number": "04", "title": "References, const and Value Categories", "status": "planned"},
{"id": "CPP05", "repo": "lab-cpp-copy-move", "number": "05", "title": "Copy, Move and the Rule of Zero/Five", "status": "planned"},
{"id": "CPP06", "repo": "lab-cpp-ownership", "number": "06", "title": "Ownership and Resource Types", "status": "planned"},
{"id": "CPP07", "repo": "lab-cpp-templates", "number": "07", "title": "Function and Class Templates", "status": "planned"},
{"id": "CPP08", "repo": "lab-cpp-static-polymorphism", "number": "08", "title": "Static Polymorphism and CRTP", "status": "planned"},
{"id": "CPP09", "repo": "lab-cpp-dynamic-polymorphism", "number": "09", "title": "Inheritance, Interfaces and Dynamic Dispatch", "status": "planned"},
{"id": "CPP10", "repo": "lab-cpp-strong-types", "number": "10", "title": "Operator Overloading and Strong Types", "status": "planned"},
{"id": "CPP11", "repo": "lab-cpp-containers-iterators", "number": "11", "title": "Containers, Iterators and Algorithms", "status": "planned"},
{"id": "CPP12", "repo": "lab-cpp-lambdas-callables", "number": "12", "title": "Lambdas, Function Objects and Callables", "status": "planned"},
{"id": "CPP13", "repo": "lab-cpp-error-models", "number": "13", "title": "Error Models with and without Exceptions", "status": "planned"},
{"id": "CPP14", "repo": "lab-cpp-abi-evidence", "number": "14", "title": "Object Layout, ABI and Binary Evidence", "status": "planned"},
{"id": "CPP15", "repo": "lab-cpp-resource-integration", "number": "15", "title": "Resource-type Integration Project", "status": "planned"}
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"id": "freertos-c",
"title": "FreeRTOS C",
"catalog_only": true,
"cards": [
{"id": "FC01", "repo": "lab-rv32i-freertos-heap4", "number": "01", "title": "heap_1heap_5 and heap_4 mechanics", "status": "existing"},
{"id": "FC02", "repo": "lab-rv32i-freertos-c-first-task", "number": "02", "title": "First Task, TCB and Task Stack", "status": "existing"},
{"id": "FC03", "repo": "lab-rv32i-freertos-c-scheduler", "number": "03", "title": "Tick, Scheduler, Priorities and Time Slicing", "status": "existing"},
{"id": "FC04", "repo": "lab-rv32i-freertos-c-delay-state", "number": "04", "title": "Delay, Blocking and Task States", "status": "existing"},
{"id": "FC05", "repo": "lab-rv32i-freertos-c-queue", "number": "05", "title": "Queues and Byte-copy Semantics", "status": "existing"},
{"id": "FC06", "repo": "lab-rv32i-freertos-c-software-timers", "number": "06", "title": "Software Timers and the Daemon Task", "status": "existing"},
{"id": "FC07", "repo": "lab-rv32i-freertos-c-isr-semaphore", "number": "07", "title": "Interrupt-safe API and Semaphore Handoff", "status": "existing"},
{"id": "FC08", "repo": "lab-rv32i-freertos-c-resource-management", "number": "08", "title": "Critical Sections, Mutexes and Priority Inheritance", "status": "existing"},
{"id": "FC09", "repo": "lab-rv32i-freertos-c-event-groups", "number": "09", "title": "Event Groups and Multi-event Synchronization", "status": "existing"},
{"id": "FC10", "repo": "lab-rv32i-freertos-c-notifications", "number": "10", "title": "Direct-to-task Notifications", "status": "existing"},
{"id": "FC11", "repo": "lab-rv32i-freertos-c-static-allocation", "number": "11", "title": "Static Allocation and Bounded Storage", "status": "existing"},
{"id": "FC12", "repo": "lab-rv32i-freertos-c-diagnostics", "number": "12", "title": "Assertions, Hooks, Stack Checks and Runtime Diagnostics", "status": "planned"},
{"id": "FC13", "repo": "lab-rv32i-freertos-c-uart", "number": "13", "title": "UART Interrupt-to-task Pipeline", "status": "planned"},
{"id": "FC14", "repo": "lab-rv32i-freertos-c-gpio-timer", "number": "14", "title": "GPIO, Hardware Timer and Deferred Work", "status": "planned"},
{"id": "FC15", "repo": "lab-rv32i-freertos-c-integration", "number": "15", "title": "Integrated Deterministic FreeRTOS C Application", "status": "planned"}
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"id": "freertos-cpp",
"title": "FreeRTOS C++",
"catalog_only": true,
"cards": [
{"id": "K02", "repo": "lab-rv32i-freertos-task-stack-vector", "number": "02", "title": "First Task, Stack, Tick, Scheduler and Vector V0", "status": "existing"},
{"id": "K03", "repo": "lab-rv32i-freertos-vector-raii", "number": "03", "title": "Vector V1 — Destructor, Move, Ownership and RAII", "status": "planned"},
{"id": "K04", "repo": "lab-rv32i-freertos-scheduler-states", "number": "04", "title": "Scheduler States, Priorities and Typed Ticks", "status": "planned"},
{"id": "K05", "repo": "lab-rv32i-freertos-heap-models", "number": "05", "title": "C++ Heap Bridge, Heap Models and HeapStats", "status": "planned"},
{"id": "K06", "repo": "lab-rv32i-freertos-allocator-resource", "number": "06", "title": "MemoryResource and FreeRtosAllocator<T>", "status": "planned"},
{"id": "K07", "repo": "lab-rv32i-freertos-task-wrapper", "number": "07", "title": "TaskHandle_t, Explicit Start and Static Trampoline", "status": "planned"},
{"id": "K08", "repo": "lab-rv32i-freertos-static-task", "number": "08", "title": "DynamicTask, StaticTask, Deletion and Lifetime", "status": "planned"},
{"id": "K09", "repo": "lab-rv32i-freertos-kernel-facade", "number": "09", "title": "Scheduler Facade and Scoped Kernel Guards", "status": "planned"},
{"id": "K10", "repo": "lab-rv32i-freertos-queue", "number": "10", "title": "Queue<T> and StaticQueue<T, N>", "status": "planned"},
{"id": "K11", "repo": "lab-rv32i-freertos-mutex", "number": "11", "title": "Mutex, LockGuard and Priority Inheritance", "status": "planned"},
{"id": "K12", "repo": "lab-rv32i-freertos-semaphore-notify", "number": "12", "title": "Semaphores and Task Notifications", "status": "planned"},
{"id": "K13", "repo": "lab-rv32i-freertos-event-group", "number": "13", "title": "EventGroup and Coordinated State", "status": "planned"},
{"id": "K14", "repo": "lab-rv32i-freertos-sw-timer", "number": "14", "title": "Software Timer and the Timer Daemon Task", "status": "planned"},
{"id": "K15", "repo": "lab-rv32i-freertos-isr-drivers", "number": "15", "title": "Explicit FromISR, UART and GPIO Wrappers", "status": "planned"},
{"id": "K16", "repo": "lab-rv32i-freertos-integration", "number": "16", "title": "Integrated Real-time Application and Evidence", "status": "planned"}
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"id": "modern-cpp-stl",
"title": "Modern C++ / STL",
"catalog_only": true,
"status": "scope-reserved",
"cards": []
}
+23
View File
@@ -0,0 +1,23 @@
{
"id": "oop",
"title": "OOP and Design Patterns",
"catalog_only": true,
"role": "reference",
"cards": [
{"id": "OOP01", "repo": "lab-cpp-oop-strategy", "number": "01", "title": "Strategy — Replaceable Behaviour", "status": "design"},
{"id": "OOP02", "repo": "lab-cpp-oop-adapter", "number": "02", "title": "Adapter — Stable Boundary", "status": "planned"},
{"id": "OOP03", "repo": "lab-cpp-oop-template-method", "number": "03", "title": "Template Method — Fixed Skeleton", "status": "planned"},
{"id": "OOP04", "repo": "lab-cpp-oop-dispatch", "number": "04", "title": "Static vs Dynamic Dispatch", "status": "planned"},
{"id": "OOP05", "repo": "lab-cpp-oop-raii", "number": "05", "title": "RAII and Ownership", "status": "planned"},
{"id": "OOP06", "repo": "lab-cpp-oop-state", "number": "06", "title": "State — Explicit Behaviour", "status": "planned"},
{"id": "OOP07", "repo": "lab-cpp-oop-facade", "number": "07", "title": "Facade — Subsystem Boundary", "status": "planned"},
{"id": "OOP08", "repo": "lab-cpp-oop-command", "number": "08", "title": "Command — Request as Object", "status": "planned"},
{"id": "OOP09", "repo": "lab-cpp-oop-observer", "number": "09", "title": "Observer — Subscription and Telemetry", "status": "planned"},
{"id": "OOP10", "repo": "lab-cpp-oop-factory-method", "number": "10", "title": "Factory Method — Resource Policy", "status": "planned"},
{"id": "OOP11", "repo": "lab-cpp-oop-builder", "number": "11", "title": "Builder — Valid Configuration", "status": "planned"},
{"id": "OOP12", "repo": "lab-cpp-oop-decorator", "number": "12", "title": "Decorator — Measurement and Diagnostics", "status": "planned"},
{"id": "OOP13", "repo": "lab-cpp-oop-composite", "number": "13", "title": "Composite — Component Tree", "status": "planned"},
{"id": "OOP14", "repo": "lab-cpp-oop-chain", "number": "14", "title": "Chain of Responsibility", "status": "planned"},
{"id": "OOP15", "repo": "lab-cpp-oop-integration", "number": "15", "title": "Pattern-language Integration", "status": "planned"}
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"id": "posix-threads",
"title": "POSIX Threads",
"catalog_only": true,
"cards": [
{"id": "PT01", "repo": "lab-posix-process-thread", "number": "01", "title": "Process and Thread Execution Context", "status": "planned"},
{"id": "PT02", "repo": "lab-posix-pthread-create-join", "number": "02", "title": "pthread_create, pthread_join and Lifecycle", "status": "planned"},
{"id": "PT03", "repo": "lab-posix-thread-arguments", "number": "03", "title": "Arguments, Return Values and Ownership", "status": "planned"},
{"id": "PT04", "repo": "lab-posix-data-races", "number": "04", "title": "Data Races and the Happens-before Question", "status": "planned"},
{"id": "PT05", "repo": "lab-posix-mutex", "number": "05", "title": "Mutex, Critical Section and Deadlock", "status": "planned"},
{"id": "PT06", "repo": "lab-posix-condition-variable", "number": "06", "title": "Condition Variables and Predicates", "status": "planned"},
{"id": "PT07", "repo": "lab-posix-producer-consumer", "number": "07", "title": "Bounded ProducerConsumer Queue", "status": "planned"},
{"id": "PT08", "repo": "lab-posix-semaphore", "number": "08", "title": "POSIX Semaphores", "status": "planned"},
{"id": "PT09", "repo": "lab-posix-rwlock", "number": "09", "title": "ReaderWriter Lock", "status": "planned"},
{"id": "PT10", "repo": "lab-posix-atomics", "number": "10", "title": "C Atomics and Memory Ordering", "status": "planned"},
{"id": "PT11", "repo": "lab-posix-cancellation-cleanup", "number": "11", "title": "Cancellation, Cleanup and Safe Shutdown", "status": "planned"},
{"id": "PT12", "repo": "lab-posix-thread-local", "number": "12", "title": "Thread-local Storage", "status": "planned"},
{"id": "PT13", "repo": "lab-posix-scheduling", "number": "13", "title": "Scheduling Policy, Priority and Affinity", "status": "planned"},
{"id": "PT14", "repo": "lab-posix-thread-debugging", "number": "14", "title": "GDB, Sanitizers and Race Evidence", "status": "planned"},
{"id": "PT15", "repo": "lab-posix-freertos-comparison", "number": "15", "title": "POSIX Threads vs FreeRTOS Integration", "status": "planned"}
]
}
+16
View File
@@ -0,0 +1,16 @@
{
"id": "rv32i-asm",
"title": "ASM · RV32I From Blinker to RISC-V",
"catalog_only": true,
"cards": [
{"id": "L01", "repo": "lab-rv32i-asm-number-systems", "number": "01", "title": "Number Systems and Storage", "status": "planned"},
{"id": "L02", "repo": "lab-rv32i-asm-fpga-bringup", "number": "02", "title": "FPGA Bring-up and Programming", "status": "planned"},
{"id": "L03", "repo": "lab-rv32i-asm-blinker", "number": "03", "title": "Blinker and Synchronous Logic", "status": "planned"},
{"id": "L04", "repo": "lab-rv32i-asm-decoder", "number": "04", "title": "The RISC-V ISA and Instruction Decoder", "status": "planned"},
{"id": "L05", "repo": "lab-rv32i-asm-alu", "number": "05", "title": "ALU and the Verilog Assembler", "status": "planned"},
{"id": "L06", "repo": "lab-rv32i-asm-control-flow", "number": "06", "title": "Control Flow — Jumps and Branches", "status": "planned"},
{"id": "L07", "repo": "lab-rv32i-asm-addresses-memory", "number": "07", "title": "Addresses and Memory", "status": "planned"},
{"id": "L08", "repo": "lab-rv32i-asm-subroutines-abi", "number": "08", "title": "Subroutines and the RISC-V ABI", "status": "planned"},
{"id": "L09", "repo": "lab-rv32i-asm-load-store", "number": "09", "title": "Load and Store", "status": "planned"}
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"id": "std-threads",
"title": "std::thread / std::jthread",
"catalog_only": true,
"status": "scope-reserved",
"cards": []
}
+7
View File
@@ -0,0 +1,7 @@
{
"id": "transformers-gpu",
"title": "Transformers on GPU",
"catalog_only": true,
"status": "scope-reserved",
"cards": []
}
+65
View File
@@ -0,0 +1,65 @@
# INF — plan serii i kart
Status: katalog programu, wersja 0.1, 2026-07-17.
Ten katalog jest źródłem czytelnego drzewa nawigacyjnego używanego przez
viewer kart. Nie jest aktywnym manifestem `stemctl`: pozycja planowana może
być widoczna w menu, ale staje się linkiem dopiero po utworzeniu repozytorium
i nadaniu karcie kanonicznego adresu HTTP(S).
```text
INF · Informatyka
├── Rok 1
│ ├── Bash · Console Tools [8]
│ ├── ASM · RV32I From Blinker to RISC-V [9]
│ └── C · Freestanding RV32I and K&R [13]
├── Rok 2
│ ├── C++ [15]
│ ├── FreeRTOS C [15]
│ ├── FreeRTOS C++ [15]
│ ├── POSIX Threads [15]
│ └── OOP and Design Patterns [reference]
├── Rok 3
│ ├── Modern C++ / STL [scope reserved]
│ ├── std::thread / std::jthread [scope reserved]
│ ├── Boost.Asio [scope reserved]
│ └── OOP and Design Patterns [reference]
└── Rok 4
└── Transformers on GPU [scope reserved]
```
Pierwszy blok zawiera dokładnie 30 tematów: Bash 8 + ASM 9 + C 13.
Drugi blok zawiera dokładnie 60 tematów: FreeRTOS C 15 + C++ 15 + FreeRTOS
C++ 15 + POSIX Threads 15. OOP and Design Patterns jest osobnym kursem i nie
jest wliczany do tych 60. `std::thread`/`std::jthread` i Boost.Asio są kolejnym
etapem i nie są jeszcze częścią tego katalogu.
Kolejność stosowania języków jest jawna:
```text
Bash -> ASM -> C
├──> FreeRTOS C ───────┐
└──> C++ ──────────────┼──> FreeRTOS C++ -> POSIX Threads
↕ │
OOP / Patterns ───┘
```
FreeRTOS C i C++ rozpoczynają się równolegle po zakończeniu C. FreeRTOS C++
ma dwie bramki wejścia: ukończony surowy blok FreeRTOS C oraz mechanizmy
językowe C++. OOP jest osobnym kursem odniesienia, do którego prowadzą linki z
kart C++ i FreeRTOS C++; nie jest jednorazowym blokiem do „zaliczenia i
zapomnienia”.
Pliki planów:
- `console-bash.md`
- `rv32i-asm.md`
- `c.md`
- `freertos-c.md`
- `freertos-cpp.md`
- `cpp.md`
- `oop-design-patterns.md`
- `posix-threads.md`
Odpowiadające im dane menu znajdują się w `../../catalog/*.json`. Aktywne
repozytoria nadal są zadeklarowane wyłącznie w `../../series/*.json`.
+27
View File
@@ -0,0 +1,27 @@
# C — Freestanding RV32I and K&R
Status: 8 kart istniejących lub rozpoczętych, 5 planowanych.
```text
C · Freestanding RV32I and K&R
├── C01 · ASM, C and GCC
├── C02 · .bss, .data and static storage
├── C03 · ABI and Stack Frame
├── C04 · Types, Operators and Expressions [K&R 2]
├── C05 · Control Flow [K&R 3]
├── C06 · Functions and Program Structure [K&R 4]
├── C07 · Pointers, Arrays and Linear Allocator [K&R 5]
├── C08 · Structures and Linked State [K&R 6]
├── C09 · smalloc, sbrk and minimal libc
├── C10 · RV32I Traps and Interrupt Control
├── C11 · Machine Timer and Periodic Work
├── C12 · UART — polling and interrupts
└── C13 · GPIO, Edges and Debounce
```
RV32I ASM jest osobną serią-prerekwizytem. C01C03 tworzą przejście z
freestanding assemblera do środowiska C, ale pozostają kartami serii C,
ponieważ ich wynikiem jest rozumienie uruchomienia i ABI programu C.
Pełne cele C10C13 i granica roku znajdują się w
`series/inf/lab-rv32i-c-pointers-arrays/guidelines/year-01-interrupts-to-year-02-freertos.md`.
+25
View File
@@ -0,0 +1,25 @@
# Bash · Console Tools — plan kart
Status: plan, 8 lekcji.
Seria przygotowuje warsztat przed FPGA, assemblerem i C. Nazwa obejmuje pracę
w powłoce i terminalu; BusyBox może udostępniać `ash`, więc nie utożsamiamy
każdego appletu BusyBox z implementacją Bash.
```text
Bash · Console Tools
├── L01 · BusyBox — the Swiss Army Knife
├── L02 · Tmux — sessions, windows and panes
├── L03 · Neovim — navigation and editing
├── L04 · Git Basics I — status, add and commit
├── L05 · Git Basics II — log, diff and restore
├── L06 · Git Branching I — branch, switch and merge
├── L07 · Git Branching II — rebase and conflicts
└── L08 · Docker Fundamentals
```
Każda karta kończy się małym dowodem wykonania: komendą, stanem terminala albo
historią Git, którą uczeń potrafi odtworzyć i wyjaśnić.
Pierwotne ustalenia znajdują się również w
`series/inf/lab-rv32i-c-pointers-arrays/guidelines/console-series.md`.
+32
View File
@@ -0,0 +1,32 @@
# C++ — plan kart
Status: plan, 15 tematów.
Seria uczy języka i modelu obiektu bez zależności od RTOS. Dopiero po niej
uczeń przechodzi do FreeRTOS C++ i rozpoznaje, które zachowanie pochodzi z C++,
a które z wrappera lub kernela. Kurs może być prowadzony równolegle z
FreeRTOS C, ponieważ oba mają wspólny ukończony prerekwizyt C.
```text
C++
├── CPP01 · Translation Units, Linkage and Namespaces
├── CPP02 · Classes, Encapsulation and Invariants
├── CPP03 · Construction, Destruction and RAII
├── CPP04 · References, const and Value Categories
├── CPP05 · Copy, Move and the Rule of Zero/Five
├── CPP06 · Ownership and Resource Types
├── CPP07 · Function and Class Templates
├── CPP08 · Static Polymorphism and CRTP
├── CPP09 · Inheritance, Interfaces and Dynamic Dispatch
├── CPP10 · Operator Overloading and Strong Types
├── CPP11 · Containers, Iterators and Algorithms
├── CPP12 · Lambdas, Function Objects and Callables
├── CPP13 · Error Models with and without Exceptions
├── CPP14 · Object Layout, ABI and Binary Evidence
└── CPP15 · Resource-type Integration Project
```
Kurs OOP/wzorców pozostaje osobną serią. Karty C++ mogą przygotowywać potrzebny
mechanizm, ale nie udają, że każda cecha języka jest wzorcem GoF. Gdy w kodzie
pojawia się rzeczywisty problem projektowy, karta C++ linkuje do odpowiedniej
karty OOP jako rozwinięcia decyzji.
+283
View File
@@ -0,0 +1,283 @@
# FC02 Plan — First Task, TCB and Task Stack
Status: implemented and validated locally. The card exists at
`series/freertos/lab-rv32i-freertos-c-first-task`, is visible in the
FreeRTOS C catalog and remains outside the deploy manifest until its own
repository is committed and published.
The paired experiment and common E01E12 vocabulary are defined in
[`freertos-first-task-a1-a8.md`](freertos-first-task-a1-a8.md).
## Goal
The student creates a FreeRTOS task through the raw C API, follows
`pvParameters` into a typed context, separates that context from the TCB and
task stack, observes equal-priority time slicing, and proves deterministic
completion in Hazard3/GDB.
The card is the C baseline for K02. It must not imitate a C++ wrapper in C.
## Scope
Included:
- `TaskFunction_t` and `void *pvParameters`;
- `xTaskCreate`, `TaskHandle_t`, scheduler start and self-delete;
- two equal-priority CPU-bound workers and one lower-priority supervisor;
- static application contexts, dynamic TCB/task-stack allocation in `heap_4`;
- TCB, stack, PC/SP, callback ABI and task-state observations;
- the same sum and scheduling invariants as K02.
Excluded:
- C++ classes, templates, RAII or virtual dispatch;
- queues, mutexes, notifications, timers, ISR APIs and peripherals;
- proof that the idle task has already reclaimed deleted tasks;
- report/PDF/Teams generation and the later book/matura lesson payload.
## Implemented program shape
```c
typedef enum
{
TRACE_PREPARED,
TRACE_STARTING,
TRACE_READY,
TRACE_RUNNING,
TRACE_COMPLETED,
TRACE_CREATE_FAILED
} WorkerTraceState;
typedef struct
{
uint32_t id;
volatile uint32_t result;
volatile uint32_t iterations;
volatile WorkerTraceState trace_state;
TaskHandle_t handle;
TickType_t start_tick;
TickType_t end_tick;
} WorkerContext;
```
Source responsibilities:
```text
src/tasks/task01_first_task.c
├── two static WorkerContext instances
├── trace/checkpoint state
├── create_worker(WorkerContext*, ...)
├── sum_task_entry(void *pvParameters)
├── supervisor_task_entry(void *pvParameters)
├── task01_debug_checkpoint(event, subject)
└── main()
```
`trace_state` is an application diagnostic. Its name deliberately avoids
pretending that it is `eTaskState`.
## Applicable viewpoint profile
| View | Status | FC02 purpose |
|---|---|---|
| A1 CONTEXT | enabled | raw application → C API/kernel/port → Hazard3 |
| A2 STRUCTURE | enabled | contexts, handles, entry functions and storage domains |
| A3 DISPATCH | enabled | function pointer + erased parameter → typed C body |
| A4 APPLICATION | unavailable | the raw task module already is the concrete application; no generic application layer exists |
| A5 FLOW | enabled | E01E12 creation and execution scenario |
| A6 STATE | enabled | static context/diagnostic state versus kernel state |
| A7 RUNTIME | enabled | context, TCB, stack, registers, PC and ticks |
| A8 PATTERNS | unavailable | a standalone pattern view would be decorative; idioms are labelled in A2/A3 and compared in K02 A8 |
Unavailable A4/A8 tabs remain readable in the viewer and print index with the
reasons above.
## Canonical tree
```text
Series · FreeRTOS C
└── Card FC02 · First Task, TCB and Task Stack
└── Task01 · Raw C task and typed context
├── Block · A1 CONTEXT
│ └── Phase · SYSTEM BOUNDARY
│ ├── Step 01 · application module requests tasks [CODE]
│ ├── Step 02 · FreeRTOS C API owns scheduling [CODE]
│ └── Step 03 · kernel/port execute on Hazard3 [CODE]
├── Block · A2 STRUCTURE
│ └── Phase · C DATA / FUNCTIONS
│ ├── Step 01 · WorkerContext is application state [CODE]
│ ├── Step 02 · TaskHandle_t is an opaque kernel handle [CODE]
│ ├── Step 03 · two static worker contexts [CODE]
│ ├── Step 04 · sum_task_entry has TaskFunction_t shape [CODE]
│ ├── Step 05 · SupervisorContext observes both workers [CODE]
│ └── Step 06 · common sum/scheduling invariants [CODE]
├── Block · A3 DISPATCH · C FUNCTION POINTER
│ └── Phase · CALLBACK / CONTEXT
│ ├── Step 01 · TaskFunction_t erases the context type [CODE]
│ ├── Step 02 · xTaskCreate receives entry and context [RUN E03]
│ ├── Step 03 · pvParameters arrives in RV32 a0 at entry [RUN E06]
│ ├── Step 04 · cast recovers WorkerContext* [RUN E06]
│ ├── Step 05 · entry executes the typed calculation [RUN E07]
│ └── Step 06 · wrong context cast is not rejected by C [CODE]
├── Block · A5 FLOW
│ ├── Phase · CREATE / START
│ │ ├── Step 01 · static contexts prepared [RUN E01]
│ │ ├── Step 02 · first worker create request [RUN E02]
│ │ ├── Step 03 · xTaskCreate(entry, &workerA) [RUN E03]
│ │ ├── Step 04 · handle != null; diagnostic ready [RUN E04]
│ │ └── Step 05 · vTaskStartScheduler() [RUN E05]
│ └── Phase · DISPATCH / FINISH
│ ├── Step 06 · sum_task_entry(&workerA) [RUN E06]
│ ├── Step 07 · diagnostic running; calculation loop [RUN E07]
│ ├── Step 08 · tick/time slice A -> B -> A [RUN E08]
│ ├── Step 09 · result 200010000 published [RUN E09]
│ ├── Step 10 · diagnostic completed; public handle null [RUN E10]
│ ├── Step 11 · vTaskDelete(NULL) [RUN E11]
│ └── Step 12 · supervisor verifies PASS [RUN E12]
├── Block · A6 STATE
│ ├── Phase · CONTEXT / DIAGNOSTIC
│ │ ├── Step 01 · static WorkerContext lifetime [CODE]
│ │ ├── Step 02 · PREPARED -> STARTING -> READY [RUN E01E04]
│ │ └── Step 03 · RUNNING -> COMPLETED [RUN E07E10]
│ └── Phase · KERNEL
│ ├── Step 04 · Ready -> Running through scheduler [RUN E04E07]
│ ├── Step 05 · equal-priority time slicing [RUN E08]
│ └── Step 06 · Deleted does not destroy static context [RUN E10E11]
├── Block · A7 RUNTIME
│ ├── Phase · MEMORY
│ │ ├── Step 01 · context address is not a TCB address [RUN E04/E06]
│ │ ├── Step 02 · TCB and task stack come from heap_4 [RUN E04/E07]
│ │ └── Step 03 · SP lies inside worker stack interval [RUN E06/E07]
│ └── Phase · CPU / SCHEDULER
│ ├── Step 04 · pvParameters in a0 only at callback entry [RUN E06]
│ ├── Step 05 · PC, tick and switch trace [RUN E08]
│ └── Step 06 · result, source and checkpoint identity [RUN E12]
└── Exercise · Timestamped raw-C task trace
```
## Checkpoint table
FC02 snapshots are local to the FC02 binary even though their `event_id`
matches K02.
| Event | Planned snapshot | Stop condition | Required verification |
|---|---|---|---|
| E01 | `task01.contexts` | point 1, worker A | trace prepared, handle null, result zero |
| E02 | `task01.create-request` | point 2, worker A, previous point 1 | first launch request only |
| E03 | `task01.create-call` | point 3, worker A | trace starting; callback/context arguments correct |
| E04 | `task01.ready` | point 4, worker A | trace ready; handle non-null |
| E05 | `task01.scheduler` | point 5 | all three tasks created; startup stack active |
| E06 | `task01.entry` | point 6, worker A | `pvParameters == &workerA`; callback-entry `a0` matches |
| E07 | `task01.work` | point 7, worker A | typed context recovered; trace running |
| E08 | `task01.timeslice` | point 8, worker A only | A/B/A trace; >=2 switches and elapsed ticks |
| E09 | `task01.result` | point 9, worker A | result `200010000`, iterations `20000` |
| E10 | `task01.completed` | point 10, worker A | trace completed; public handle null |
| E11 | `task01.delete` | point 11, worker A | published state persists before non-returning delete |
| E12 | `task01.pass` | point 12, supervisor | two results, contexts, handles, stacks and scheduler invariants pass |
The checkpoint sink is `noinline` and `used`, writes volatile point/subject
state, and ends with a compiler memory barrier. E08 is emitted once by worker
A after the trace has proved `A -> B -> A`.
## A3 dispatch evidence
The exact boundary is:
```text
xTaskCreate(sum_task_entry, ..., &workerA, ..., &workerA.handle)
│ │
│ TaskFunction_t │ void* context
▼ ▼
sum_task_entry(void *pvParameters)
│ callback-entry a0 == &workerA
WorkerContext *worker = (WorkerContext *)pvParameters
typed calculation and published result
```
There is one C callback dispatch. The cast does not cause a second dynamic
dispatch. At callback entry, source + disassembly + `a0` prove the ABI. After
ordinary instructions execute, the card stops claiming that `a0` retains
`pvParameters`.
A compile-only negative exhibit demonstrates that C can accept a wrong
`void*`-to-structure cast that the K02 C++ contract rejects. The unsafe fixture
is never linked into or executed by the teaching program.
## Per-view debugging strategies
| View/anchor | Mode | Layout/action | Expected evidence |
|---|---|---|---|
| A1 dependency boundary | CODE | include/link/config excerpts | application calls public API; kernel/port/target boundary |
| A2 context layout | CODE | source excerpt + `ptype`/DWARF or bounded layout output | static context fields and no hidden C++ object model |
| A2 handle/storage | CODE | declaration + memory-region map | handle is opaque; context is static; TCB/stack are dynamic |
| A3 entry/context | RUN | source + entry disassembly + `a0` + context memory | callback ABI and exact worker identity |
| A3 wrong-cast exhibit | CODE | deterministic compile output and source blob | C compiler does not encode the desired context type |
| A5 E01E12 | RUN | per-event minimal source/asm/register/stack/memory set | ordered scenario and non-empty assertions |
| A6 diagnostic state | RUN | context fields beside public `eTaskGetState`/`vTaskGetInfo` result | correlated domains remain explicitly distinct |
| A7 TCB/stack | RUN | context address, public handle, TCB address, heap range, SP interval | context != TCB; SP belongs to the selected task stack |
| A7 scheduling | RUN | PC, tick, trace buffer and current-task observation | computation crosses real ticks and task changes |
Application code uses public task APIs. `pxCurrentTCB` may appear only in a
clearly labelled debugger-internal observation, never in a C assertion or
source dependency.
## State model
```text
static context lifetime: initialized -------------------------- program end
diagnostic trace state: PREPARED -> STARTING -> READY -> RUNNING -> COMPLETED
kernel task state: Ready <-> Running <-> Blocked; Deleted
```
The lanes can be correlated by an event and handle, but they are not equal.
Clearing the public handle before `vTaskDelete(NULL)` is an application
diagnostic choice. It does not prove immediate heap reclamation.
## Page and spread plan
1. goal/scope, paired invariants and viewpoint index;
2. compact A1 plus main A2 C structure/storage map;
3. A3 callback/parameter dispatch;
4. A5 CREATE/START (E01E05);
5. A5 DISPATCH/FINISH (E06E12), joined with sheet 4 in the viewer;
6. A6 diagnostic and kernel state lanes;
7. A7 runtime map plus exercise/rubric.
The A5 split occurs at the scheduler boundary. Both assets share a
`spread_group`, stable anchor numbering and common participant alignment.
## Acceptance contract
- freestanding C11 build, same pinned kernel/port/config as K02;
- no `_Z*`, `.init_array`, `_GLOBAL__sub_I`, `_Unwind*`, `__cxa_*` or hosted
C++ runtime symbols; positive C/FreeRTOS/checkpoint symbols must exist;
- two independent results equal `200010000`;
- two workers each execute `20000` loop iterations;
- work crosses at least two ticks and proves at least two task changes with an
`A -> B -> A` subsequence;
- callback-entry `a0`, `pvParameters` and worker A address match;
- static context, TCB and task stack are shown as distinct objects/domains;
- all twelve RUN checkpoints have assertions and replay from clean RAM;
- every CODE step has a deterministic source/artifact query and no snapshot;
- all enabled/disabled views, anchors and full tree keys validate;
- plain cursor movement never runs or resets the simulator.
## Validation result
1. The raw C workload and A1/A2/A3/A5/A6/A7 views are implemented.
2. Kernel/config/workload parity is pinned in
`config/paired-experiment.json` and passes `make check-pair`.
3. C-only ABI, context contract and host workload checks pass.
4. Hazard3 finishes with `PASS`; two results equal `200010000`, the trace
contains `A -> B -> A`, and three clean simulator processes produce
identical evidence.
5. HTML and TeX render with A1/A6 portrait, A2/A3/A7 landscape and A5 as a
two-page landscape spread. No PDF was generated.
6. The catalog marks FC02 as existing. The deploy manifest is unchanged
until a published card repository exists.
HTML and TeX may be rendered during validation. PDF generation and commit
remain outside this pass.
+186
View File
@@ -0,0 +1,186 @@
# FC03 Plan — Tick, Priorities, Preemption and Time Slicing
Status: implementation started after completed FC02. Language: freestanding
C11 only. Primary source: FreeRTOS Kernel Book sections 4.5, 4.6, 4.9 and
4.12.
## Learning contract
The student must distinguish four scheduler facts:
1. the highest-priority Ready task is selected;
2. equal-priority Ready tasks may time-slice when the option is enabled;
3. the tick provides a scheduling opportunity, not per-task fairness;
4. making a higher-priority task Ready can preempt the caller immediately.
The card does not teach delays, queues, semaphores, ISR-safe APIs or C++.
## Controlled experiment
```text
priority 0→3 high_probe Ready but initially below the verifier
priority 2 peer_A CPU-bound trace producer
priority 2 peer_B CPU-bound trace producer
priority 1 verifier final invariant checker
```
The program creates `high_probe` Ready at priority 0. The two peers then run
at equal priority 2 until the trace contains A→B→A. Peer A commits a
`before_raise` marker and raises the probe to priority 3 with
`vTaskPrioritySet`. With preemption enabled, `high_probe` must commit its
marker before peer A can commit `after_raise`. The probe self-deletes. After
the call returns, peer A commits `after_raise`, requests both peers to stop,
and each peer clears its own public handle before self-deleting. Only then can
the priority-1 verifier run and publish PASS.
This produces two independent scheduler proofs in one bounded trace:
```text
equal priority: A → B → A time slicing
priority change: A.before → HIGH → A.after immediate preemption
```
## Applicable viewpoints
| View | Status | Purpose |
|---|---|---|
| A1 CONTEXT | enabled | `mtime/mtimecmp` → tick ISR → scheduler → tasks |
| A2 STRUCTURE | enabled | task contexts, priorities, handles and trace buffers |
| A3 DISPATCH | unavailable | callback/context dispatch was proved in FC02 and is unchanged |
| A4 APPLICATION | enabled | four-task experiment topology and invariants |
| A5 FLOW | enabled | ordered time-slice and preemption checkpoints |
| A6 STATE | enabled | Ready/Running lanes and priority-change selection |
| A7 RUNTIME | enabled | tick hook, `mcause`, PC/SP, current handle and trace |
| A8 PATTERNS | unavailable | scheduler policy is a kernel configuration, not an application design pattern |
## Canonical tree
```text
Series · FreeRTOS C
└── Card FC03 · Tick, Priorities, Preemption and Time Slicing
└── Task01 · Controlled scheduler experiment
├── Block · A1 CONTEXT
│ └── Phase · TICK / SCHEDULER BOUNDARY
│ ├── Step 01 · Hazard3 mtime reaches mtimecmp [CODE]
│ ├── Step 02 · port tick handler enters the kernel [CODE]
│ ├── Step 03 · scheduler selects a Ready task [CODE]
│ └── Step 04 · application records public evidence [CODE]
├── Block · A2 STRUCTURE
│ └── Phase · TASKS / TRACE
│ ├── Step 01 · peer contexts have equal priority [CODE]
│ ├── Step 02 · high probe priority contract is 0 → 3 [CODE]
│ ├── Step 03 · verifier has priority 1 [CODE]
│ ├── Step 04 · switch trace stores task and tick [CODE]
│ └── Step 05 · before/high/after order is explicit [CODE]
├── Block · A4 APPLICATION
│ └── Phase · EXPERIMENT TOPOLOGY
│ ├── Step 01 · high probe starts Ready at priority 0 [RUN E02]
│ ├── Step 02 · peers compete at priority 2 [RUN E04]
│ ├── Step 03 · peer A raises high probe to priority 3 [RUN E08]
│ └── Step 04 · verifier is intentionally lowest [RUN E12]
├── Block · A5 FLOW
│ ├── Phase · PREPARE / TIME SLICE
│ │ ├── Step 01 · contexts and config committed [RUN E01]
│ │ ├── Step 02 · high probe created at priority 0 [RUN E02]
│ │ ├── Step 03 · all handles and priorities verified [RUN E03]
│ │ ├── Step 04 · scheduler starts [RUN E04]
│ │ ├── Step 05 · first peer runs [RUN E05]
│ │ ├── Step 06 · first tick hook observes timer interrupt [RUN E06]
│ │ └── Step 07 · trace contains A→B→A [RUN E07]
│ └── Phase · PREEMPT / FINISH
│ ├── Step 08 · peer A commits before_raise [RUN E08]
│ ├── Step 09 · high probe runs before caller returns [RUN E09]
│ ├── Step 10 · peer A commits after_raise and stop [RUN E10]
│ ├── Step 11 · equal-priority peers finish [RUN E11]
│ └── Step 12 · low-priority verifier publishes PASS [RUN E12]
├── Block · A6 STATE
│ ├── Phase · HIGH PROBE
│ │ ├── Step 01 · Ready at priority 0 [RUN E02]
│ │ ├── Step 02 · Ready priority changes 0 → 3 [RUN E08]
│ │ └── Step 03 · selected → Running → Deleted [RUN E09]
│ └── Phase · PEERS / VERIFIER
│ ├── Step 04 · peer A and B alternate Ready/Running [RUN E07]
│ ├── Step 05 · caller remains Ready during preemption [RUN E09]
│ └── Step 06 · verifier runs after priorities 2/3 end [RUN E12]
├── Block · A7 RUNTIME
│ ├── Phase · TIMER / CPU
│ │ ├── Step 01 · tick hook records machine-timer cause [RUN E06]
│ │ ├── Step 02 · ticks in trace are nondecreasing [RUN E07]
│ │ └── Step 03 · PC/SP identify the selected task [RUN E09]
│ └── Phase · SCHEDULER EVIDENCE
│ ├── Step 04 · priorities read through public API [RUN E03]
│ ├── Step 05 · marker projection is before/high/after [RUN E10]
│ └── Step 06 · source, ELF and final invariants match [RUN E12]
└── Exercise · Bounded no-time-slicing observation and explanation
```
## Checkpoint contract
| Event | Snapshot | Required observation |
|---|---|---|
| E01 | `task01.config` | one core; preemption, time slicing, tick hook, priority get/set and delete enabled |
| E02 | `task01.high-dormant` | high handle exists and priority is 0 |
| E03 | `task01.priorities` | high=0, peers=2/2, verifier=1 via public API |
| E04 | `task01.scheduler` | scheduler start requested with all handles valid |
| E05 | `task01.peer-entry` | peer A or B is Running on its own stack |
| E06 | `task01.first-tick` | tick hook count=1; timer cause and ISR stack recorded |
| E07 | `task01.timeslice` | committed trace contains A→B→A and nondecreasing ticks |
| E08 | `task01.before-raise` | caller marker set; high marker and after marker clear |
| E09 | `task01.high-preempts` | high marker set while caller after marker remains clear |
| E10 | `task01.after-raise` | marker projection is A.before→HIGH→A.after; stop requested |
| E11 | `task01.peers-finished` | both peer handles cleared after bounded work |
| E12 | `task01.pass` | verifier ran last and every scheduler invariant is true |
All task-context checkpoint writes complete before entering the stable
noinline sink. The tick hook uses a separate ISR-safe sink, emits E06 only
once and performs bounded writes only. E07 is emitted only by peer A after a
one-entry-per-observed-slice trace contains A→B→A. The exact
before→HIGH→after claim applies to the marker projection, not to every task
that may legally run before peer A is selected again.
## Debug strategies
- `code.tick-boundary`: open RISC-V port/config and trace the public boundary
without making application code depend on kernel internals.
- `code.scheduler-data`: inspect C contexts, priority constants and trace
layout; compile-time assertions keep IDs and buffer bounds stable.
- `run.tick`: stop in the first tick hook; capture `mcause`, `mepc`, ISR SP,
tick count and source/ELF identity.
- `run.timeslice`: show the trace buffer beside peer source and current
task/PC evidence; assert A→B→A.
- `run.preempt`: show `before_raise`, high marker and `after_raise` beside
the call site and selected task; assert the exact ordering.
- `run.pass`: show all handles, priorities, ticks and final invariants.
Application assertions use only public APIs and application-owned records.
Kernel internals such as `pxCurrentTCB` may appear only as a clearly labelled
debugger observation in A7.
## Page layout
1. goal, scope, book mapping and viewpoint index — portrait;
2. A1 vertical context — portrait;
3. A2 data/trace structure — landscape;
4. A4 experiment topology — landscape;
5. A5 part 1, E01E07 — landscape;
6. A5 part 2, E08E12 — landscape, joined with sheet 5 on screen;
7. A6 state lanes — landscape;
8. A7 tick/CPU/scheduler evidence — landscape.
Each diagram starts on a new sheet. The A5 split is one logical sequence with
identical participants and a centered join; no block is cut at the sheet
boundary.
## Acceptance gates
- RV32I/Hazard3 freestanding C11 build against the pinned FreeRTOS kernel;
- no C++ runtime or mangled application symbols;
- deterministic E01E12 replay from clean RAM;
- A→B→A occurs with equal priority and at least two tick observations;
- high probe commits before peer A returns from `vTaskPrioritySet`;
- verifier priority is lower and it publishes PASS only after higher tasks
terminate;
- every CODE step resolves a stable source reference;
- every RUN step has a strategy, checkpoint and non-empty assertions;
- generated HTML and TeX validate; no PDF and no commit without an explicit
request.
+389
View File
@@ -0,0 +1,389 @@
# FreeRTOS C — book-led card sequence
Status: FC01FC02 exist; FC03 is the next implementation; FC04FC15 are
planned. This series uses only the FreeRTOS C API. C++ wrappers belong to a
later, separate series.
## Primary source and ordering rule
The content map follows the official **FreeRTOS Kernel Book**:
- <https://github.com/FreeRTOS/FreeRTOS-Kernel-Book>
- <https://github.com/FreeRTOS/FreeRTOS-Kernel-Book/blob/main/toc.md>
The book supplies the concepts and API order. Each card adds the local
Hazard3/RV32I observation contract: stable checkpoints, source and ELF
identity, a debugging strategy and a timestamped runtime proof. We do not
copy the book examples verbatim; every program is a small deterministic
experiment suitable for replay.
```text
FreeRTOS Kernel Book
├── Ch. 3 Heap memory management → FC01, revisited in FC11
├── Ch. 4 Task management → FC02FC04
├── Ch. 5 Queue management → FC05
├── Ch. 6 Software timer management → FC06
├── Ch. 7 Interrupt management → FC07, FC13FC14
├── Ch. 8 Resource management → FC08
├── Ch. 9 Event groups → FC09
├── Ch. 10 Task notifications → FC10, FC13
├── Ch. 11 Low-power support → optional extension after FC15
├── Ch. 12 Developer support → FC12
└── Ch. 13 Troubleshooting → FC12 and every acceptance gate
```
FC11 deliberately revisits static allocation after the student has already
seen tasks, queues and timers. The book introduces it in Chapter 3; the later
placement lets one card compare real dynamic and static forms of several
kernel objects without teaching APIs that have not appeared yet.
## A1A8 viewpoint policy
A1A8 is a set of questions, not a requirement to draw eight decorative
diagrams. A view is enabled only when it adds a distinct proof.
```text
A1 CONTEXT system boundary and responsibility
A2 STRUCTURE C structs, handles, kernel objects and ownership
A3 DISPATCH callback, ISR or other binding boundary
A4 APPLICATION concrete task/object topology and invariants
A5 FLOW ordered execution and checkpoints
A6 STATE task/object state and lifetime
A7 RUNTIME addresses, TCB, stack, registers, tick and ELF evidence
A8 PATTERNS named reusable design decision, only when real
```
Every enabled diagram is interactive. A CODE step opens a stable source or
artifact reference without running the target. A RUN step replays from clean
RAM to a verified checkpoint. Moving the cursor alone never mutates the
simulator.
## Curated sequence
```text
FreeRTOS C — 15 cards
├── FC01 · Heap schemes and heap_4 block mechanics
├── FC02 · First task, typed context, TCB and task stack
├── FC03 · Tick, priorities, preemption and time slicing
├── FC04 · Delay, blocking, task states and deletion
├── FC05 · Queues, blocking and byte-copy semantics
├── FC06 · Software timers and the daemon task
├── FC07 · Interrupt-safe API and semaphore handoff
├── FC08 · Critical sections, mutexes and priority inheritance
├── FC09 · Event groups and multi-event synchronization
├── FC10 · Direct-to-task notifications
├── FC11 · Static allocation and bounded kernel storage
├── FC12 · Assertions, hooks, stack checks and runtime diagnostics
├── FC13 · UART interrupt-to-task pipeline
├── FC14 · GPIO, hardware timer and deferred work
└── FC15 · Integrated deterministic FreeRTOS C application
```
## FC01 — Heap schemes and heap_4 block mechanics
**Book basis:** 3.13.4: `heap_1``heap_5`, heap utilities, allocation
failure and static allocation introduction.
- Raw API: `pvPortMalloc`, `vPortFree`, `xPortGetFreeHeapSize`,
`xPortGetMinimumEverFreeHeapSize`, `vPortGetHeapStats`.
- Main task: compare allocator policies, then walk allocation, split, free
and coalescing in `heap_4`.
- Blocks: A1 allocator boundary; A2 block/list layout; A5 allocation flow;
A6 free/allocated block state; A7 heap addresses and statistics.
- Exercise: predict the free-list shape for a new allocate/free order.
- Hazard3/GDB proof: block headers, aligned sizes and coalesced neighbors
agree with the final heap statistics.
- Main pitfall: treating the minimum-ever-free value as current free space or
assuming all heap implementations support free/coalescing.
## FC02 — First task, typed context, TCB and task stack
**Book basis:** 4.24.6 and the creation/parameter parts of Examples 4.14.2.
- Raw API: `xTaskCreate`, `vTaskStartScheduler`, `vTaskDelete`,
`uxTaskGetStackHighWaterMark`.
- Main task: two equal-priority workers compute `sum(1..20000)` through
`void *pvParameters`; a lower-priority supervisor verifies both results.
- Enabled views: A1, A2, A3, A5, A6 and A7.
- Exercise: add a third typed context without introducing global task data.
- Hazard3/GDB proof: callback-entry `a0`, context, opaque handle/TCB, task
stack and A→B→A execution trace are distinct and consistent.
- Main pitfall: confusing `&handle`, the handle value, TCB, context and stack.
Detailed plan: [FC02 — A1A8 raw C task](freertos-c-fc02-a1-a8.md).
## FC03 — Tick, priorities, preemption and time slicing
**Book basis:** 4.5, 4.6, 4.9 and 4.12, especially prioritized preemptive
scheduling, runtime priority changes and time slicing.
- Raw API/config: `uxTaskPriorityGet`, `vTaskPrioritySet`,
`xTaskGetTickCount`, `configUSE_PREEMPTION`, `configUSE_TIME_SLICING`.
- Main task: two equal-priority peers establish A→B→A; one peer raises a
dormant probe from priority 0 to 3, which must preempt before the peer's
next committed write; a priority-1 verifier runs only after higher-priority
work ends.
- Blocks: A1 tick/scheduler boundary; A2 task/priority/trace data; A4
experiment topology; A5 two-part scheduling flow; A6 Ready/Running lanes;
A7 timer interrupt, current TCB, PC/SP and trace evidence.
- Exercise: run a bounded expected-noncompletion observation with time slicing
disabled, then explain why a CPU-bound peer can starve its equal-priority
neighbor.
- Hazard3/GDB proof: nondecreasing ticks, A→B→A, immediate high-priority
takeover and delayed low-priority verifier.
- Main pitfall: interpreting priority as fairness or treating a tick as a
guarantee that every Ready task ran.
Detailed plan: [FC03 — scheduler experiment](freertos-c-fc03-a1-a8.md).
## FC04 — Delay, blocking, task states and deletion
**Book basis:** 4.74.10 and Examples 4.44.8.
- Raw API: `vTaskDelay`, `vTaskDelayUntil`, `eTaskGetState`,
`vTaskSuspend`, `vTaskResume`, `vTaskDelete`.
- Main task: periodic and non-periodic tasks cross Ready, Running, Blocked,
Suspended and Deleted states on a controlled tick timeline.
- Blocks: A2 state-bearing contexts/handles; A5 delay and resume sequence;
A6 canonical task-state machine; A7 wake tick, PC/SP, TCB and idle cleanup.
- Exercise: replace relative delay with `vTaskDelayUntil` and quantify drift.
- Hazard3/GDB proof: actual wake ticks and public `eTaskState` observations
match the selected state-machine edges.
- Main pitfall: busy waiting instead of blocking, or assuming `vTaskDelete`
immediately erases every forensic trace.
## FC05 — Queues, blocking and byte-copy semantics
**Book basis:** Chapter 5, with emphasis on 5.25.5 and Examples 5.15.2.
- Raw API: `xQueueCreate`, `xQueueSendToBack`, `xQueueSendToFront`,
`xQueueReceive`, `uxQueueMessagesWaiting`, `xQueuePeek`.
- Main task: two producers send typed messages by value to one consumer; a
full and an empty queue deliberately block the correct task.
- Blocks: A1 producer/kernel/consumer boundary; A2 queue item/ring/storage;
A4 producer-consumer topology; A5 send/copy/block/wake/receive; A6 queue
and task states; A7 source address versus copied queue slot and destination.
- Exercise: compare a value queue with a queue of pointers and write the
ownership contract for the latter.
- Hazard3/GDB proof: changing the producer buffer after send does not change
the queued value; waiting counts and task transitions are correct.
- Main pitfall: assuming queues hold references, or queuing a pointer without
an explicit lifetime owner.
## FC06 — Software timers and the daemon task
**Book basis:** Chapter 6 and Examples 6.16.3.
- Raw API: `xTimerCreate`, `xTimerStart`, `xTimerChangePeriod`,
`xTimerReset`, `pvTimerGetTimerID`.
- Main task: one-shot and auto-reload timers share a callback but use distinct
IDs; task code resets one timer and changes the other's period.
- Blocks: A1 application/timer service/kernel boundary; A2 timer objects,
IDs and command queue; A3 callback dispatch; A5 command→daemon→callback;
A6 dormant/active/expired states; A7 daemon task, callback PC and tick.
- Exercise: derive the callback order for a changed period and verify it.
- Hazard3/GDB proof: callback context is the timer daemon task, not the task
that issued `xTimerStart`.
- Main pitfall: blocking inside a timer callback or assuming timer commands
execute synchronously in the caller.
## FC07 — Interrupt-safe API and semaphore handoff
**Book basis:** Chapter 7, especially 7.27.5 and queue/ISR considerations.
- Raw API: `xSemaphoreCreateBinary`, `xSemaphoreCreateCounting`,
`xSemaphoreGiveFromISR`, `xSemaphoreTake`, `portYIELD_FROM_ISR`.
- Main task: a deterministic simulated interrupt gives a semaphore, sets
`xHigherPriorityTaskWoken`, and transfers execution to a waiting task.
- Blocks: A1 ISR/task/kernel boundary; A2 semaphore and ISR evidence; A3
FromISR dispatch/yield contract; A5 interrupt→unblock→yield→task flow; A6
waiting/ready/running; A7 trap frame, `mcause`, PC/SP and awakened TCB.
- Exercise: replace binary with counting semantics and explain event loss or
accumulation.
- Hazard3/GDB proof: ISR uses only FromISR API, does not block, and a required
yield selects the unblocked higher-priority task.
- Main pitfall: calling task-context API from an ISR or ignoring
`xHigherPriorityTaskWoken`.
## FC08 — Critical sections, mutexes and priority inheritance
**Book basis:** Chapter 8, including critical sections, scheduler suspension,
mutexes, priority inversion/inheritance, deadlock and gatekeeper tasks.
- Raw API: `taskENTER_CRITICAL`, `taskEXIT_CRITICAL`, `vTaskSuspendAll`,
`xTaskResumeAll`, `xSemaphoreCreateMutex`, `xSemaphoreTake/Give`.
- Main task: low/medium/high tasks first expose bounded priority inversion,
then prove inherited priority while a mutex protects a shared resource.
- Blocks: A2 mutex owner/waiters/resource; A4 three-task topology; A5
inversion and inheritance flow; A6 mutex/task states; A7 effective versus
base priority and owner TCB; A8 mutex versus gatekeeper decisions.
- Exercise: construct a lock-order table that removes a demonstrated
two-mutex deadlock.
- Hazard3/GDB proof: low task's effective priority rises while high waits and
returns after release; the shared invariant remains intact.
- Main pitfall: using a binary semaphore where priority inheritance is
required, or holding a mutex across an unbounded operation.
## FC09 — Event groups and multi-event synchronization
**Book basis:** Chapter 9.
- Raw API: `xEventGroupCreate`, `xEventGroupSetBits`,
`xEventGroupWaitBits`, `xEventGroupSync`.
- Main task: two workers publish independent readiness bits; a coordinator
waits for ALL bits, then all participants cross a reusable barrier.
- Blocks: A2 bit ownership and event object; A4 participant topology; A5
set/wait/unblock/barrier; A6 bit mask and blocked-task state; A7 EventBits_t,
wait masks and TCB wake evidence; A8 barrier pattern.
- Exercise: compare ANY versus ALL and clear-on-exit semantics on the same
event trace.
- Hazard3/GDB proof: the coordinator cannot pass before the complete mask and
the barrier releases the intended set of tasks once.
- Main pitfall: reusing one bit for incompatible meanings or forgetting the
effects of automatic bit clearing.
## FC10 — Direct-to-task notifications
**Book basis:** Chapter 10, especially benefits/limits and 10.3.210.3.6.
- Raw API: `xTaskNotifyGive`, `ulTaskNotifyTake`, `xTaskNotify`,
`xTaskNotifyWait` and their explicit FromISR variants as a comparison.
- Main task: one receiver exercises counting, value overwrite and bit-set
notification modes without an intermediary queue/semaphore object.
- Blocks: A2 notification value in the target task; A3 sender→target binding;
A5 notify/block/wake/consume; A6 notification state/value; A7 target TCB,
value transitions and RAM comparison with queue/semaphore alternatives.
- Exercise: choose the correct notification action for three stated
protocols and justify what information can be lost.
- Hazard3/GDB proof: only the selected target wakes, and the observed value
transition matches the selected action.
- Main pitfall: treating a single notification slot as a general multi-reader
message queue.
## FC11 — Static allocation and bounded kernel storage
**Book basis:** 3.4 plus the static creation variants introduced throughout
Chapters 46.
- Raw API: `xTaskCreateStatic`, `xQueueCreateStatic`, `xTimerCreateStatic`,
`vApplicationGetIdleTaskMemory`, `vApplicationGetTimerTaskMemory`.
- Main task: rebuild a small task+queue+timer topology with explicit TCB,
stack and object buffers; compare it to the dynamic build.
- Blocks: A1 ownership boundary; A2 complete storage graph; A4 bounded
topology; A5 initialization order; A7 `.bss` addresses, map file and zero
heap growth.
- Exercise: calculate and declare all required storage for one additional
task and queue.
- Hazard3/GDB proof: kernel object addresses lie in declared static storage,
and free-heap values do not change during creation.
- Main pitfall: confusing a statically allocated task with a static C
function, or under-sizing stack/object buffers.
## FC12 — Assertions, hooks, stack checks and runtime diagnostics
**Book basis:** Chapters 1213.
- Raw API/config: `configASSERT`, malloc-failed and stack-overflow hooks,
`uxTaskGetStackHighWaterMark`, `uxTaskGetSystemState`, trace hooks.
- Main task: run controlled positive diagnostics plus isolated expected-fail
fixtures for an assertion, allocation failure and stack guard.
- Blocks: A1 diagnostic boundaries; A2 evidence record and hook contracts;
A5 fault→hook→frozen evidence; A6 healthy/failing terminal states; A7
stack watermark, task statistics, fault PC and build identity.
- Exercise: diagnose a supplied trace without changing the program first.
- Hazard3/GDB proof: every fixture stops in the intended hook with preserved
source/ELF/checkpoint identity and no false PASS.
- Main pitfall: optimizing hooks away, allocating/printing unsafely inside a
hook, or treating watermark as the exact current stack use.
## FC13 — UART interrupt-to-task pipeline
**Book basis:** 7.27.7 and the UART notification example in 10.3.7.
- Raw API: explicit UART ISR, `vTaskNotifyGiveFromISR` or
`xTaskNotifyFromISR`, `ulTaskNotifyTake`, `portYIELD_FROM_ISR`.
- Main task: RX ISR transfers bytes into a bounded ring; a task drains and
validates complete frames while TX ownership remains explicit.
- Blocks: A1 peripheral/ISR/task boundary; A2 MMIO/ring/task context; A3
ISR→notification binding; A5 byte→interrupt→ring→task→frame flow; A6 ring
and receiver states; A7 MMIO, indices, trap frame and task stack.
- Exercise: specify overflow policy and prove it with an overlong frame.
- Hazard3/GDB proof: ISR duration is bounded, no blocking API is used, ring
indices remain valid and the consumer wakes at the correct boundary.
- Main pitfall: doing parsing in the ISR or publishing an index before the
corresponding byte is visible.
## FC14 — GPIO, hardware timer and deferred work
**Book basis:** 6.4, 7.3 and 7.6, applied to GPIO/timer peripherals.
- Raw API: hardware timer ISR, `xTimerPendFunctionCallFromISR`, optional
notification/semaphore comparison, GPIO MMIO.
- Main task: a timer edge records minimal ISR evidence, defers a bounded
callback to the daemon task, and updates GPIO state under a stated timing
contract.
- Blocks: A1 hardware/ISR/daemon/task boundary; A2 event record; A3 deferred
callback binding; A5 edge→ISR→daemon queue→callback→GPIO; A6 pending and
applied states; A7 `mtime/mtimecmp`, trap frame, daemon task and MMIO.
- Exercise: select notification, semaphore or daemon deferral for three
different workloads.
- Hazard3/GDB proof: ISR and deferred callback have different stacks/PCs,
exactly one GPIO transition is associated with each accepted event.
- Main pitfall: confusing a hardware timer interrupt with a FreeRTOS software
timer callback or overloading the daemon task.
## FC15 — Integrated deterministic FreeRTOS C application
**Book basis:** synthesis of Chapters 313.
- Raw API: tasks, queues, notification, event group, mutex, software timer,
FromISR handoff and diagnostics, selected only where justified.
- Main task: acquire deterministic UART/GPIO/timer events, process one
algorithmic workload, publish results and supervise health under bounded
memory.
- Blocks: all A1A8 views may be enabled because architecture, topology,
dispatch, flow, state, runtime and patterns are all distinct here.
- Exercise: change one application policy while preserving the published
concurrency and memory contracts.
- Hazard3/GDB proof: timestamped end-to-end trace connects input event,
selected task, communication object, result, deadline/ordering invariant
and final PASS.
- Main pitfall: adding every learned primitive instead of choosing the
smallest correct synchronization mechanism.
## Common card contract
Every new card must contain:
1. a one-page goal and scope contract;
2. one principal Task divided into viewpoint Blocks and Phases/Steps;
3. only applicable A1A8 views, with explicit reasons for unavailable views;
4. a stable `code_ref` for every CODE step;
5. a debug strategy, checkpoint and non-empty assertion set for every RUN
step;
6. a student exercise that changes one variable without changing the whole
experiment;
7. a Hazard3/GDB acceptance proof including source and ELF identity;
8. HTML and TeX generated from one `card_source.json`;
9. no PDF generation and no commit unless explicitly requested.
## Implementation order
```text
FC03 scheduler
→ FC04 state/delay
→ FC05 queues
→ FC06 software timers
→ FC07 interrupts/semaphores
→ FC08 resources/mutex
→ FC09 event groups
→ FC10 notifications
→ FC11 static allocation
→ FC12 diagnostics
→ FC13 UART
→ FC14 GPIO/timer
→ FC15 integration
```
Ukończenie FC15 jest pierwszą z dwóch bramek wejścia do FreeRTOS C++; drugą
jest ukończenie właściwych kart językowych C++/OOP.
+38
View File
@@ -0,0 +1,38 @@
# FreeRTOS C++ — plan kart
Status: K02 istnieje i jest bieżącą kartą; K03K16 są planem.
Karta `heap_4` należy do serii FreeRTOS C. FreeRTOS C++ zaczyna się dopiero po
ukończeniu dwóch torów prowadzonych równolegle: FreeRTOS C oraz C++. K02
porównuje znany już surowy task C z freestanding wrapperem C++ i Vector V0.
```text
FreeRTOS C++
├── K02 · First Task, Stack, Tick, Scheduler and Vector V0
├── K03 · Vector V1 — Destructor, Move, Ownership and RAII
├── K04 · Scheduler States, Priorities and Typed Ticks
├── K05 · C++ Heap Bridge, Heap Models and HeapStats
├── K06 · MemoryResource and FreeRtosAllocator<T>
├── K07 · TaskHandle_t, Explicit Start and Static Trampoline
├── K08 · DynamicTask, StaticTask, Deletion and Lifetime
├── K09 · Scheduler Facade and Scoped Kernel Guards
├── K10 · Queue<T> and StaticQueue<T, N>
├── K11 · Mutex, LockGuard and Priority Inheritance
├── K12 · Semaphores and Task Notifications
├── K13 · EventGroup and Coordinated State
├── K14 · Software Timer and the Timer Daemon Task
├── K15 · Explicit FromISR, UART and GPIO Wrappers
└── K16 · Integrated Real-time Application and Evidence
```
Pełna specyfikacja każdej lekcji znajduje się w
`series/freertos/lab-rv32i-freertos-task-stack-vector/doc/cpp-wrappers-roadmap.md`.
Kernel oraz port pozostają w C; publiczna warstwa dydaktyczna C++ jest
freestanding, bez wyjątków, RTTI i zależności od hosted `libstdc++`.
Każda karta linkuje również do osobnej serii OOP, gdy wrapper rzeczywiście
realizuje wzorzec lub idiom wymagający osobnego omówienia.
Szczegółowy plan bieżącej K02 oraz kontrolowane porównanie z FC02:
- [K02 Task01 — A1A8 plan](../../../../series/freertos/lab-rv32i-freertos-task-stack-vector/doc/task01-a1-a8-plan.md)
- [FC02/K02 — paired first-task experiment](freertos-first-task-a1-a8.md)
@@ -0,0 +1,379 @@
# Paired FC02/K02 Plan — First FreeRTOS Task through A1A8
Status: agreed paired design; FC02 C and K02 C++ now have local
implementations that follow the shared E01E12 contract.
This plan defines one controlled teaching experiment rendered twice:
- **FC02 / FreeRTOS C:** raw `TaskFunction_t`, `void *pvParameters`,
`TaskHandle_t` and `xTaskCreate`;
- **K02 / FreeRTOS C++:** the existing header-only `Task<Derived>` CRTP
wrapper, explicit `start()` and static trampoline.
The design remains the comparison contract. FC02 now has a local executable,
HTML and TeX implementation; PDF generation and publication remain separate
operations.
## Learning question
The student must be able to answer one question with source, binary and
runtime evidence:
> What remains identical when a FreeRTOS task is expressed through raw C or a
> small C++ wrapper, and what new compile-time and runtime boundaries does the
> wrapper introduce?
The C and C++ cards therefore use the same calculation and kernel behaviour.
Only the language-facing task abstraction changes.
## Curriculum position
```text
C pointers
→ C structures and memory regions
→ heap_4 mechanics in C
→ FC02 raw FreeRTOS task in C
→ C++ language/OOP prerequisites
→ K02 FreeRTOS task wrapper in C++
→ later lifetime, RAII, communication and synchronization cards
```
FC02 establishes the raw kernel boundary first. K02 reuses that known
behaviour and makes the abstraction delta observable instead of teaching the
kernel and C++ wrapper as two simultaneous unknowns.
## Controlled experiment contract
Both cards must share these invariants:
| Property | Required value |
|---|---|
| Kernel | FreeRTOS-Kernel V11.3.0, same pinned source revision |
| Target | RV32I/Hazard3 simulator, cycle-exact teaching profile |
| Workers | two equal-priority CPU-bound workers, created before the scheduler |
| Work | sum integers `1..20000` independently |
| Expected result | `200010000` for each worker |
| Supervisor | one lower-priority task validates both workers |
| Scheduling proof | elapsed work crosses at least two ticks and records `A -> B -> A` |
| Allocation | dynamic `xTaskCreate` backed by the same `heap_4` configuration |
| Completion | diagnostic state/result is published before self-delete: `NULL` in C, `nullptr` in C++ |
| Replay | clean RAM and a new generation for every requested RUN checkpoint |
The comparison is valid only when the two builds also use byte-identical
`FreeRTOSConfig.h`, the same tick rate, time-slicing setting, priorities, stack
depths, worker creation order and checkpoint-sink signature. CI must compare
those inputs rather than relying on prose.
Language flags differ only where the lesson requires it:
- FC02: freestanding C11;
- K02: freestanding C++17, no exceptions, no RTTI and no hosted C++ runtime.
The workload must remain present in disassembly. Bounds, trace writes and
published results are observable; a compiler-folded constant is a failed
teaching build.
## A1A8 is a palette, not a quota
The stable viewer keeps all eight positions. A card enables only viewpoints
that answer a real question. An unavailable tab remains visible with a short
reason, and the print index repeats that reason.
| Viewpoint | FC02 C | K02 C++ | Reason |
|---|---:|---:|---|
| A1 CONTEXT | yes | yes | system and language boundaries |
| A2 STRUCTURE | yes | yes | C contexts/handles versus C++ classes/fields |
| A3 DISPATCH | yes | yes | C function pointer versus CRTP trampoline |
| A4 APPLICATION | no | yes | raw C module already is the application; C++ specializes a generic wrapper |
| A5 FLOW | yes | yes | common E01E12 scenario |
| A6 STATE | yes | yes | diagnostic/language lifetime separated from kernel task state |
| A7 RUNTIME | yes | yes | addresses, TCB, stack, registers, PC and ticks |
| A8 PATTERNS | no | yes | a separate C pattern view would be decorative; K02 provides the comparison |
FC02 may label local idioms such as **context object**, **opaque handle** and
**C callback ABI** in A2/A3. It must not manufacture an A8 diagram merely to
fill the tab.
## Teaching hierarchy
Each applicable viewpoint is a normal `Block`. This preserves the existing
card tree and does not add a new hierarchy level.
```text
Series
└── Card
└── Task01 · First FreeRTOS task
├── Block · A1 CONTEXT
├── Block · A2 STRUCTURE
├── Block · A3 DISPATCH
├── Block · A4 APPLICATION K02 only
├── Block · A5 FLOW
│ ├── Phase · CREATE / START
│ └── Phase · DISPATCH / FINISH
├── Block · A6 STATE
│ ├── Phase · LANGUAGE / DIAGNOSTIC
│ └── Phase · KERNEL
├── Block · A7 RUNTIME
│ ├── Phase · MEMORY
│ └── Phase · CPU / SCHEDULER
├── Block · A8 PATTERNS K02 only
└── Exercise · Paired timestamped trace
```
The A1A8 top strip jumps to its block. `Up/Down` walks steps inside a block;
`Ctrl+Up/Down` crosses blocks. Cursor movement is inert. `Enter` in the viewer
and `F2` from Neovim explicitly activate the selected item.
## Common semantic event vocabulary
Snapshot identifiers remain local to each card and container. A shared
`event_id` makes the observations comparable without pretending that one
debugger checkpoint can be reused across two binaries.
| Event | Shared meaning | FC02 C boundary | K02 C++ boundary |
|---|---|---|---|
| E01 | application representation prepared | static worker contexts initialized | static `SumTask` objects constructed |
| E02 | launch interface entered | first raw create request | first `workerA.start()` entry |
| E03 | kernel create boundary | `xTaskCreate(entry, ctx)` | `xTaskCreate(trampoline, this)` |
| E04 | task ready and handle stored | context handle is non-null | wrapper state `ready`, handle non-null |
| E05 | scheduler start | `vTaskStartScheduler()` | `vTaskStartScheduler()` |
| E06 | C callback entry | `sum_task_entry(void *)` | static `trampoline(void *)` |
| E07 | calculation running | typed `WorkerContext *` body | `SumTask::run()` and state `running` |
| E08 | deterministic time slice | worker A observes `A -> B -> A` | worker A observes `A -> B -> A` |
| E09 | result published | context/global result stored | `g_results[id]` stored, `run()` returns |
| E10 | diagnostic completion | context state complete, public handle cleared | wrapper state complete, public handle cleared |
| E11 | current task self-deletes | `vTaskDelete(NULL)` | `vTaskDelete(nullptr)` |
| E12 | lower-priority supervisor passes | raw context invariants pass | wrapper/object invariants pass |
E02 is the first launch hit and is guarded by prior checkpoint state. E08 is
pinned to worker A. Per-instance conditions must prevent worker B from
accidentally satisfying worker A checkpoints.
The supervisor executes before the idle task necessarily reclaims deleted
TCBs. Heap reclamation is therefore not an E01E12 acceptance event. A7 may
measure allocator deltas, but it must describe them as observations at a
defined instant.
## CODE and RUN semantics
An interactive anchor has one of two modes:
- **CODE** selects source or a deterministic binary query. It never resets or
runs the target and does not require `snapshot_ref`.
- **RUN** opens the associated source and performs a clean deterministic
replay to its card-local `snapshot_ref`.
Compile-time facts—types, inheritance, `friend`, field layout, absence of
virtual dispatch and ABI restrictions—are CODE facts. Scheduling, registers,
task states and memory values are RUN facts. A class diagram must never fake a
runtime event.
Repeated visible step numbers are permitted in different blocks, but tooling
must address a step by its full `task/block/phase/step` key. A bare ambiguous
`--step` request is rejected.
## Debug strategy attached to every step
Every selectable UML anchor owns one default debugging strategy. The strategy
is keyed by the full navigation position rather than embedded as unstructured
prose in the step.
```text
strategy
├── id and kind: code | run
├── prerequisites: card, profile, target and required artifact
├── code_ref: repository-validated file and line/range
├── action: open | replay
├── layout: source, asm, registers, stack, memory, kernel state
├── commands: deterministic GDB or artifact queries
├── expected_observations
├── assertions
└── evidence_fields
```
RUN assertions reuse `debug_checkpoints.verify.expressions`. CODE assertions
are exact command/pattern pairs over an identified ELF or source blob, for
example `nm`, `readelf` or a bounded disassembly query. A screenshot of an
unidentified terminal is not sufficient CODE evidence.
The minimum Termdebug observation set is chosen per step, not displayed by
habit:
- source and assembly at the boundary being taught;
- `a0` only where the RV32 ABI still carries the callback argument;
- `sp` and task stack interval where stack ownership is the question;
- object/context address, public handle and TCB address where identity is the
question;
- PC, tick and trace when scheduling is the question;
- result and diagnostic state when completion is the question.
`pxCurrentTCB` may be inspected by the debugger and is marked **kernel
internal**. Card code uses public FreeRTOS APIs and does not make this symbol a
program contract.
## Visual and code evidence contract
Each UML element has a visible numbered anchor and a stable authored
`svg_target`. Selection by mouse and keyboard controls the same cursor.
- disabled content remains readable and uses a neutral outline plus an
explicit unavailable marker/reason;
- selectable inactive neighbours alternate two restrained treatments so their
hit areas remain distinguishable;
- active selection adds a stronger outline, small positional marker and light
fill;
- focus, selectability and completion remain distinguishable in grayscale and
do not rely on hue alone;
- non-selected elements remain legible rather than disappearing.
Code shown beside a diagram is read-only evidence. Neovim remains the editor
and live debugger. The component receives a validated `code_ref`, source blob
hash and explicit highlighted line range; it never fetches an arbitrary file
path supplied by the browser.
The planned `CodeEvidence` pipeline uses **Shiki at generator/build time**, not
as a browser editor or runtime highlighter. A fine-grained, version-pinned
highlighter loads only `c`, `cpp`, `riscv`, `shellscript` and `json`, produces
flat per-line token arrays, and the React viewer renders that allow-listed
data. This keeps the browser bundle free of the regex/WASM engine while
retaining an actual RISC-V TextMate grammar and exact line/range classes.
Rendering never relies on `dangerouslySetInnerHTML`.
A custom Shiki theme emits CSS-variable values rather than stock-theme hex
colours. Light, dark and print treatments therefore remain viewer CSS
decisions. Assembly source uses the `riscv` grammar directly. Objdump `.lst`
input first passes through a small deterministic column parser: address, byte
and symbol fields receive fixed semantic classes, while only the instruction
tail is tokenized as RISC-V. A non-matching listing line falls back to plain
text. Disassembly keeps `white-space: pre` and horizontal scrolling rather
than soft wrapping.
## Audit chain and later evidence capture
The intended chain is:
```text
goal and scope
→ applicable A1A8 viewpoints
→ UML anchor
→ checkpoint debugging strategy
→ CODE proof or RUN replay
→ Neovim + Termdebug + Hazard3 measurement
→ approved checkpoint
→ later composite screenshot
→ later lesson report
```
Approval must be bound to `snapshot_ref`, replay generation and verification
result. A later capture must reject stale identity/generation, retain the raw
PNG, store an image SHA-256 and record backend timestamp, card/version/source
hash, target, event, checkpoint and viewer state. Metadata is rendered from
the database rather than burned irreversibly into the original image.
This plan does **not** implement screenshot capture or report generation.
## Page plan
### FC02 — seven sheets
1. goal, scope, experiment invariants and viewpoint index;
2. compact A1 plus main A2;
3. A3 callback/parameter dispatch;
45. joined A5 CREATE/START and DISPATCH/FINISH spread;
6. A6 diagnostic and kernel state lanes;
7. A7 runtime evidence plus exercise.
A4 and A8 are printed in the index as unavailable with their reasons.
### K02 — eight sheets
1. goal, scope, experiment invariants and viewpoint index;
2. compact A1 plus main A2;
3. main A3 plus compact A4;
45. joined A5 CREATE/START and DISPATCH/FINISH spread;
6. A6 object/wrapper and kernel state lanes;
7. A7 runtime evidence;
8. A8 C-versus-wrapper role table plus exercise and rubric.
One diagram must fit the content box. A long logical diagram is split only at
a phase/group boundary and shares a `spread_group`; the viewer may join those
sheets side by side without changing print pagination.
## Acceptance gates for a future implementation
1. Parity check proves common kernel/config/workload/priority/stack inputs.
2. Every enabled viewpoint has purpose, model kind and ordered anchors.
3. Every disabled viewpoint has a non-empty reason.
4. Every `svg_target` resolves after rendering and anchor order passes lint.
5. Every CODE step has a validated code/artifact proof and no snapshot.
6. Every RUN step has a card-local snapshot and non-empty assertions.
7. E01E12 are unique, ordered and comparable across the two cards.
8. A clean replay produces two sums of `200010000` and the `A -> B -> A`
trace.
9. FC02 has C-only ABI evidence; K02 has no exceptions, RTTI, vtables or hosted
runtime.
10. Navigation never mutates the simulator until explicit `Enter`/`F2`.
11. No program assertion depends on undocumented kernel internals.
12. Print remains meaningful without viewer controls or colour.
## Decisions from the Claude review
Accepted corrections:
- treat viewpoints as blocks and A1A8 as an optional palette;
- enforce the paired-experiment parity gates in tooling;
- add shared semantic `event_id` while keeping snapshots card-local;
- validate viewpoint availability, anchors, RUN snapshots and strategies;
- make assertions mandatory rather than merely displaying observations;
- bind approval and later capture to a verified replay generation;
- support deterministic text evidence for CODE steps;
- pre-tokenize source with fine-grained Shiki grammars and keep the React
component display-only;
- pin the highlighter/grammar versions and test the objdump-column parser with
fixed listing fixtures;
- distinguish diagnostic state from `eTaskState` and mark kernel internals;
- keep idle-task reclamation outside E01E12.
Rejected for these cards:
- replacing K02 CRTP with the upstream virtual `TaskBase` design;
- forcing A4/A8 into FC02;
- automatic replay on cursor movement;
- claiming RAII or ownership semantics before the later lifetime card;
- using `pxCurrentTCB` as application code;
- treating a class relationship as a runtime checkpoint.
## Deferred curriculum envelope — not part of this implementation
For Year 2, a later curriculum pass will attach three coordinated layers to a
lesson:
1. one FreeRTOS mechanism/concurrent algorithm being learned, for example a
task or queue;
2. one algorithm selected from the course book;
3. one examination task selected from the current matura schedule/material.
The current technology is the execution medium, not a decorative appendix:
- a bare-C card implements and debugs the work in bare C;
- a FreeRTOS-C task card places suitable work inside raw C task(s);
- a FreeRTOS-C++ card expresses the same responsibility through the wrapper
under study.
Later work may capture approved UML/debugger evidence, compose a lesson report,
generate a PDF and prepare it for Teams. None of that is implemented or
assigned to FC02/K02 by this plan.
## Primary references
- FreeRTOS task creation:
<https://www.freertos.org/Documentation/02-Kernel/04-API-references/01-Task-creation/01-xTaskCreate>
- FreeRTOS task states:
<https://www.freertos.org/Documentation/02-Kernel/02-Kernel-features/01-Tasks-and-co-routines/02-Task-states>
- FreeRTOS task implementation and self-deletion:
<https://www.freertos.org/Documentation/02-Kernel/02-Kernel-features/01-Tasks-and-co-routines/05-Implementing-a-task>
- Shared A1A8 convention:
`tools/card-layouts/docs/UML-VIEWPOINTS.md`
- Shiki bundled languages and transformers:
<https://shiki.style/languages>,
<https://shiki.style/packages/transformers>
+30
View File
@@ -0,0 +1,30 @@
# OOP and Design Patterns — plan kart
Status: osobny kurs; OOP01 ma opracowany przykład Strategy.
OOP jest przekrojowym kursem odniesienia. Nie blokuje rozpoczęcia całej serii
C++ i nie jest wliczony do 60 tematów FreeRTOS/C++/POSIX. Karty językowe i
systemowe odwołują się do OOP dokładnie tam, gdzie dany wzorzec wyjaśnia
rzeczywistą decyzję projektu.
```text
OOP and Design Patterns
├── OOP01 · Strategy — Replaceable Behaviour
├── OOP02 · Adapter — Stable Boundary
├── OOP03 · Template Method — Fixed Skeleton
├── OOP04 · Static vs Dynamic Dispatch
├── OOP05 · RAII and Ownership
├── OOP06 · State — Explicit Behaviour
├── OOP07 · Facade — Subsystem Boundary
├── OOP08 · Command — Request as Object
├── OOP09 · Observer — Subscription and Telemetry
├── OOP10 · Factory Method — Resource Policy
├── OOP11 · Builder — Valid Configuration
├── OOP12 · Decorator — Measurement and Diagnostics
├── OOP13 · Composite — Component Tree
├── OOP14 · Chain of Responsibility
└── OOP15 · Pattern-language Integration
```
Kanoniczny rozwinięty plan znajduje się w
`/home/user/dev/c++/oop/doc/seria-oop-wzorce.md`.
+26
View File
@@ -0,0 +1,26 @@
# POSIX Threads — plan kart
Status: plan, 15 tematów.
```text
POSIX Threads
├── PT01 · Process and Thread Execution Context
├── PT02 · pthread_create, pthread_join and Lifecycle
├── PT03 · Arguments, Return Values and Ownership
├── PT04 · Data Races and the Happens-before Question
├── PT05 · Mutex, Critical Section and Deadlock
├── PT06 · Condition Variables and Predicates
├── PT07 · Bounded ProducerConsumer Queue
├── PT08 · POSIX Semaphores
├── PT09 · ReaderWriter Lock
├── PT10 · C Atomics and Memory Ordering
├── PT11 · Cancellation, Cleanup and Safe Shutdown
├── PT12 · Thread-local Storage
├── PT13 · Scheduling Policy, Priority and Affinity
├── PT14 · GDB, Sanitizers and Race Evidence
└── PT15 · POSIX Threads vs FreeRTOS Integration
```
Seria kończy rok 2 porównaniem dwóch modeli wykonania. Nie wprowadza jeszcze
`std::thread`, `std::jthread` ani Boost.Asio; te mechanizmy dostaną osobne
plany w następnym etapie.
+24
View File
@@ -0,0 +1,24 @@
# ASM · RV32I From Blinker to RISC-V
Status: plan, 9 lekcji.
```text
ASM · RV32I From Blinker to RISC-V
├── L01 · Number Systems and Storage
├── L02 · FPGA Bring-up and Programming
├── L03 · Blinker and Synchronous Logic [steps 13]
├── L04 · The RISC-V ISA and Instruction Decoder [steps 45]
├── L05 · ALU and the Verilog Assembler [steps 67]
├── L06 · Control Flow — Jumps and Branches [steps 89]
├── L07 · Addresses and Memory [steps 1011]
├── L08 · Subroutines and the RISC-V ABI [steps 1314]
└── L09 · Load and Store [steps 1516]
```
L01 dostarcza języka liczb, kodowania i pamięci. L02 ustanawia fizyczną
drabinkę FPGA. Kolejne karty prowadzą od logiki synchronicznej do rdzenia,
który wykonuje podstawowe instrukcje RV32I. Step 12 pozostaje późniejszym
przeglądem jakości implementacji.
Materiał źródłowy programu:
`series/inf/lab-rv32i-c-pointers-arrays/guidelines/year-01-interrupts-to-year-02-freertos.md`.
+80
View File
@@ -0,0 +1,80 @@
{
"id": "freertos-c",
"title": "FreeRTOS C",
"source_org": "edu-freertos-c",
"answer_org": "c2025-1a-inf",
"source_remote": "r1",
"answer_remote": "r1a",
"fallback_branch": "main",
"workspace_dir": "freertos",
"source_dir": "freertos",
"default_card": "FC01",
"cards": [
{
"id": "FC01",
"repo": "lab-rv32i-freertos-heap4",
"branch": "main",
"title": "heap_1heap_5 and heap_4 mechanics"
},
{
"id": "FC02",
"repo": "lab-rv32i-freertos-c-first-task",
"branch": "main",
"title": "First Task, TCB and Task Stack"
},
{
"id": "FC03",
"repo": "lab-rv32i-freertos-c-scheduler",
"branch": "main",
"title": "Tick, Scheduler, Priorities and Time Slicing"
},
{
"id": "FC04",
"repo": "lab-rv32i-freertos-c-delay-state",
"branch": "main",
"title": "Delay, Blocking and Task States"
},
{
"id": "FC05",
"repo": "lab-rv32i-freertos-c-queue",
"branch": "main",
"title": "Queues and Byte-copy Semantics"
},
{
"id": "FC06",
"repo": "lab-rv32i-freertos-c-software-timers",
"branch": "main",
"title": "Software Timers and the Daemon Task"
},
{
"id": "FC07",
"repo": "lab-rv32i-freertos-c-isr-semaphore",
"branch": "main",
"title": "Interrupt-safe API and Semaphore Handoff"
},
{
"id": "FC08",
"repo": "lab-rv32i-freertos-c-resource-management",
"branch": "main",
"title": "Critical Sections, Mutexes and Priority Inheritance"
},
{
"id": "FC09",
"repo": "lab-rv32i-freertos-c-event-groups",
"branch": "main",
"title": "Event Groups and Multi-event Synchronization"
},
{
"id": "FC10",
"repo": "lab-rv32i-freertos-c-notifications",
"branch": "main",
"title": "Direct-to-task Notifications"
},
{
"id": "FC11",
"repo": "lab-rv32i-freertos-c-static-allocation",
"branch": "main",
"title": "Static Allocation and Bounded Storage"
}
]
}
+1
View File
@@ -1,6 +1,7 @@
{
"id": "freertos",
"title": "FreeRTOS na RV32I/Hazard3",
"legacy": true,
"source_org": "edu-inf",
"answer_org": "c2025-1a-inf",
"source_remote": "r1",
+89
View File
@@ -1,6 +1,33 @@
{
"version": 1,
"workspace": "edu",
"organizations": [
{
"id": "edu",
"title": "EDU control plane",
"role": "control-plane",
"series": []
},
{
"id": "edu-inf",
"title": "Legacy Informatyka series",
"role": "series",
"legacy": true,
"series": ["inf", "freertos"]
},
{
"id": "edu-fiz",
"title": "Fizyka series",
"role": "series",
"series": ["fiz"]
},
{
"id": "edu-freertos-c",
"title": "FreeRTOS C series",
"role": "series",
"series": ["freertos-c"]
}
],
"series": [
{
"id": "inf",
@@ -13,6 +40,68 @@
{
"id": "freertos",
"file": "series/freertos.json"
},
{
"id": "freertos-c",
"file": "series/freertos-c.json"
}
],
"catalog_subjects": [
{
"id": "inf",
"title": "INF · Informatyka",
"levels": [
{
"id": "year-1",
"title": "Rok 1",
"series": [
{"id": "console-bash", "file": "catalog/console-bash.json"},
{"id": "rv32i-asm", "file": "catalog/rv32i-asm.json"},
{"id": "c", "file": "catalog/c.json"}
]
},
{
"id": "year-2",
"title": "Rok 2",
"series": [
{"id": "cpp", "file": "catalog/cpp.json"},
{"id": "freertos-c", "file": "catalog/freertos-c.json"},
{"id": "freertos-cpp", "file": "catalog/freertos-cpp.json"},
{"id": "posix-threads", "file": "catalog/posix-threads.json"},
{"id": "oop", "file": "catalog/oop.json"}
]
},
{
"id": "year-3",
"title": "Rok 3 · plan",
"series": [
{"id": "modern-cpp-stl", "file": "catalog/modern-cpp-stl.json"},
{"id": "std-threads", "file": "catalog/std-threads.json"},
{"id": "boost-asio", "file": "catalog/boost-asio.json"},
{"id": "oop-reference", "file": "catalog/oop.json"}
]
},
{
"id": "year-4",
"title": "Rok 4 · plan",
"series": [
{"id": "transformers-gpu", "file": "catalog/transformers-gpu.json"}
]
}
]
},
{
"id": "fiz",
"title": "FIZ · Fizyka",
"levels": [
{
"id": "all",
"title": "Katalog",
"series": [
{"id": "fiz", "file": "series/fiz.json", "catalog_only": false}
]
}
]
}
]
}