\documentclass[11pt]{article} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage[polish]{babel} \usepackage[a4paper,margin=1.75cm]{geometry} \usepackage{array,tabularx,booktabs} \usepackage{amsmath,amssymb} \usepackage{xcolor,listings} \usepackage{hyperref,fancyhdr,lastpage} \usepackage{enumitem} \definecolor{accent}{HTML}{16324A} \definecolor{accentlight}{HTML}{EEF3F7} \definecolor{rulegray}{HTML}{D7DEE5} \hypersetup{colorlinks=true,linkcolor=accent,urlcolor=blue} \IfFileExists{build-meta.tex}{\input{build-meta.tex}}{\newcommand{\BuildCommit}{local}} \newcommand{\PublisherDomain}{mpabi} \newcommand{\DocumentAuthor}{M. Pabiszczak} \newcommand{\DocumentYear}{2026} \newcommand{\CardArea}{inf} \newcommand{\CardSeries}{rv32i-freertos} \newcommand{\CardNumber}{01} \newcommand{\CardCount}{14} \newcommand{\CardSlug}{heap4} \newcommand{\CardVersion}{v0.2} \newcommand{\DocumentKey}{\PublisherDomain/\CardArea/\CardSeries/\CardNumber/\CardSlug/\CardVersion} \newcommand{\DocumentUUID}{4654524c-73f2-46df-83a3-d448ba6d6c5a} \lstset{ language=C,basicstyle=\ttfamily\scriptsize,columns=fullflexible, keepspaces=true,frame=single,breaklines=true,showstringspaces=false, numbers=left,numberstyle=\tiny\color{accent},numbersep=6pt, backgroundcolor=\color{accentlight},rulecolor=\color{rulegray} } \pagestyle{fancy} \fancyhf{} \lhead{\textbf{FreeRTOS: heap\_4}} \rhead{\small karta 01/14} \lfoot{\scriptsize commit \BuildCommit} \cfoot{\scriptsize \thepage/\pageref{LastPage}} \rfoot{\scriptsize V11.3.0 / \CardVersion} \setlength{\headheight}{15pt} \setlength{\footskip}{22pt} \setlist[itemize]{nosep,leftmargin=1.5em} \setlist[enumerate]{itemsep=.25em,leftmargin=1.7em} \newcommand{\checkline}{\(\square\)\;} \begin{document} \sloppy \begin{center} {\LARGE\bfseries Karta pracy: FreeRTOS \texttt{heap\_4}}\par \vspace{.4em} {\large model $\rightarrow$ prawdziwy upstream $\rightarrow$ RP2350}\par \end{center} \begin{tabularx}{\textwidth}{@{}lX@{}} \toprule Klucz & \texttt{\DocumentKey} \\ Wersja / commit & \texttt{\CardVersion} / \texttt{\BuildCommit} \\ Data & 14.07.2026 \\ Allocator & FreeRTOS-Kernel V11.3.0, \texttt{9b777ae5c5b8} \\ Port RP2350 & fork Raspberry Pi, \texttt{4f7299d6ea74} \\ Źródło & \texttt{portable/MemMang/heap\_4.c} — bez modyfikacji \\ Punkt wejścia & \texttt{stemctl} \\ \bottomrule \end{tabularx} \section*{Tylko trzy kroki} \begin{enumerate} \item First-fit + split: skąd bierze się drugi nagłówek. \item Free-list + coalescing: dlaczego lista jest uporządkowana po adresie. \item API FreeRTOS: \texttt{pvPortMalloc}, \texttt{vPortFree}, stats, OOM. \end{enumerate} \section*{Warunek zaliczenia} \begin{itemize} \item \checkline przewiduję rozmiary nagłówków i bloków na AMD64/RV32; \item \checkline rozpoznaję fragmentację: suma wolnych bajtów $\neq$ największy blok; \item \checkline pokazuję split i dwa kierunki scalania w Memory; \item \checkline odczytuję \texttt{xStart}, \texttt{pxEnd}, minimum-ever i stack frame; \item \checkline Task 3 daje \texttt{pass=1} na host, Hazard3 i RP2350. \end{itemize} \newpage \section{Start — polecenia i platformy} \begin{lstlisting}[language=bash,numbers=none] 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 \end{lstlisting} \begin{tabularx}{\textwidth}{@{}p{3.1cm}XXX@{}} \toprule & AMD64 & Hazard3 & RP2350 \\ \midrule Task 1--2 & model + sanitizery & model na RTL & build \\ Task 3 & V11.3 + adapter 1-thread & pełny V11.3 + port RISC-V & zgodny core+port RP; allocator V11.3 \\ Debug & GDB & GDB stub RTL & OpenOCD; SRAM \\ Deploy & --- & --- & SPI flash + verify \\ \bottomrule \end{tabularx} \subsection*{Termdebug} \begin{tabularx}{\textwidth}{@{}lXlX@{}} \toprule \texttt{F5} & continue & \texttt{F9} & breakpoint \\ \texttt{F10} & next & \texttt{F11} & step \\ \texttt{Shift-F11} & finish & \texttt{F8} & stepi \\ \texttt{:StudentStack} & frame + stos & \texttt{:StudentLst} & listing ELF-a \\ \bottomrule \end{tabularx} \textbf{Strategia obserwacji}: breakpoint przed zmianą $\rightarrow$ Memory $\rightarrow$ continue/finish $\rightarrow$ Memory. Nie opieramy karty na data watchpointach. \newpage \section{Task 1 — first-fit i split} \subsection*{Policz przed uruchomieniem} \begin{tabular}{@{}lcc@{}} \toprule & AMD64 & RV32 \\ \midrule \texttt{sizeof(ModelBlock)} & \rule{1.6cm}{.2pt} & \rule{1.6cm}{.2pt} \\ request & 13 B & 13 B \\ \texttt{align8(header + request)} & \rule{1.6cm}{.2pt} & \rule{1.6cm}{.2pt} \\ remainder z 256 B & \rule{1.6cm}{.2pt} & \rule{1.6cm}{.2pt} \\ offset payloadu & \rule{1.6cm}{.2pt} & \rule{1.6cm}{.2pt} \\ \bottomrule \end{tabular} \subsection*{Do wykonania} \begin{enumerate} \item Wskaż nagłówek bloku przydzielonego i nagłówek remainder. \item Sprawdź: \texttt{wanted + remainder == 256}. \item Zmień request 13 na 17; przewidź wynik bez uruchamiania. \item W listingu znajdź dodawanie bajtowego offsetu do adresu areny. \end{enumerate} \lstinputlisting{../src/tasks/task01_first_fit_split.c} \newpage \section{Task 2 — lista adresowa i coalescing} \subsection*{Eksperyment} \begin{center} \texttt{A:48 | B:48 | C:48}\quad $\xrightarrow{\text{free A, free C}}$\quad \texttt{A:48 -> C:48}\quad $\xrightarrow{\text{free B}}$\quad \texttt{A:144} \end{center} \subsection*{Do wykonania} \begin{enumerate} \item Zatrzymaj program w \texttt{task02\_fragmented\_checkpoint}. \item Zapisz adresy i rozmiary dwóch elementów free-list. \item Wykonaj \texttt{F5}; zatrzymaj w \texttt{task02\_debug\_checkpoint}. \item Wskaż pierwszy warunek scalania: z blokiem po prawej. \item Wskaż drugi warunek scalania: z blokiem po lewej. \item Wyjaśnij, czemu kolejność po adresie redukuje koszt szukania sąsiadów. \end{enumerate} \subsection*{Tabela obserwacji} \begin{tabular}{@{}lccc@{}} \toprule Stan & liczba bloków & suma & największy \\ \midrule przed B & \rule{1.4cm}{.2pt} & \rule{1.4cm}{.2pt} & \rule{1.4cm}{.2pt} \\ po B & \rule{1.4cm}{.2pt} & \rule{1.4cm}{.2pt} & \rule{1.4cm}{.2pt} \\ \bottomrule \end{tabular} \lstinputlisting{../src/tasks/task02_address_order_coalesce.c} \newpage \section{Task 3 — prawdziwy FreeRTOS \texttt{heap\_4.c}} \subsection*{Sekwencja testowa} \begin{enumerate} \item init przez pierwsze \texttt{pvPortMalloc(1)} i \texttt{vPortFree}; zapisz $F_0$; \item malloc: 24 B, 40 B, 16 B; zapisz $F_1$; \item free pierwszego i trzeciego; oczekuj 2 wolnych bloków; \item free środkowego; oczekuj jednego bloku i $F_{final}=F_0$; \item malloc większy niż heap; oczekuj \texttt{NULL} i jednego hooka. \end{enumerate} \subsection*{Inwarianty — zaznacz po teście} \begin{itemize} \item \checkline $F_0 > F_1$; \item \checkline $F_{final}=F_0$; \item \checkline minimum-ever $\leq F_1$ i nie rośnie po free; \item \checkline każdy payload ma adres podzielny przez 8; \item \checkline OOM zwraca \texttt{NULL}; \item \checkline końcowa free-list ma dokładnie jeden blok. \end{itemize} \lstinputlisting{../src/tasks/task03_freertos_heap4.c} \newpage \section{Czytanie upstream \texttt{heap\_4.c}} \subsection*{Znajdź w pliku — nie czytaj całego od góry} \begin{lstlisting}[language=bash,numbers=none] K=/opt/FreeRTOS-Kernel/portable/MemMang/heap_4.c rg -n 'xHeapStructSize|pvPortMalloc|prvHeapInit' "$K" rg -n 'prvInsertBlockIntoFreeList|vPortFree' "$K" rg -n 'xFreeBytesRemaining|xMinimumEver' "$K" rg -n 'heapADD_WILL_OVERFLOW|heapBLOCK_ALLOCATED' "$K" \end{lstlisting} \begin{itemize}[leftmargin=*,itemsep=2pt] \item \texttt{xHeapStructSize}: dlaczego jest wyrównany oddzielnie od \texttt{sizeof}? \item \texttt{heapBLOCK\_ALLOCATED\_BITMASK}: który bit rozmiaru oznacza właściciela? \item \texttt{pvPortMalloc}: gdzie są overflow, alignment, first-fit i split? \item \texttt{vPortFree}: jak odzyskuje nagłówek z payloadu? \item \texttt{prvInsertBlockIntoFreeList}: gdzie są dwa kierunki scalania? \item \texttt{xMinimumEverFreeBytesRemaining}: dlaczego free go nie zwiększa? \end{itemize} \subsection*{Breakpointy} \begin{lstlisting}[numbers=none] b pvPortMalloc b vPortFree b prvInsertBlockIntoFreeList p xStart p pxEnd p xFreeBytesRemaining p xMinimumEverFreeBytesRemaining x/160bx ucHeap \end{lstlisting} \newpage \section{RP2350 — deploy i dowód sprzętowy} \subsection*{Polecenie} \begin{lstlisting}[language=bash,numbers=none] stemctl probe list stemctl deploy rp2350 freertos heap4 3 \ --device /dev/bus/usb/BBB/DDD \end{lstlisting} \subsection*{Automatyczny test zatrzymuje się dwa razy} \begin{enumerate} \item \texttt{heap4\_fragmented\_checkpoint}: 2 wolne bloki; \item \texttt{task03\_debug\_checkpoint}: heap odtworzony, OOM obsłużony. \end{enumerate} \subsection*{Zapis ucznia} \begin{tabular}{@{}ll@{}} \toprule Wielkość & Wartość \\ \midrule \texttt{initial free} & \rule{4cm}{.2pt} \\ \texttt{after allocations} & \rule{4cm}{.2pt} \\ \texttt{minimum ever} & \rule{4cm}{.2pt} \\ \texttt{final free} & \rule{4cm}{.2pt} \\ \texttt{sp / fp / pc} & \rule{7cm}{.2pt} \\ \bottomrule \end{tabular} \subsection*{Kontrakt} \begin{itemize} \item flash: write + verify; ELF: RISC-V; \item breakpointy sprzętowe, nie data watchpoint; \item \texttt{aligned=1 oom=1 hooks=1 asserts=0 pass=1}; \item \texttt{sp \& 15 == 0}; \item \texttt{rp2350-hardware-ok task=task03 heap\_4=upstream}. \end{itemize} \textbf{Operacje są rozdzielone}: \texttt{debug} ładuje do SRAM; \texttt{deploy} zapisuje trwały obraz do SPI flash. \newpage \section{Podsumowanie i oddanie} \subsection*{Odpowiedz jednym zdaniem} \begin{enumerate} \item Dlaczego \texttt{heap\_4} scala, a nie tylko odkłada blok na listę?\\[.6em] \rule{\textwidth}{.2pt} \item Dlaczego „wolne razem” nie oznacza „można przydzielić jeden duży blok”?\\[.6em] \rule{\textwidth}{.2pt} \item Gdzie leży metadata bloku przydzielonego aplikacji?\\[.6em] \rule{\textwidth}{.2pt} \item Co mierzy minimum-ever-free, a czego nie mierzy?\\[.6em] \rule{\textwidth}{.2pt} \end{enumerate} \subsection*{Oddaj} \begin{itemize} \item \checkline wyniki 3 tasków na AMD64; \item \checkline Hazard3: trzy kody wyjścia 0; \item \checkline zrzut Task 2: przed i po scaleniu; \item \checkline zrzut Task 3: source + listing + Memory + Stack; \item \checkline wynik RP2350 \texttt{rp2350-hardware-ok}; \item \checkline wypełnione inwarianty i cztery odpowiedzi. \end{itemize} \vfill \noindent\textbf{Dalej}: taski FreeRTOS, scheduler, osobne stosy, 1 kHz tick; następnie cienki C++ header wrapper i użycie w projekcie hoveboard. \end{document}