\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}
