Files
2026-07-21 19:14:20 +02:00

2.9 KiB
Raw Permalink Blame History

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ą highlowhigh, również przez rollover;
  2. jednorazowe przerwanie machine timer z mtimecmp, mie.MTIE, mstatus.MIE, wektorem 7 i powrotem mret;
  3. okresowe deadliney 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 po wfi;
  • Task03: 4 ISR, okres 0x640 (1600), deadliney 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 fixtureem 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

./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 A1A8. Widok A3 jest N/D tylko w Task01; w Task02 i Task03 dowodem dispatchu jest faktyczny wybór slotu mtvec na podstawie przyczyny przerwania.