Karta pracy: FreeRTOS heap_4
Trzy programy wspierające kartę po K&R 5.4 oraz structures:
- nagłówek, wyrównanie i geometria splitu na arenie 256 B;
- lista adresowa + scalanie
A | B | C; - niezmodyfikowany FreeRTOS-Kernel V11.3.0
heap_4.c.
W lekcji 30-minutowej programy 1–2 są demonstracjami z predykcją. Uczeń debugguje wyłącznie program 3.
Task 3 linkuje upstream portable/MemMang/heap_4.c z commita
9b777ae5c5b8e9e456065a00294d1e5f5f9facf5.
- AMD64: rzeczywisty algorytm + jednowątkowy adapter sekcji krytycznej.
- Hazard3:
tasks.c,list.c,heap_4.ci oficjalny port RISC-V. - RP2350: zgodny core+port z forka Raspberry Pi (
4f7299d6ea74) oraz podstawiony stabilny allocator V11.3.0.
Bezpośrednia kontynuacja K&R 5.4
Lekcja zaczyna się od gotowego projektu z poprzedniej karty:
allocbuf[64], allocp, alloc(5), alloc(7) oraz offsety
0 -> 5 -> 12. Ten alokator:
- nie potrafi zwolnić pierwszego bloku i zachować drugiego;
- nie przechowuje rozmiaru ani stanu zwróconego obszaru;
- nie zapamiętuje i nie wykorzystuje dziur;
- odzyskuje pamięć wyłącznie przez reset całej areny.
FC01 odpowiada na jedno pytanie projektowe: co trzeba dodać, aby zwalniać
dowolny blok i ponownie wykorzystywać powstałe miejsce? Odpowiedzią jest
mechanika heap_4: nagłówek bloku, lista wolnych bloków uporządkowana po
adresie, first-fit, split oraz scalanie fizycznych sąsiadów.
FreeRTOS udostępnia kilka wymiennych implementacji tego samego API i projekt
linkuje dokładnie jedną. heap_1, heap_2, heap_3 i heap_5 są w tej
karcie tylko jednominutową mapą kontekstu. Cała obserwowana implementacja to
niezmodyfikowany heap_4.c z FreeRTOS-Kernel V11.3.0.
Lekcja trwa 30 minut. Task 1 i Task 2 są krótkimi demonstracjami z predykcją;
Task 3 jest jedynym centralnym przebiegiem ucznia w debuggerze. Obraz dla
Pico 2 W musi być zbudowany i wgrany przed zajęciami. heap_4 jest wyborem
linkera projektu, nie sprzętowym mechanizmem RP2350.
Jedno wejście: stemctl
Centralny przebieg lekcji, przygotowany przed wejściem uczniów:
stemctl debug rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
Pełna weryfikacja repozytorium wykonywana poza 30-minutową lekcją:
stemctl series cards fetch freertos heap4
stemctl test native-amd64 freertos heap4 1
stemctl test hazard3-sim freertos heap4 2
stemctl debug hazard3-sim freertos heap4 3
stemctl test rp2350 freertos heap4 3
stemctl deploy rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
stemctl debug rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
debug rp2350: roboczy ELFno_flashładowany do SRAM.deploy rp2350: trwały obraz w SPI flash, odczytany przez breakpointy.
Kontrakt zadań
| Task | Sprawdza | Wynik kluczowy |
|---|---|---|
| 1 | alignment, header, split | wanted + remainder == 256 |
| 2 | lista po adresie, coalescing | 2 bloki -> 1 blok, 96 -> 144 B |
| 3 | prawdziwe API FreeRTOS | free wraca do F0, minimum nie rośnie, OOM = NULL |
Debugowanie Task 3
Automatyczny start: heap4_reset_checkpoint. Karta prowadzi po ośmiu
powtarzalnych stanach jednego procesu:
| Event | Symbol | Najważniejszy dowód Hazard3 |
|---|---|---|
| E01 | heap4_reset_checkpoint |
free=largest=4080, 1 blok |
| E02 | heap4_alloc_a_checkpoint |
A(24), consumed=48, free=4032 |
| E03 | heap4_alloc_b_checkpoint |
B(40), consumed=64, free=3968 |
| E04 | heap4_alloc_c_checkpoint |
C(16), consumed=32, free=3936 |
| E05 | heap4_free_a_checkpoint |
free=3984, 2 bloki |
| E06 | heap4_fragmented_checkpoint |
free=4016, 2 bloki, free>largest |
| E07 | heap4_coalesced_checkpoint |
free=largest=4080, 1 blok |
| E08 | task03_debug_checkpoint |
OOM NULL, hook=1, asserts=0, PASS=1 |
BlockLink_t ma na RV32 8 B, ale port wymaga wyrównania 16 B, dlatego
xHeapStructSize wynosi 16 B. To rozróżnienie tłumaczy zużycie 48/64/32 B.
p g_fragmented_stats
p g_final_stats
p g_a_consumed
p g_b_consumed
p g_c_consumed
p xFreeBytesRemaining
p xMinimumEverFreeBytesRemaining
p xStart
p pxEnd
x/160bx ucHeap
b prvInsertBlockIntoFreeList
b pvPortMalloc
b vPortFree
Scalanie sprawdzamy z replay E06: zatrzymujemy się przed vPortFree(g_b),
ustawiamy tymczasowy breakpoint na prvInsertBlockIntoFreeList i krokujemy.
Upstream V11.3.0 scala najpierw poprzedni/lewy, a potem następny/prawy blok.
Pełna macierz kroków diagramów jest w
doc/hazard3-iteration-plan.md.
W UI: Termdebug po lewej; źródło i listing po prawej; bash pod Neovimem.
F5 continue, F9 breakpoint, F10 next, F11 step, Shift-F11
finish, F8 stepi, :StudentStack, :StudentMemory, :StudentLst.
Test repozytorium
./tests/test_host.sh
bash -n tools/card-action.sh
./scripts/render_pdf.sh
Źródło i licencja: UPSTREAM.md.