# 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**: - - 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.