C11 — machine timer na RV32I/Hazard3
Karta pokazuje trzy osobne, wykonywalne przykłady obsługi 64-bitowego timera z 32-bitowego rdzenia:
- spójny odczyt
mtimesekwencją high–low–high, również przez rollover; - jednorazowe przerwanie machine timer z
mtimecmp,mie.MTIE,mstatus.MIE, wektorem 7 i powrotemmret; - 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
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 powfi; - Task03: 4 ISR, okres
0x640(1600), deadline’y oddalone dokładnie o okres, obserwowane spóźnienie0x28(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
mtimew Task01 jest wyłącznie fixture’em dostępnego testbencha; kod produkcyjny nie powinien zakładać, że licznik czasu jest zapisywalny. mtimeimtimecmpsą urządzeniami 64-bitowymi widzianymi przez cztery rejestry 32-bitowe. Zwykłe Cuint64_tnie 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 odczytmcausenie czyści źródła. common/init.Sustawiamtvecw tryb wektorowy. Slot 7 wybiera symbolisr_machine_timer; atrybut GCCinterrupt("machine")generujemret.- Model
deadline += periodzachowuje fazę.now + perioduż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
./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.