824 lines
46 KiB
JSON
824 lines
46 KiB
JSON
{
|
||
"$schema": "../../../tools/card-layouts/schemas/card-source.schema.json",
|
||
"schema": "esc-card-source.v1",
|
||
"card": {
|
||
"id": "mpabi-inf-c-13-gpio-edges-debounce",
|
||
"series": "c",
|
||
"series_title": "C · Freestanding RV32I and K&R",
|
||
"number": "13",
|
||
"count": "13",
|
||
"slug": "gpio-edges-debounce",
|
||
"title": "GPIO, zbocza i quiet-window debounce",
|
||
"topic": "RV32I/Hazard3: polling GPIO, external IRQ18, debounce i końcowy superloop raw C",
|
||
"project": "Freestanding C na RV32I",
|
||
"subject": "Informatyka",
|
||
"level": "Rok 1 · C13 · RV32I/Hazard3",
|
||
"revision_date": "2026-07-20T00:00:00+02:00",
|
||
"status": "Gotowa",
|
||
"version": "v00.01",
|
||
"uuid": "72e2cbba-4658-5de2-a0dc-8b600ee3f7b0",
|
||
"author": "M. Pabiszczak",
|
||
"year": "2026"
|
||
},
|
||
"generated": {
|
||
"tex": "doc/generated/main.tex",
|
||
"html": "web/index.html",
|
||
"html_css": "web/style.css",
|
||
"html_tree_inspector": false,
|
||
"react_app": true
|
||
},
|
||
"render_dictionary": false,
|
||
"template": "templates/karta-klasyczna.json",
|
||
"title_block": {
|
||
"category": "KARTA PRACY · INFORMATYKA",
|
||
"prepared_by": "M. Pabiszczak",
|
||
"prepared_on": "2026-07-20T00:00:00+02:00",
|
||
"title": "GPIO, zbocza i quiet-window debounce",
|
||
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/29e6021a-d033-5fbe-a5fc-ec03442ac68a",
|
||
"repository_url": "https://zsl-gitea.mpabi.pl/edu-inf/lab-rv32i-c-gpio-edges-debounce",
|
||
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
|
||
"url_domain": "mpabi.pl",
|
||
"doc_uuid": "29e6021a-d033-5fbe-a5fc-ec03442ac68a",
|
||
"revision": "v00.01",
|
||
"issued_on": "2026-07-20T00:00:00+02:00",
|
||
"series": "C-13",
|
||
"document_type": "karta pracy",
|
||
"tool": "card-layouts",
|
||
"show_qr": true,
|
||
"show_repository_qr": true,
|
||
"height_cm": 2.6,
|
||
"repeat_on_every_page": true,
|
||
"replace_front_matter": true
|
||
},
|
||
"front_page_break": true,
|
||
"front_page_scope": {
|
||
"title": "Cel karty",
|
||
"content_tex": "Uczeń rozdziela fizyczny lub modelowany poziom wejścia, detekcję zbocza, zatrzaśnięty pending, maskowanie kontrolera, wybór handlera i efekt wykonywany później przez main. Potrafi zrealizować quiet-window debounce oraz połączyć timer, UART i GPIO w końcowym superloop bez RTOS.",
|
||
"scope_title": "Zakres i zachowane przykłady",
|
||
"scope_content_tex": "Cztery przykłady wykonują się na centralnym modelu RTL Hazard3. TEST\\_IN i UART TEST\\_RX są jawnie wyłącznie bodźcami testbencha. Karta nie udaje modelu RP2350 ani fizycznego pinu. Task01 dowodzi DIR/OUT/IN przez polling, Task02 pełnej ścieżki rising-edge IRQ18 z W1C, Task03 krótkiego ISR i decyzji debounce w main, a Task04 współpracy machine timer, UART IRQ16 i GPIO IRQ18.\\par\\textbf{Układ każdego przykładu:} pełny profil A1--A8; widok N/D ma jawny powód, a diagram nie jest wymagany, gdy tekst daje lepszy dowód.",
|
||
"scope_table": {
|
||
"headers": [
|
||
"Typ",
|
||
"Task",
|
||
"Idea",
|
||
"Waga"
|
||
],
|
||
"rows": [
|
||
{
|
||
"chapter": "POLL",
|
||
"task": "Task01",
|
||
"idea_tex": "kierunek, latch wyjścia i testbench-only bodziec wejścia",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "IRQ18",
|
||
"task": "Task02",
|
||
"idea_tex": "zbocze, pending peryferium, kontroler i resume",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "DBNC",
|
||
"task": "Task03",
|
||
"idea_tex": "krótki ISR, mtime i decyzja stabilności w main",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
},
|
||
{
|
||
"chapter": "LOOP",
|
||
"task": "Task04",
|
||
"idea_tex": "trzy źródła, dwa dispatchery, flagi i efekty main",
|
||
"priority": "kluczowe",
|
||
"key": true
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"side_margin_tree_layout": {
|
||
"columns": [
|
||
{
|
||
"id": "zawodowe",
|
||
"label": "TECH",
|
||
"side": "left",
|
||
"tree": "WE -> EK -> KW",
|
||
"description": "Kod C, ABI i obserwacja RV32I."
|
||
},
|
||
{
|
||
"id": "ogolne",
|
||
"label": "OG",
|
||
"side": "right",
|
||
"tree": "WE -> EN -> KW",
|
||
"description": "Przewidywanie, pomiar i wniosek."
|
||
}
|
||
]
|
||
},
|
||
"learning_effects": {
|
||
"C13.EN01": {
|
||
"bloom_level": "Analiza",
|
||
"label": "Od poziomu wejścia do efektu aplikacji",
|
||
"text": "Uczeń dla każdego zdarzenia wskazuje osobno source, pending, enable, decyzję dispatchera, minimalny efekt ISR i późniejszy efekt normalnego kodu.",
|
||
"assessment_criteria": [
|
||
"C13.KW01"
|
||
]
|
||
},
|
||
"C13.EK01": {
|
||
"bloom_level": "Zastosowanie",
|
||
"label": "Dowód na GPIO/UART/timer RTL",
|
||
"text": "Uczeń uruchamia obrazy RV32I z limitem cykli, odczytuje rejestry MMIO i kontrolera przerwań, przelicza czasy bounce i sprawdza, że main, a nie ISR, wykonuje politykę debounce oraz aktualizuje wyjścia.",
|
||
"assessment_criteria": [
|
||
"C13.KW01"
|
||
]
|
||
}
|
||
},
|
||
"assessment_criteria": {
|
||
"C13.KW01": {
|
||
"text": "Cztery programy kończą się kodem 0 bez timeoutu i nieobsłużonej pułapki. Task01 daje DIR=1 oraz sekwencję IN 2,3,0. Task02 ma jeden IRQ18, PENDING=0x4 w handlerze, source i controller pending 1 przed obsługą oraz 0 po W1C. Task03 zapisuje poziomy 1,0,1, oba odstępy dodatnie i krótsze od quiet=2000, zero wczesnych akceptacji i jedną akceptację po co najmniej quiet. Task04 ma po jednym timer IRQ, UART16 i GPIO18, trzy efekty main, OUT=0x7 oraz IN=0x17.",
|
||
"learning_effects": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
]
|
||
}
|
||
},
|
||
"educational_requirements": {
|
||
"C13.WE01": {
|
||
"text": "Obsługa GPIO i zdarzeń w raw C z jawną granicą bodźca testbench, krótkim ISR, W1C, synchronizacją z main i bez przypisywania modelowi właściwości RP2350.",
|
||
"label": "RV32I/Hazard3: polling GPIO, external IRQ18, debounce i końcowy superloop raw C",
|
||
"learning_effects": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"learning_tree": {
|
||
"schema": "we-learning-tree.v1",
|
||
"policy": "Najpierw przewidywanie, następnie wykonanie i odczyt dowodu.",
|
||
"ogolne": [
|
||
{
|
||
"effect_ref": "C13.EN01",
|
||
"display": "EN C13 01",
|
||
"source": "LOCAL",
|
||
"official": "C",
|
||
"local": "01",
|
||
"kind": "EN",
|
||
"tree_id": "C13.WE01.OG.LOCAL.C.01",
|
||
"text": "Uczeń dla każdego zdarzenia wskazuje osobno source, pending, enable, decyzję dispatchera, minimalny efekt ISR i późniejszy efekt normalnego kodu.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "C13.KW01",
|
||
"display": "KW C13 01",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "C",
|
||
"local": "01",
|
||
"text": "Kod, przewidywanie i pomiar tworzą jeden dowód."
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"zawodowe": [
|
||
{
|
||
"effect_ref": "C13.EK01",
|
||
"display": "EK C13 01",
|
||
"source": "LOCAL",
|
||
"official": "C",
|
||
"local": "01",
|
||
"kind": "EK",
|
||
"tree_id": "C13.WE01.TECH.LOCAL.C.01",
|
||
"text": "Uczeń uruchamia obrazy RV32I z limitem cykli, odczytuje rejestry MMIO i kontrolera przerwań, przelicza czasy bounce i sprawdza, że main, a nie ISR, wykonuje politykę debounce oraz aktualizuje wyjścia.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "C13.KW01",
|
||
"display": "KW C13 01",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "C",
|
||
"local": "01",
|
||
"text": "Kod, przewidywanie i pomiar tworzą jeden dowód."
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"sections": [
|
||
{
|
||
"title": "1 — Rejestr modelu nie jest fizycznym pinem",
|
||
"order": 10,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "GPIO modelu zaczyna się pod adresem \\texttt{0xc0000300}. \\texttt{DIR} wybiera kierunek, \\texttt{OUT/OUT\\_SET/OUT\\_CLR} sterują zatrzaśnięciem wyjściowym, a \\texttt{IN} pokazuje wyjścia dla pinów ustawionych jako output i bodziec zewnętrzny dla pinów input. \\texttt{RISE\\_EN} i \\texttt{FALL\\_EN} wybierają wykrywane zbocza, a \\texttt{PENDING} zatrzaskuje je do zapisu W1C.\n\n\\texttt{TEST\\_IN} istnieje tylko po stronie laboratorium. Pozwala programowi testowemu wywołać zmianę otoczenia bez fizycznego przewodu. Produkcyjny sterownik czyta \\texttt{IN}; nie powinien zawierać zapisu do takiego fixture'u.",
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C13.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "2 — Source, pending i enable to trzy różne fakty",
|
||
"order": 20,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Zmiana 0 na 1 jest source dla detektora rising edge. Włączony bit \\texttt{RISE\\_EN} pozwala zatrzasnąć bit w \\texttt{PENDING}; ten bit utrzymuje poziomową linię GPIO external IRQ18. Kontroler Hazard3 osobno ma per-line enable, priorytet oraz globalne bramki \\texttt{mie.MEIE} i \\texttt{mstatus.MIE}. Dispatcher odczytuje aktywny numer i wywołuje handler z tablicy.\n\nW1C usuwa źródło poziomowego żądania po stronie peryferium. Sam powrót z handlera, odczyt \\texttt{PENDING} ani zamknięcie maski nie potwierdzają zdarzenia.",
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C13.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "3 — Debounce jest decyzją czasu w main",
|
||
"order": 30,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "ISR Task03 robi tylko trzy rzeczy: zapisuje czas i poziom, potwierdza pending przez W1C oraz na końcu publikuje licznik. Main obserwuje kandydata i akceptuje go dopiero wtedy, gdy od ostatniego zbocza minęło quiet window oraz bieżący poziom nadal odpowiada kandydatowi. Każde nowe zbocze przesuwa początek okna.\n\nSekwencja \\texttt{1--0--1} jest kontrolowanym bounce. Oba odstępy są krótsze od 2000 taktów, dlatego żaden z trzech bezpośrednich odczytów nie może zaakceptować stanu. To polityka aplikacji, nie funkcja kontrolera przerwań.",
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C13.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "4 — Superloop jest granicą serii raw C",
|
||
"order": 40,
|
||
"content_kind": "prose",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Task04 łączy machine timer, UART0 RX external IRQ16 i GPIO external IRQ18. ISR-y publikują flagi, a main konsumuje je i ustawia trzy różne bity wyjściowe. Flaga może skleić wiele produkcji, więc nie jest kolejką; zachowanie liczby i kolejności zdarzeń należy do następnej serii FreeRTOS.",
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C13.KW01"
|
||
]
|
||
},
|
||
{
|
||
"title": "Zadania — zachowane przykłady w profilu A1–A8",
|
||
"order": 50,
|
||
"content_kind": "tasks",
|
||
"page_orientation": "portrait",
|
||
"task_refs": [
|
||
"task01",
|
||
"task02",
|
||
"task03",
|
||
"task04"
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_refs": [
|
||
"C13.KW01"
|
||
]
|
||
}
|
||
],
|
||
"tasks": {
|
||
"task01": {
|
||
"title": "Polling DIR, OUT i IN",
|
||
"uuid": "223fada6-43e4-532a-9c9b-e17445857214",
|
||
"prompt_tex": "Przewidź cztery wartości: IN po ustawieniu zewnętrznego pinu 1, OUT po ustawieniu pinu 0, IN przy obu wysokich i IN po wyzerowaniu. Wyjaśnij, dlaczego zapis TEST\\_IN jest dozwolony tylko w fixture testbencha.",
|
||
"criterion": "Oracle: dir=1, external_high=2, out_after_set=1, both_high=3, final_in=0, pass=1 i kod wyjścia 0. PENDING pozostaje 0, ponieważ detektory zboczy są wyłączone.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — dwa źródła widocznego IN",
|
||
"content_tex": "Dla bitu z \\texttt{DIR=1} widoczne \\texttt{IN} pochodzi z latcha \\texttt{OUT}; dla \\texttt{DIR=0} pochodzi z modelowanego wejścia. \\texttt{TEST\\_IN} zmienia tylko tę drugą część i jest bodźcem laboratorium, nie pinem RP2350."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — pin0 output, pin1 input",
|
||
"content_tex": "Maska 0x1 wybiera pin wyjściowy, a 0x2 wejściowy. Rejestry SET i CLR modyfikują latch bez read--modify--write. Jeden odczyt \\texttt{IN} składa oba widoki, dlatego przy obu stanach wysokich wynosi 0x3."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "unavailable",
|
||
"title": "DISPATCH",
|
||
"reason": "Task01 wyłącza detektory zboczy i przerwania; każdy krok jest bezpośrednim pollingiem MMIO, bez ISR, callbacku ani wyboru handlera."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — kontrolowany round trip poziomów",
|
||
"content_tex": "Po external high program widzi 0x2. SET pinu0 daje OUT=0x1 i IN=0x3. CLR pinu0 oraz TEST\\_IN=0 kończą sekwencję IN=0. Te liczby są bitowymi relacjami modelu, nie numerami pinów konkretnej płytki."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — configure, stimulate, sample, clear",
|
||
"content_tex": "Program wyłącza edge enable, czyści pending, ustawia kierunek i stan początkowy. Następnie podaje bodziec wejściowy, próbkuje, ustawia output, próbkuje ponownie i zeruje oba źródła. Każdy pomiar następuje po odpowiadającym mu zapisie MMIO."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — 0x2 → 0x3 → 0x0",
|
||
"content_tex": "Widoczny stan portu przechodzi kolejno przez tylko input high, oba bity high i oba low. Kierunek pozostaje 0x1 przez cały eksperyment, a pending pozostaje pusty."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — rzeczywiste transakcje pod 0xc0000300",
|
||
"content_tex": "Log RTL raportuje 1,2,1,3,0 i pass=1. Listing powinien pokazać osobne zapisy do offsetów DIR, TEST\\_IN, OUT\\_SET i OUT\\_CLR oraz odczyty IN; nie ma wejścia do wspólnego dispatchera external IRQ."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — polling z jawną granicą fixture",
|
||
"content_tex": "Wzorzec produkcyjny konfiguruje kierunek i czyta wejście lub steruje wyjściem. Warstwa testowa może dostarczyć osobny mechanizm wstrzyknięcia, ale jego nazwa, dokumentacja i lokalizacja muszą uniemożliwiać pomylenie z rejestrem sprzętu."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — dwa źródła widocznego IN",
|
||
"content_tex": "\\textbf{Zachowany przykład:} \\nolinkurl{src/tasks/task01_gpio_polling.c}.\\par Dla bitu z \\texttt{DIR=1} widoczne \\texttt{IN} pochodzi z latcha \\texttt{OUT}; dla \\texttt{DIR=0} pochodzi z modelowanego wejścia. \\texttt{TEST\\_IN} zmienia tylko tę drugą część i jest bodźcem laboratorium, nie pinem RP2350."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — pin0 output, pin1 input",
|
||
"content_tex": "Maska 0x1 wybiera pin wyjściowy, a 0x2 wejściowy. Rejestry SET i CLR modyfikują latch bez read--modify--write. Jeden odczyt \\texttt{IN} składa oba widoki, dlatego przy obu stanach wysokich wynosi 0x3."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a3",
|
||
"title": "A3 DISPATCH · N/D",
|
||
"content_tex": "\\textbf{N/D.} Task01 wyłącza detektory zboczy i przerwania; każdy krok jest bezpośrednim pollingiem MMIO, bez ISR, callbacku ani wyboru handlera."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — kontrolowany round trip poziomów",
|
||
"content_tex": "Po external high program widzi 0x2. SET pinu0 daje OUT=0x1 i IN=0x3. CLR pinu0 oraz TEST\\_IN=0 kończą sekwencję IN=0. Te liczby są bitowymi relacjami modelu, nie numerami pinów konkretnej płytki."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a5",
|
||
"title": "A5 FLOW · AKTYWNE — configure, stimulate, sample, clear",
|
||
"content_tex": "Program wyłącza edge enable, czyści pending, ustawia kierunek i stan początkowy. Następnie podaje bodziec wejściowy, próbkuje, ustawia output, próbkuje ponownie i zeruje oba źródła. Każdy pomiar następuje po odpowiadającym mu zapisie MMIO."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a6",
|
||
"title": "A6 STATE · AKTYWNE — 0x2 → 0x3 → 0x0",
|
||
"content_tex": "Widoczny stan portu przechodzi kolejno przez tylko input high, oba bity high i oba low. Kierunek pozostaje 0x1 przez cały eksperyment, a pending pozostaje pusty."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — rzeczywiste transakcje pod 0xc0000300",
|
||
"content_tex": "Log RTL raportuje 1,2,1,3,0 i pass=1. Listing powinien pokazać osobne zapisy do offsetów DIR, TEST\\_IN, OUT\\_SET i OUT\\_CLR oraz odczyty IN; nie ma wejścia do wspólnego dispatchera external IRQ."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — polling z jawną granicą fixture",
|
||
"content_tex": "Wzorzec produkcyjny konfiguruje kierunek i czyta wejście lub steruje wyjściem. Warstwa testowa może dostarczyć osobny mechanizm wstrzyknięcia, ale jego nazwa, dokumentacja i lokalizacja muszą uniemożliwiać pomylenie z rejestrem sprzętu."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task01.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Przewidź cztery wartości: IN po ustawieniu zewnętrznego pinu 1, OUT po ustawieniu pinu 0, IN przy obu wysokich i IN po wyzerowaniu. Wyjaśnij, dlaczego zapis TEST\\_IN jest dozwolony tylko w fixture testbencha.",
|
||
"evidence_tex": "Tabela DIR/OUT/IN przed uruchomieniem, log wykonania RTL Hazard3 z kodem wyjścia, odczyt rejestrów MMIO i wniosek oddzielający fixture TEST\\_IN od produkcyjnego API GPIO.",
|
||
"criterion": "Oracle: dir=1, external_high=2, out_after_set=1, both_high=3, final_in=0, pass=1 i kod wyjścia 0. PENDING pozostaje 0, ponieważ detektory zboczy są wyłączone."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task01.worksheet",
|
||
"title": "TASK01 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Log RTL: DIR, OUT i kolejne wartości IN}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Granica modelu: TEST\\_IN kontra fizyczny pin}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C13.KW01"
|
||
},
|
||
"task02": {
|
||
"title": "Rising edge, IRQ18 i W1C",
|
||
"uuid": "93fb66db-d0ac-5fc2-811e-5b28e072a346",
|
||
"prompt_tex": "Rozpisz ścieżkę od zmiany TEST\\_IN 0→1 do wznowienia main. Zaznacz GPIO PENDING, pending linii 18 w kontrolerze, dwa poziomy enable, decyzję dispatchera, zapis W1C i efekt ponownego podania tego samego poziomu.",
|
||
"criterion": "Jeden handler IRQ18 widzi PENDING=0x4 i poziom high. GPIO source oraz controller pending są 1 przed globalnym enable i 0 po W1C; high→high nie tworzy nowego pending, resume=1, pass=1.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — zbocze tworzy zatrzaśnięty fakt",
|
||
"content_tex": "Bodziec TEST\\_IN zmienia pin2 z 0 na 1. Włączony bit RISE\\_EN tworzy bit 0x4 w GPIO PENDING, a ten utrzymuje external IRQ18. TEST\\_IN jest sztuczny, lecz dalsza ścieżka przez kontroler i rdzeń jest rzeczywistą ścieżką modelu RTL."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — dwa pending i tablica handlerów",
|
||
"content_tex": "Pierwszy pending leży w peryferium jako maska pinów. Drugi jest widokiem aktywnej linii 18 w kontrolerze Hazard3. Tablica \\texttt{\\_external\\_irq\\_table[18]} przechowuje adres zwykłej funkcji handlera."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "enabled",
|
||
"title": "DISPATCH — external vector wybiera linię 18",
|
||
"content_tex": "\\texttt{mtvec} wybiera wspólny vector machine external interrupt. \\texttt{irq\\_dispatch.S} odczytuje aktywną linię z \\texttt{meinext}, indeksuje tablicę i wykonuje pośredni \\texttt{jalr} do handlera GPIO. Handler potwierdza, że bieżący numer to 18."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — jedno zbocze, jedno wznowienie",
|
||
"content_tex": "Program celowo generuje edge przy zamkniętym globalnym MIE. Dzięki temu może najpierw zmierzyć oba pending jako 1. Po otwarciu MIE oczekuje dokładnie jednego handlera, W1C, obu pending równych 0 i wykonania kodu resume."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — source → pending → enable → dispatch → W1C",
|
||
"content_tex": "0→1 ustawia GPIO PENDING. Włączona linia18, MEIE i później MIE dopuszczają trap. Dispatcher wybiera handler18; ISR próbkuje maskę i poziom, zapisuje tę maskę do PENDING jako W1C, a dopiero potem publikuje count. Main wraca i mierzy stan 0."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — IDLE, LATCHED, HANDLING, ACKED, RESUMED",
|
||
"content_tex": "IDLE ma input low i pending 0. Rising edge tworzy LATCHED. Otwarcie MIE prowadzi do HANDLING. Zapis W1C tworzy ACKED, a powrót dispatchera RESUMED. Ponowne high pozostaje ACKED, ponieważ nie zaszła zmiana 0→1."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — 0x4 w GPIO i 18 w kontrolerze",
|
||
"content_tex": "Raport daje count=1, irq=0x12, source/controller przed 1, pending w ISR 0x4, oba pending po 0 i same-level 0. Listing ma zawierać handler GPIO oraz wspólny dispatcher zakończony \\texttt{mret}."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — acknowledge peripheral before publish",
|
||
"content_tex": "Dla poziomowego IRQ najpierw ustal i usuń przyczynę po stronie peryferium, a dopiero potem publikuj zakończenie dla main. Zamknięcie maski może odłożyć obsługę, ale nie jest potwierdzeniem zdarzenia."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — zbocze tworzy zatrzaśnięty fakt",
|
||
"content_tex": "\\textbf{Zachowany przykład:} \\nolinkurl{src/tasks/task02_gpio_rising_irq.c}.\\par Bodziec TEST\\_IN zmienia pin2 z 0 na 1. Włączony bit RISE\\_EN tworzy bit 0x4 w GPIO PENDING, a ten utrzymuje external IRQ18. TEST\\_IN jest sztuczny, lecz dalsza ścieżka przez kontroler i rdzeń jest rzeczywistą ścieżką modelu RTL."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — dwa pending i tablica handlerów",
|
||
"content_tex": "Pierwszy pending leży w peryferium jako maska pinów. Drugi jest widokiem aktywnej linii 18 w kontrolerze Hazard3. Tablica \\texttt{\\_external\\_irq\\_table[18]} przechowuje adres zwykłej funkcji handlera."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a3",
|
||
"title": "A3 DISPATCH · AKTYWNE — external vector wybiera linię 18",
|
||
"content_tex": "\\texttt{mtvec} wybiera wspólny vector machine external interrupt. \\texttt{irq\\_dispatch.S} odczytuje aktywną linię z \\texttt{meinext}, indeksuje tablicę i wykonuje pośredni \\texttt{jalr} do handlera GPIO. Handler potwierdza, że bieżący numer to 18."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — jedno zbocze, jedno wznowienie",
|
||
"content_tex": "Program celowo generuje edge przy zamkniętym globalnym MIE. Dzięki temu może najpierw zmierzyć oba pending jako 1. Po otwarciu MIE oczekuje dokładnie jednego handlera, W1C, obu pending równych 0 i wykonania kodu resume."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a5",
|
||
"title": "A5 FLOW · AKTYWNE — source → pending → enable → dispatch → W1C",
|
||
"content_tex": "0→1 ustawia GPIO PENDING. Włączona linia18, MEIE i później MIE dopuszczają trap. Dispatcher wybiera handler18; ISR próbkuje maskę i poziom, zapisuje tę maskę do PENDING jako W1C, a dopiero potem publikuje count. Main wraca i mierzy stan 0."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a6",
|
||
"title": "A6 STATE · AKTYWNE — IDLE, LATCHED, HANDLING, ACKED, RESUMED",
|
||
"content_tex": "IDLE ma input low i pending 0. Rising edge tworzy LATCHED. Otwarcie MIE prowadzi do HANDLING. Zapis W1C tworzy ACKED, a powrót dispatchera RESUMED. Ponowne high pozostaje ACKED, ponieważ nie zaszła zmiana 0→1."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — 0x4 w GPIO i 18 w kontrolerze",
|
||
"content_tex": "Raport daje count=1, irq=0x12, source/controller przed 1, pending w ISR 0x4, oba pending po 0 i same-level 0. Listing ma zawierać handler GPIO oraz wspólny dispatcher zakończony \\texttt{mret}."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — acknowledge peripheral before publish",
|
||
"content_tex": "Dla poziomowego IRQ najpierw ustal i usuń przyczynę po stronie peryferium, a dopiero potem publikuj zakończenie dla main. Zamknięcie maski może odłożyć obsługę, ale nie jest potwierdzeniem zdarzenia."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task02.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Rozpisz ścieżkę od zmiany TEST\\_IN 0→1 do wznowienia main. Zaznacz GPIO PENDING, pending linii 18 w kontrolerze, dwa poziomy enable, decyzję dispatchera, zapis W1C i efekt ponownego podania tego samego poziomu.",
|
||
"evidence_tex": "Przewidywany łańcuch source--pending--enable--dispatch--effect, log RTL z IRQ18 i stanami przed/po, listing wspólnego dispatchera oraz wniosek wyjaśniający W1C i brak drugiego zbocza dla high→high.",
|
||
"criterion": "Jeden handler IRQ18 widzi PENDING=0x4 i poziom high. GPIO source oraz controller pending są 1 przed globalnym enable i 0 po W1C; high→high nie tworzy nowego pending, resume=1, pass=1."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task02.worksheet",
|
||
"title": "TASK02 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Log RTL: pending GPIO i kontrolera przed/po ISR}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Dowód dispatchu IRQ18 i zapisu W1C}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C13.KW01"
|
||
},
|
||
"task03": {
|
||
"title": "Quiet-window debounce po trzech zboczach",
|
||
"uuid": "a2e3b023-04f1-5863-a4e0-360b5ec69b89",
|
||
"prompt_tex": "Dla sekwencji poziomów 1,0,1 oblicz oba odstępy i porównaj z quiet=2000. Wyjaśnij, dlaczego ISR publikuje czas, lecz nie akceptuje przycisku, oraz jak nowe zbocze restartuje okno ciszy.",
|
||
"criterion": "Poziomy 1,0,1, count=3 i IRQ18. Oba gapy są dodatnie i mniejsze od quiet=2000; early=0, accepted=1, zaakceptowany poziom high, accepted_after >= quiet i pass=1.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — IRQ rejestruje zmianę, nie intencję użytkownika",
|
||
"content_tex": "Trzy przejścia TEST\\_IN modelują bounce, nie trzy świadome naciśnięcia. Kontroler potrafi zgłosić rising i falling edge, lecz nie zna quiet window ani znaczenia stabilnego przycisku. Ta semantyka należy do kodu normalnego."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — historia ISR i kandydat main",
|
||
"content_tex": "ISR zapisuje trzy pary \\texttt{level,time}, a osobno publikuje ostatni poziom, ostatni czas i count. Main utrzymuje seen count, candidate level oraz candidate time. Krytyczna sekcja chroni snapshot 64-bitowego czasu na RV32."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "enabled",
|
||
"title": "DISPATCH — każde włączone zbocze wybiera GPIO18",
|
||
"content_tex": "RISE\\_EN i FALL\\_EN pozwalają trzem przejściom utworzyć pending. External dispatcher trzy razy wybiera wpis 18 i wywołuje ten sam krótki handler. Numer ostatniego handlera oraz count=3 są dowodem decyzji, nie sam fakt zapisu TEST\\_IN."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — restart okna po każdym bounce",
|
||
"content_tex": "Po każdym nowym count main zastępuje candidate time czasem ostatniego zbocza. Natychmiastowe próby dają early=0. Dopiero stabilny high utrzymany przez co najmniej 2000 taktów daje accepted=1."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — ISR publish, main observe, wait, validate",
|
||
"content_tex": "ISR czyta pending, poziom i mtime, zapisuje rekord, wykonuje W1C i na końcu zwiększa count. Main atomowo pobiera publikację, aktualizuje kandydata, mierzy wiek oraz porównuje bieżący IN. Nowe zbocze wraca do początku okna."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — HIGH?, LOW?, HIGH?, STABLE_HIGH",
|
||
"content_tex": "Pierwsze high jest kandydatem, low unieważnia go, a drugie high tworzy nowego kandydata. Żaden stan z wiekiem mniejszym niż quiet nie jest zaakceptowany. STABLE\\_HIGH powstaje dopiero po pełnym oknie bez kolejnego IRQ."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — dwa bounce gapy krótsze od 0x7d0",
|
||
"content_tex": "Bieżący RTL raportuje czasy low 0x591, 0x8ea, 0xc43, czyli oba gapy 0x359. Akceptacja następuje po 0x878 od ostatniego edge. Konkretne czasy zależą od buildu; oracle niezależnie sprawdza tylko relacje gap<quiet i accepted\\_after>=quiet."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — timestamp in ISR, policy in consumer",
|
||
"content_tex": "ISR powinien szybko potwierdzić sprzęt i opublikować minimalne dane. Konsument może wtedy zmieniać quiet window, politykę akceptacji lub raportowanie bez wydłużania czasu blokowania innych przerwań."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — IRQ rejestruje zmianę, nie intencję użytkownika",
|
||
"content_tex": "\\textbf{Zachowany przykład:} \\nolinkurl{src/tasks/task03_gpio_quiet_window.c}.\\par Trzy przejścia TEST\\_IN modelują bounce, nie trzy świadome naciśnięcia. Kontroler potrafi zgłosić rising i falling edge, lecz nie zna quiet window ani znaczenia stabilnego przycisku. Ta semantyka należy do kodu normalnego."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — historia ISR i kandydat main",
|
||
"content_tex": "ISR zapisuje trzy pary \\texttt{level,time}, a osobno publikuje ostatni poziom, ostatni czas i count. Main utrzymuje seen count, candidate level oraz candidate time. Krytyczna sekcja chroni snapshot 64-bitowego czasu na RV32."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a3",
|
||
"title": "A3 DISPATCH · AKTYWNE — każde włączone zbocze wybiera GPIO18",
|
||
"content_tex": "RISE\\_EN i FALL\\_EN pozwalają trzem przejściom utworzyć pending. External dispatcher trzy razy wybiera wpis 18 i wywołuje ten sam krótki handler. Numer ostatniego handlera oraz count=3 są dowodem decyzji, nie sam fakt zapisu TEST\\_IN."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — restart okna po każdym bounce",
|
||
"content_tex": "Po każdym nowym count main zastępuje candidate time czasem ostatniego zbocza. Natychmiastowe próby dają early=0. Dopiero stabilny high utrzymany przez co najmniej 2000 taktów daje accepted=1."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a5",
|
||
"title": "A5 FLOW · AKTYWNE — ISR publish, main observe, wait, validate",
|
||
"content_tex": "ISR czyta pending, poziom i mtime, zapisuje rekord, wykonuje W1C i na końcu zwiększa count. Main atomowo pobiera publikację, aktualizuje kandydata, mierzy wiek oraz porównuje bieżący IN. Nowe zbocze wraca do początku okna."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a6",
|
||
"title": "A6 STATE · AKTYWNE — HIGH?, LOW?, HIGH?, STABLE_HIGH",
|
||
"content_tex": "Pierwsze high jest kandydatem, low unieważnia go, a drugie high tworzy nowego kandydata. Żaden stan z wiekiem mniejszym niż quiet nie jest zaakceptowany. STABLE\\_HIGH powstaje dopiero po pełnym oknie bez kolejnego IRQ."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — dwa bounce gapy krótsze od 0x7d0",
|
||
"content_tex": "Bieżący RTL raportuje czasy low 0x591, 0x8ea, 0xc43, czyli oba gapy 0x359. Akceptacja następuje po 0x878 od ostatniego edge. Konkretne czasy zależą od buildu; oracle niezależnie sprawdza tylko relacje gap<quiet i accepted\\_after>=quiet."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — timestamp in ISR, policy in consumer",
|
||
"content_tex": "ISR powinien szybko potwierdzić sprzęt i opublikować minimalne dane. Konsument może wtedy zmieniać quiet window, politykę akceptacji lub raportowanie bez wydłużania czasu blokowania innych przerwań."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task03.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Dla sekwencji poziomów 1,0,1 oblicz oba odstępy i porównaj z quiet=2000. Wyjaśnij, dlaczego ISR publikuje czas, lecz nie akceptuje przycisku, oraz jak nowe zbocze restartuje okno ciszy.",
|
||
"evidence_tex": "Przewidywana sekwencja kandydatów, log RTL z trzema czasami i poziomami, niezależne przeliczenie gapów oraz accepted\\_after i wniosek przypisujący politykę debounce do main.",
|
||
"criterion": "Poziomy 1,0,1, count=3 i IRQ18. Oba gapy są dodatnie i mniejsze od quiet=2000; early=0, accepted=1, zaakceptowany poziom high, accepted_after >= quiet i pass=1."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task03.worksheet",
|
||
"title": "TASK03 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Log RTL: trzy poziomy, czasy i gapy}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Dowód quiet window i miejsca decyzji w main}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C13.KW01"
|
||
},
|
||
"task04": {
|
||
"title": "Timer + UART16 + GPIO18 bez RTOS",
|
||
"uuid": "ebb18b6a-cf31-5595-9901-ac2ac870296f",
|
||
"prompt_tex": "Dla timer tick, bajtu U i rising edge narysuj trzy osobne ścieżki source--pending--enable--dispatcher--ISR--flag--main effect. Wyjaśnij, dlaczego trzy flagi nie są kolejką i jakie ograniczenie przechodzi do serii FreeRTOS.",
|
||
"criterion": "Po jednym timer IRQ z mcause=0x80000007, UART IRQ16 z bajtem 0x55 i GPIO IRQ18 z high. Main konsumuje każdą flagę raz, ustawia trzy bity, OUT=0x7, IN=0x17, pass=1.",
|
||
"conclusion_tex": "",
|
||
"render_task_acceptance": false,
|
||
"viewpoints": [
|
||
{
|
||
"id": "A1",
|
||
"status": "enabled",
|
||
"title": "CONTEXT — trzy usługi, wspólny czas CPU",
|
||
"content_tex": "Machine timer pochodzi z mtime>=mtimecmp, UART16 z niepustego RX FIFO przy włączonym RX IRQ, a GPIO18 z rising edge zatrzaśniętego w PENDING. TEST\\_RX i TEST\\_IN tworzą tylko bodźce; logika timer/UART/GPIO po nich jest rzeczywistym modelem RTL."
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"status": "enabled",
|
||
"title": "STRUCTURE — trzy publikacje i trzy bity efektu",
|
||
"content_tex": "Każda usługa ma licznik ISR, payload i flagę. Main ma osobny licznik konsumpcji. Bity OUT 0,1,2 reprezentują odpowiednio efekt GPIO, UART i timera, więc końcowe 0x7 dowodzi wykonania trzech gałęzi bez ukrywania ich w jednej sumie."
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"status": "enabled",
|
||
"title": "DISPATCH — slot 7 oraz external 16/18",
|
||
"content_tex": "Machine timer cause 7 trafia bezpośrednio do \\texttt{isr\\_machine\\_timer} i wraca przez \\texttt{mret}. Machine external vector trafia do wspólnego dispatchera; \\texttt{meinext} wybiera wpis 16 dla UART albo 18 dla GPIO i wykonuje \\texttt{jalr}."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"status": "enabled",
|
||
"title": "APPLICATION — efekt dopiero po konsumpcji flagi",
|
||
"content_tex": "UART handler publikuje U, GPIO handler high, a timer handler tick. Żaden ISR nie ustawia aplikacyjnego bitu OUT. Superloop atomowo zabiera flagę i dopiero jego trzy gałęzie ustawiają 0x2, 0x1 i 0x4."
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"status": "enabled",
|
||
"title": "FLOW — source → pending → dispatch → ISR → main",
|
||
"content_tex": "Timer: comparator→MTIP→slot7→tick flag→bit2. UART: RX FIFO→IRQ16→external dispatcher→read DATA i flag→bit1. GPIO: edge→PENDING→IRQ18→dispatcher→W1C i flag→bit0. Main używa WFI tylko wtedy, gdy nadal brakuje któregoś efektu."
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"status": "enabled",
|
||
"title": "STATE — trzy niezależne PRODUCED/CONSUMED",
|
||
"content_tex": "Każda usługa przechodzi IDLE→PRODUCED w ISR i PRODUCED→CONSUMED w main. Stan końcowy wymaga trzech liczników konsumpcji równych 1. Flaga wraca do 0, ale licznik zachowuje dowód przejścia."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"status": "enabled",
|
||
"title": "RUNTIME — cause 7, linie 16/18 i OUT 0x7",
|
||
"content_tex": "Raport daje timer count 1 i mcause 0x80000007, UART count 1/irq 0x10/byte 0x55, GPIO count 1/irq 0x12/high oraz trzy main actions po 1. OUT=0x7, a IN=0x17 dodaje widoczny wysoki pin wejściowy 0x10."
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"status": "enabled",
|
||
"title": "PATTERNS — ISR-to-main flags with an explicit ceiling",
|
||
"content_tex": "Jednokomórkowa flaga jest poprawna tylko wtedy, gdy wystarcza informacja co najmniej jedno zdarzenie. Nie zachowuje liczby ani kolejności wielu produkcji. Ten sufit jest powodem przejścia do kolejek i tasków FreeRTOS, a nie pretekstem do nazywania flagi kolejką."
|
||
}
|
||
],
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a1",
|
||
"title": "A1 CONTEXT · AKTYWNE — trzy usługi, wspólny czas CPU",
|
||
"content_tex": "\\textbf{Zachowany przykład:} \\nolinkurl{src/tasks/task04_raw_c_superloop.c}.\\par Machine timer pochodzi z mtime>=mtimecmp, UART16 z niepustego RX FIFO przy włączonym RX IRQ, a GPIO18 z rising edge zatrzaśniętego w PENDING. TEST\\_RX i TEST\\_IN tworzą tylko bodźce; logika timer/UART/GPIO po nich jest rzeczywistym modelem RTL."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a2",
|
||
"title": "A2 STRUCTURE · AKTYWNE — trzy publikacje i trzy bity efektu",
|
||
"content_tex": "Każda usługa ma licznik ISR, payload i flagę. Main ma osobny licznik konsumpcji. Bity OUT 0,1,2 reprezentują odpowiednio efekt GPIO, UART i timera, więc końcowe 0x7 dowodzi wykonania trzech gałęzi bez ukrywania ich w jednej sumie."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a3",
|
||
"title": "A3 DISPATCH · AKTYWNE — slot 7 oraz external 16/18",
|
||
"content_tex": "Machine timer cause 7 trafia bezpośrednio do \\texttt{isr\\_machine\\_timer} i wraca przez \\texttt{mret}. Machine external vector trafia do wspólnego dispatchera; \\texttt{meinext} wybiera wpis 16 dla UART albo 18 dla GPIO i wykonuje \\texttt{jalr}."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a4",
|
||
"title": "A4 APPLICATION · AKTYWNE — efekt dopiero po konsumpcji flagi",
|
||
"content_tex": "UART handler publikuje U, GPIO handler high, a timer handler tick. Żaden ISR nie ustawia aplikacyjnego bitu OUT. Superloop atomowo zabiera flagę i dopiero jego trzy gałęzie ustawiają 0x2, 0x1 i 0x4."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a5",
|
||
"title": "A5 FLOW · AKTYWNE — source → pending → dispatch → ISR → main",
|
||
"content_tex": "Timer: comparator→MTIP→slot7→tick flag→bit2. UART: RX FIFO→IRQ16→external dispatcher→read DATA i flag→bit1. GPIO: edge→PENDING→IRQ18→dispatcher→W1C i flag→bit0. Main używa WFI tylko wtedy, gdy nadal brakuje któregoś efektu."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a6",
|
||
"title": "A6 STATE · AKTYWNE — trzy niezależne PRODUCED/CONSUMED",
|
||
"content_tex": "Każda usługa przechodzi IDLE→PRODUCED w ISR i PRODUCED→CONSUMED w main. Stan końcowy wymaga trzech liczników konsumpcji równych 1. Flaga wraca do 0, ale licznik zachowuje dowód przejścia."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a7",
|
||
"title": "A7 RUNTIME · AKTYWNE — cause 7, linie 16/18 i OUT 0x7",
|
||
"content_tex": "Raport daje timer count 1 i mcause 0x80000007, UART count 1/irq 0x10/byte 0x55, GPIO count 1/irq 0x12/high oraz trzy main actions po 1. OUT=0x7, a IN=0x17 dodaje widoczny wysoki pin wejściowy 0x10."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.a8",
|
||
"title": "A8 PATTERNS · AKTYWNE — ISR-to-main flags with an explicit ceiling",
|
||
"content_tex": "Jednokomórkowa flaga jest poprawna tylko wtedy, gdy wystarcza informacja co najmniej jedno zdarzenie. Nie zachowuje liczby ani kolejności wielu produkcji. Ten sufit jest powodem przejścia do kolejek i tasków FreeRTOS, a nie pretekstem do nazywania flagi kolejką."
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "task04.proof",
|
||
"title": "Przewidywanie → wykonanie → wniosek",
|
||
"prompt_tex": "Dla timer tick, bajtu U i rising edge narysuj trzy osobne ścieżki source--pending--enable--dispatcher--ISR--flag--main effect. Wyjaśnij, dlaczego trzy flagi nie są kolejką i jakie ograniczenie przechodzi do serii FreeRTOS.",
|
||
"evidence_tex": "Trzy przewidywane ścieżki zdarzeń, log RTL z numerami przerwań i licznikami, listing machine-timer oraz external dispatchera, końcowe OUT/IN i wniosek o granicy flag jednozdarzeniowych.",
|
||
"criterion": "Po jednym timer IRQ z mcause=0x80000007, UART IRQ16 z bajtem 0x55 i GPIO IRQ18 z high. Main konsumuje każdą flagę raz, ustawia trzy bity, OUT=0x7, IN=0x17, pass=1."
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "task04.worksheet",
|
||
"title": "TASK04 · Zapis dowodu ucznia",
|
||
"content_tex": "\\textbf{1. Przewidywanie przed uruchomieniem}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{2. Log RTL: timer, UART16, GPIO18 i efekty main}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{3. Dowód dwóch dispatcherów i końcowego OUT/IN}\\par\\noindent\\dotfill\\par\\noindent\\dotfill\\par\\textbf{4. Wniosek: reguła języka lub kontrakt targetu potwierdzony przez pomiar}\\par\\noindent\\dotfill\\par\\noindent\\dotfill"
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"C13.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"C13.EN01",
|
||
"C13.EK01"
|
||
],
|
||
"assessment_criterion_ref": "C13.KW01"
|
||
}
|
||
},
|
||
"tasks_order": [
|
||
"task01",
|
||
"task02",
|
||
"task03",
|
||
"task04"
|
||
]
|
||
}
|