66 lines
2.9 KiB
Markdown
66 lines
2.9 KiB
Markdown
# 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.
|