# C11 — machine timer na RV32I/Hazard3 Karta pokazuje trzy osobne, wykonywalne przykłady obsługi 64-bitowego timera z 32-bitowego rdzenia: 1. spójny odczyt `mtime` sekwencją high–low–high, również przez rollover; 2. jednorazowe przerwanie machine timer z `mtimecmp`, `mie.MTIE`, `mstatus.MIE`, wektorem 7 i powrotem `mret`; 3. okresowe deadline’y `deadline += period`, z zapisem czasu planowanego, obserwowanego i spóźnienia każdego ticka. To nie jest model hostowy. Programy są kompilowane jako freestanding RV32I+Zicsr+Zifencei i wykonywane przez RTL Hazard3/Verilator. Testbench inkrementuje `mtime` w każdym kroku oraz wystawia poziomowe żądanie timera, gdy `mtime >= mtimecmp[hart]`. ## Budowanie i dowód wykonania ```sh make tasks ./tests/test_hazard3.sh ``` Test zewnętrzny wymaga kodu wyjścia 0, braku nieobsłużonej pułapki i braku timeoutu, a następnie sprawdza raportowane relacje. Przy bieżącym RTL uzyskano: - Task01: wybrany offset `0x13`, 2 próby, poprawny high po rolloverze; - Task02: dokładnie 1 ISR, `mcause=0x80000007`, pending 0 przed i po, wznowienie po `wfi`; - Task03: 4 ISR, okres `0x640` (1600), deadline’y oddalone dokładnie o okres, obserwowane spóźnienie `0x28` (40) dla każdego ticka. Wartość 40 nie jest kontraktem architektury — zależy od RTL, magistrali, prologu wygenerowanego przez kompilator i chwili próbkowania. Kontraktem karty jest `observed >= scheduled`, poprawna arytmetyka spóźnienia i stały krok deadline’ów. ## Granice i ważne rozróżnienia - Zapis do `mtime` w Task01 jest wyłącznie fixture’em dostępnego testbencha; kod produkcyjny nie powinien zakładać, że licznik czasu jest zapisywalny. - `mtime` i `mtimecmp` są urządzeniami 64-bitowymi widzianymi przez cztery rejestry 32-bitowe. Zwykłe C `uint64_t` nie daje atomowej transakcji MMIO. - Źródłem zdarzenia jest porównanie `mtime >= mtimecmp`. Bity MTIE i MIE tylko przepuszczają pending do rdzenia; nie tworzą zdarzenia i go nie kasują. - Machine timer jest poziomowy. Handler przesuwa `mtimecmp`; samo wejście do ISR ani odczyt `mcause` nie czyści źródła. - `common/init.S` ustawia `mtvec` w tryb wektorowy. Slot 7 wybiera symbol `isr_machine_timer`; atrybut GCC `interrupt("machine")` generuje `mret`. - Model `deadline += period` zachowuje fazę. `now + period` użyte jako jedyna reguła przenosi każde spóźnienie na kolejne wyzwolenie i powoduje dryf. - Karta nie obejmuje jeszcze sterownika RP2350, ticka RTOS, współdzielenia danych z wieloma hartami ani polityki nadrabiania wielu pominiętych okresów. ## Materiały karty ```sh ./scripts/render_card_layouts.sh ./scripts/render_new_pdf.sh ./tests/test_card.sh ``` Każdy z trzech przykładów ma dokładnie widoki A1–A8. Widok A3 jest N/D tylko w Task01; w Task02 i Task03 dowodem dispatchu jest faktyczny wybór slotu `mtvec` na podstawie przyczyny przerwania.