|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.10! root 7: //
! 8: // LUNA システムクロック
! 9: //
! 10:
1.1.1.9 root 11: // システムクロックは実時間または仮想時間のいずれかに同期するため、
12: // システムクロック独自の時刻 stime を持つ。
13: // stime は、割り込みを発生させるごとに、LUNA-I なら 16.67msec、
14: // LUNA88k なら 10msec 進行する。
15:
1.1 root 16: #include "sysclk.h"
1.1.1.6 root 17: #include "config.h"
18: #include "interrupt.h"
1.1.1.10! root 19: #include "rtc.h"
! 20: #include "scheduler.h"
! 21: #include "sync.h"
1.1.1.6 root 22:
1.1.1.10! root 23: // グローバル参照用
! 24: SysClkDevice *gSysClk;
1.1 root 25:
1.1.1.10! root 26: // コンストラクタ
1.1 root 27: SysClkDevice::SysClkDevice()
1.1.1.9 root 28: : inherited("SystemClock")
1.1 root 29: {
1.1.1.9 root 30: AddAlias("SysClk");
31:
1.1 root 32: devaddr = 0x63000000;
33:
1.1.1.10! root 34: monitor.func = ToMonitorCallback(&SysClkDevice::MonitorUpdate);
1.1.1.9 root 35: monitor.SetSize(31, 2);
36: monitor.Regist(ID_MONITOR_SYSCLK);
37:
1.1.1.10! root 38: event.func = ToEventCallback(&SysClkDevice::Callback);
1.1 root 39: event.code = 0;
1.1.1.10! root 40: event.Regist("System Clock");
1.1 root 41: }
42:
1.1.1.10! root 43: // デストラクタ
1.1 root 44: SysClkDevice::~SysClkDevice()
45: {
1.1.1.10! root 46: gSysClk = NULL;
1.1 root 47: }
48:
49: bool
1.1.1.4 root 50: SysClkDevice::Init()
51: {
52: // クロックは機種ごとに異なる
53: const ConfigItem& item = gConfig->Find("!sysclk-period");
1.1.1.9 root 54: period = item.AsInt();
55: event.time = period;
56:
57: // クロックの同期方法
1.1.1.10! root 58: sync_rt = gRTC->GetSyncRealtime();
1.1.1.9 root 59:
1.1.1.4 root 60: return true;
61: }
62:
1.1.1.10! root 63: // 電源オン/リセット
! 64: void
! 65: SysClkDevice::ResetHard(bool poweron)
1.1 root 66: {
1.1.1.10! root 67: // XXX たぶん電源オンだけで作用する?
! 68: if (poweron) {
! 69: if (sync_rt) {
! 70: stime = gSync->GetRealTime();
! 71: }
! 72:
! 73: // 電源オンですぐ起動
! 74: sysint = false;
! 75: gScheduler->RestartEvent(event);
1.1.1.9 root 76: }
1.1 root 77: }
78:
79: uint64
1.1.1.7 root 80: SysClkDevice::Read(uint32 offset)
1.1 root 81: {
1.1.1.3 root 82: // 1 ポートしかない
83: return GetInt();
84: }
1.1 root 85:
1.1.1.3 root 86: uint64
1.1.1.7 root 87: SysClkDevice::Write(uint32 offset, uint32 data)
1.1.1.3 root 88: {
89: // 何か書き込まれたら、フラグをクリア
90: putlog(1, "システムクロック割り込みクリア");
1.1.1.6 root 91: sysint = false;
92: gInterrupt->NegateINT(this);
1.1.1.3 root 93: return 0;
1.1 root 94: }
95:
96: uint64
1.1.1.7 root 97: SysClkDevice::Peek(uint32 offset)
1.1 root 98: {
1.1.1.3 root 99: return GetInt();
100: }
101:
1.1.1.9 root 102: void
103: SysClkDevice::MonitorUpdate(Monitor *, TextScreen& screen)
104: {
105: int y;
106:
107: screen.Clear();
108: y = 0;
109:
110: int width = stime < 86400_sec ? 20 : 25;
111: screen.Print(0, y++, "Sync: %s", sync_rt ? "Real Time" : "Virtual Time");
112: screen.Print(0, y++, "Time: %*s", width, TimeToStr(stime).c_str());
113: }
114:
1.1.1.3 root 115: // 割り込み状態を取得(?)
116: uint8
117: SysClkDevice::GetInt() const
118: {
119: uint8 data = 0;
1.1 root 120:
1.1.1.3 root 121: if (sysint) {
122: data |= 0x80;
1.1 root 123: }
1.1.1.3 root 124: return data;
1.1 root 125: }
126:
127: // イベントハンドラ
128: void
1.1.1.5 root 129: SysClkDevice::Callback(Event& ev)
1.1 root 130: {
131: putlog(3, "システムクロック割り込み発生");
1.1.1.9 root 132:
133: // システムクロックとしての現在時刻。
1.1.1.10! root 134: // 足す前は前回の割り込み発生時刻なので period を足すと現在時刻。
1.1.1.9 root 135: stime += period;
136:
1.1.1.10! root 137: sysint = true;
! 138: gInterrupt->AssertINT(this);
1.1.1.9 root 139:
1.1.1.10! root 140: if (sync_rt) {
! 141: gScheduler->StartRealtimeEvent(ev, stime, period);
1.1.1.9 root 142: } else {
1.1.1.10! root 143: gScheduler->StartEvent(ev);
1.1.1.9 root 144: }
1.1 root 145: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.