Files
workspace-info/plans/informatyka/freertos-c.md
T

409 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FreeRTOS C — book-led card sequence
Status: FC01FC15 istnieją; blok 15 kart FreeRTOS C jest kompletny i stanowi
zamknięty fundament przed serią FreeRTOS C++. Każda karta używa publicznego
API C, a końcowa FC15 scala mechanizmy w jeden deterministyczny eksperyment.
## 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_4: from a linear cursor to reusable blocks
├── 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_4`: from a linear cursor to reusable blocks
**Duration:** one 30-minute lesson.
**Direct predecessor:** C07, K&R 5.4 Task04 — `allocbuf[64]`, `allocp`,
`alloc(5)`, `alloc(7)` and cursor offsets `0 -> 5 -> 12`.
**Book basis:** the `heap_4` and heap-statistics parts of Chapter 3. The other
FreeRTOS heap implementations are a one-minute map of alternatives, not
parallel lesson content.
- Opening problem: the linear project cannot release the first 5-byte area
while preserving the later 7-byte area, cannot remember reusable holes and
recovers the arena only with a whole-arena reset.
- New model: a block header, an address-ordered free list, first-fit selection,
splitting and coalescing of physically adjacent free blocks.
- Raw API: `pvPortMalloc`, `vPortFree`, `xPortGetFreeHeapSize`,
`xPortGetMinimumEverFreeHeapSize`, `vPortGetHeapStats`.
- Task 1 and Task 2 are short teacher-led models with a student prediction;
they are not separate build/debug sessions during the lesson.
- Task 3 is the only central student replay: real upstream `heap_4.c`, two
stable checkpoints, fragmentation metrics, recovery and OOM.
- Pico 2 W supplies one prebuilt RP2350 hardware observation. `heap_4` is the
allocator selected and linked by the project, not a hardware feature of the
microcontroller.
- Acceptance: the student names the three additions over the linear allocator
(header, free list, coalescing), predicts `2 free blocks -> 1 free block`,
and distinguishes current free bytes, largest free block and minimum-ever
free bytes.
- Main pitfall: assuming that a large sum of free bytes guarantees one large
allocation, or that minimum-ever-free increases after `free`.
## 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.
## Completed implementation order
```text
FC01 heap_4
→ FC02 first task
→ 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
```
Obie bramki wejścia do FreeRTOS C++ są spełnione: FC15 zamyka tor systemowy C,
a właściwe karty językowe C++/OOP dostarczają model własności, RAII, szablony i
statyczne trampoline. Następnym etapem jest audyt i realizacja serii FreeRTOS
C++ karta po karcie, bez mieszania wrapperów z implementacją kernela w C.