199 lines
7.4 KiB
TeX
199 lines
7.4 KiB
TeX
\documentclass[10pt]{article}
|
|
\usepackage[T1]{fontenc}\usepackage[utf8]{inputenc}\usepackage[polish]{babel}
|
|
\usepackage[a4paper,margin=1.55cm]{geometry}
|
|
\usepackage{array,tabularx,booktabs,amsmath,amssymb,xcolor,listings,hyperref,fancyhdr,lastpage,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{\CardArea}{inf}
|
|
\newcommand{\CardSeries}{freertos-cpp}
|
|
\newcommand{\CardNumber}{15}
|
|
\newcommand{\CardCount}{16}
|
|
\newcommand{\CardSlug}{isr-drivers}
|
|
\newcommand{\CardVersion}{v00.01}
|
|
\newcommand{\DocumentUUID}{02f6cd71-5c85-4883-a237-1d4ba08d9469}
|
|
\newcommand{\blank}[1]{\rule{#1}{.2pt}}
|
|
\lstset{language=C++,basicstyle=\ttfamily\scriptsize,columns=fullflexible,keepspaces=true,frame=single,breaklines=true,showstringspaces=false,numbers=none,backgroundcolor=\color{accentlight},rulecolor=\color{rulegray}}
|
|
\pagestyle{fancy}\fancyhf{}
|
|
\lhead{\textbf{K15 · FreeRTOS C++ · FromISR}}\rhead{\small L14 · UART + GPIO}
|
|
\lfoot{\scriptsize commit \BuildCommit}\cfoot{\scriptsize \thepage/\pageref{LastPage}}\rfoot{\scriptsize V11.3.0 / \CardVersion}
|
|
\setlength{\headheight}{14pt}\setlength{\footskip}{19pt}
|
|
\setlist[itemize]{nosep,leftmargin=1.45em}\setlist[enumerate]{nosep,leftmargin=1.65em}
|
|
\begin{document}\sloppy
|
|
\begin{center}
|
|
{\LARGE\bfseries Jawne FromISR: UART RX i GPIO edge}\par
|
|
\vspace{.25em}{\large jeden IsrContext, jedna decyzja yield, jawny backpressure}\par
|
|
\end{center}
|
|
\noindent\begin{tabularx}{\textwidth}{@{}p{1.65cm}Xp{1.75cm}X@{}}
|
|
\toprule
|
|
Karta & K15 / \CardCount & Czas & 30 minut \\
|
|
Platforma & Hazard3 / RV32I & IRQ & machine external \\
|
|
RX queue & capacity 1 & Overflow & drop-newest \\
|
|
Wersja & \CardVersion & UUID karty & \texttt{02f6cd71-...} \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section*{Jawny kontrakt handlera}
|
|
\begin{lstlisting}
|
|
IsrContext isr;
|
|
auto byte = uart.isr_view().read_rx_from_isr();
|
|
rx.send_from_isr(byte, isr);
|
|
notify.give_from_isr(isr);
|
|
isr.yield_if_needed(); // dokladnie raz
|
|
\end{lstlisting}
|
|
|
|
\noindent\fcolorbox{accent}{accentlight}{\begin{minipage}{.94\textwidth}
|
|
\textbf{Kontrakt K15.} ISR view nie ma timeoutu ani blocking API. Każde
|
|
\texttt{...FromISR} dokłada żądanie wake do jednego contextu. Handler czyści
|
|
źródła, publikuje bounded dane i dopiero na końcu raz podejmuje decyzję yield.
|
|
\end{minipage}}
|
|
|
|
\section*{Plan 30 minut}
|
|
\noindent\begin{tabularx}{\textwidth}{@{}p{1.35cm}p{3.1cm}X@{}}
|
|
\toprule Czas & Tryb & Dowód \\
|
|
\midrule
|
|
0--5 & views & task view kontra ISR view \\
|
|
5--10 & IRQ & \texttt{mcause=0x8000000b}, ISR stack \\
|
|
10--15 & UART & 0x41 queued, 0x42 dropped \\
|
|
15--20 & GPIO & edge 1--0, notification=1 \\
|
|
20--25 & wake & flag true, yield calls=1 \\
|
|
25--30 & order & receiver przed resume stimulus \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section*{Predykcja}
|
|
Czy drugi bajt zmieści się w pełnej kolejce capacity 1? \blank{2cm}.
|
|
Ile razy handler powinien wywołać yield dla dwóch publikacji? \blank{2cm}.
|
|
|
|
\newpage
|
|
\section{Realny external IRQ i bounded handler}
|
|
|
|
\begin{center}
|
|
\texttt{stimulus: UART[41,42] + GPIO edge + SET\_IRQ}\\
|
|
$\downarrow$ \texttt{machine external trap / ISR stack}\\
|
|
$\downarrow$ \texttt{queue FromISR + notify FromISR + clear sources}\\
|
|
$\downarrow$ \texttt{one yield -- rx-worker -- resume stimulus}
|
|
\end{center}
|
|
|
|
\noindent\begin{tabularx}{\textwidth}{@{}p{5.3cm}p{3.1cm}X@{}}
|
|
\toprule Pomiar & Predykcja & Odczyt \\
|
|
\midrule
|
|
\texttt{mcause} & \texttt{0x8000000b} & \blank{2.5cm} \\
|
|
ISR SP różny od task SP & true & \blank{2.5cm} \\
|
|
external IRQ state po clear & 0 & \blank{2.5cm} \\
|
|
UART ready przed / po ISR & 1 / 0 & \blank{2.5cm} \\
|
|
GPIO edge przed / po ISR & 1 / 0 & \blank{2.5cm} \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section{UART RX i backpressure}
|
|
Dwa bajty czekają w modelu rejestrów, lecz queue ma jedno miejsce. Handler ma
|
|
limit dwóch odczytów; nie wykonuje parsowania ani oczekiwania.
|
|
|
|
\noindent\begin{tabularx}{\textwidth}{@{}p{5.3cm}p{3.1cm}X@{}}
|
|
\toprule Pomiar & Predykcja & Odczyt \\
|
|
\midrule
|
|
queued count / byte & 1 / \texttt{0x41} & \blank{2.5cm} \\
|
|
dropped count / byte & 1 / \texttt{0x42} & \blank{2.5cm} \\
|
|
overflow policy & drop-newest & \blank{2.5cm} \\
|
|
receiver byte & \texttt{0x41} & \blank{2.5cm} \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
Porównaj drop-newest, drop-oldest i overwrite dla UART:\\[.4em]
|
|
\blank{16cm}\\[.8em]\blank{16cm}
|
|
|
|
\newpage
|
|
\section{Task view i ISR view}
|
|
|
|
\noindent\begin{tabularx}{\textwidth}{@{}p{3.2cm}XX@{}}
|
|
\toprule Wrapper & Task view & ISR view \\
|
|
\midrule
|
|
\texttt{Uart} & enable/configure, test inject & ready/read, bez wait \\
|
|
\texttt{GpioPin} & direction/write output & edge pending/clear \\
|
|
\texttt{Queue} & receive(timeout) & send\_from\_isr \\
|
|
\texttt{Notification} & task odbiera & give\_from\_isr \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section{Akumulacja wake i jeden yield}
|
|
\begin{lstlisting}
|
|
BaseType_t local = pdFALSE;
|
|
xQueueSendFromISR(queue, &byte, &local); isr.merge(local);
|
|
local = pdFALSE;
|
|
vTaskNotifyGiveFromISR(worker, &local); isr.merge(local);
|
|
isr.yield_if_needed();
|
|
\end{lstlisting}
|
|
|
|
\noindent\begin{tabularx}{\textwidth}{@{}p{5.3cm}p{3.1cm}X@{}}
|
|
\toprule Pomiar & Predykcja & Odczyt \\
|
|
\midrule
|
|
notification sent/taken & 1 / 1 & \blank{2.5cm} \\
|
|
higher priority task woken & true & \blank{2.5cm} \\
|
|
yield requested & true & \blank{2.5cm} \\
|
|
\texttt{yield\_if\_needed} calls & 1 & \blank{2.5cm} \\
|
|
receiver tick & 1 & \blank{2.5cm} \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section*{Dowód natychmiastowego przełączenia}
|
|
\begin{itemize}
|
|
\item receiver widzi \texttt{stimulus\_after=0};
|
|
\item po powrocie z IRQ stimulus widzi \texttt{receiver\_done=1};
|
|
\item receiver ustawia GPIO output z bitu 0 bajtu \texttt{0x41}: data=1.
|
|
\end{itemize}
|
|
|
|
Co zmieniłby brak yield przy wake=true?\\[.4em]
|
|
\blank{16cm}\\[.8em]\blank{16cm}
|
|
|
|
\section*{Granica ISR}
|
|
Parsing, debounce, logowanie i retry są pracą taska. ISR tylko odczytuje bounded
|
|
FIFO, czyści źródło i publikuje. Static queue/task storage daje heap delta 0.
|
|
|
|
\newpage
|
|
\section{Hazard3/GDB i zaliczenie}
|
|
\begin{lstlisting}[language=bash]
|
|
make check
|
|
riscv64-unknown-elf-gdb build/task01_isr_drivers/prog.elf
|
|
b isr_drivers_debug_checkpoint
|
|
\end{lstlisting}
|
|
\begin{lstlisting}
|
|
p/x g_mcause
|
|
p g_uart_status_before_isr
|
|
p g_uart_status_after_isr
|
|
p g_gpio_edge_before_isr
|
|
p g_gpio_edge_after_isr
|
|
p g_rx_queued
|
|
p/x g_queued_byte
|
|
p g_rx_dropped
|
|
p/x g_dropped_byte
|
|
p g_notification_taken
|
|
p g_higher_priority_task_woken
|
|
p g_isr_yield_calls
|
|
p g_stimulus_after_seen_by_receiver
|
|
p g_receiver_done_at_stimulus_resume
|
|
p g_isr_drivers_pass
|
|
\end{lstlisting}
|
|
|
|
\section*{Zaliczenie}
|
|
\begin{itemize}
|
|
\item $\square$ pokazuję realny external IRQ i osobny ISR stack;
|
|
\item $\square$ używam wyłącznie jawnych metod \texttt{from\_isr};
|
|
\item $\square$ kolejkuję 0x41 i jawnie liczę drop-newest 0x42;
|
|
\item $\square$ clear UART/GPIO zmienia status 1 na 0;
|
|
\item $\square$ akumuluję wake=true i wywołuję yield dokładnie raz;
|
|
\item $\square$ receiver działa przed resume stimulus i ustawia GPIO=1.
|
|
\end{itemize}
|
|
|
|
\section*{Wyjście}
|
|
Dlaczego automatyczne zgadywanie task/ISR contextu osłabia API?\\[.5em]
|
|
\blank{16cm}\\[1em]
|
|
Gdzie zaimplementujesz parsing i debounce, i dlaczego?\\[.5em]
|
|
\blank{16cm}
|
|
|
|
\vfill
|
|
\noindent\textbf{Następna karta K16:} integracja usług RTOS, end-to-end trace,
|
|
memory/stack report, pressure injection i uzasadnienie każdej granicy.
|
|
\end{document}
|