feat: add organization-per-series EDU catalog
This commit is contained in:
@@ -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`.
|
||||
@@ -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. C01–C03 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 C10–C13 i granica roku znajdują się w
|
||||
`series/inf/lab-rv32i-c-pointers-arrays/guidelines/year-01-interrupts-to-year-02-freertos.md`.
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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 E01–E12 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 | E01–E12 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 E01–E04]
|
||||
│ │ └── Step 03 · RUNNING -> COMPLETED [RUN E07–E10]
|
||||
│ └── Phase · KERNEL
|
||||
│ ├── Step 04 · Ready -> Running through scheduler [RUN E04–E07]
|
||||
│ ├── Step 05 · equal-priority time slicing [RUN E08]
|
||||
│ └── Step 06 · Deleted does not destroy static context [RUN E10–E11]
|
||||
├── 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 E01–E12 | 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 (E01–E05);
|
||||
5. A5 DISPATCH/FINISH (E06–E12), 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.
|
||||
@@ -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, E01–E07 — landscape;
|
||||
6. A5 part 2, E08–E12 — 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 E01–E12 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.
|
||||
@@ -0,0 +1,389 @@
|
||||
# FreeRTOS C — book-led card sequence
|
||||
|
||||
Status: FC01–FC02 exist; FC03 is the next implementation; FC04–FC15 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 → FC02–FC04
|
||||
├── Ch. 5 Queue management → FC05
|
||||
├── Ch. 6 Software timer management → FC06
|
||||
├── Ch. 7 Interrupt management → FC07, FC13–FC14
|
||||
├── 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.
|
||||
|
||||
## A1–A8 viewpoint policy
|
||||
|
||||
A1–A8 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.1–3.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.2–4.6 and the creation/parameter parts of Examples 4.1–4.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 — A1–A8 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.7–4.10 and Examples 4.4–4.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.2–5.5 and Examples 5.1–5.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.1–6.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.2–7.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.2–10.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 4–6.
|
||||
|
||||
- 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 12–13.
|
||||
|
||||
- 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.2–7.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 3–13.
|
||||
|
||||
- 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 A1–A8 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 A1–A8 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.
|
||||
@@ -0,0 +1,38 @@
|
||||
# FreeRTOS C++ — plan kart
|
||||
|
||||
Status: K02 istnieje i jest bieżącą kartą; K03–K16 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 — A1–A8 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 A1–A8
|
||||
|
||||
Status: agreed paired design; FC02 C and K02 C++ now have local
|
||||
implementations that follow the shared E01–E12 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.
|
||||
|
||||
## A1–A8 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 E01–E12 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 A1–A8 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 E01–E12 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 A1–A8 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;
|
||||
4–5. 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;
|
||||
4–5. 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. E01–E12 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 A1–A8 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 E01–E12.
|
||||
|
||||
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 A1–A8 convention:
|
||||
`tools/card-layouts/docs/UML-VIEWPOINTS.md`
|
||||
- Shiki bundled languages and transformers:
|
||||
<https://shiki.style/languages>,
|
||||
<https://shiki.style/packages/transformers>
|
||||
@@ -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`.
|
||||
@@ -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 Producer–Consumer Queue
|
||||
├── PT08 · POSIX Semaphores
|
||||
├── PT09 · Reader–Writer 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.
|
||||
@@ -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 1–3]
|
||||
├── L04 · The RISC-V ISA and Instruction Decoder [steps 4–5]
|
||||
├── L05 · ALU and the Verilog Assembler [steps 6–7]
|
||||
├── L06 · Control Flow — Jumps and Branches [steps 8–9]
|
||||
├── L07 · Addresses and Memory [steps 10–11]
|
||||
├── L08 · Subroutines and the RISC-V ABI [steps 13–14]
|
||||
└── L09 · Load and Store [steps 15–16]
|
||||
```
|
||||
|
||||
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`.
|
||||
Reference in New Issue
Block a user