--- nono/vm/mpscc.cpp 2026/04/29 17:05:14 1.1.1.2 +++ nono/vm/mpscc.cpp 2026/04/29 17:05:17 1.1.1.3 @@ -23,7 +23,7 @@ #include "hostcom.h" #include "interrupt.h" #include "scheduler.h" -#include "sync.h" +#include "syncer.h" #include // @@ -59,8 +59,8 @@ MPSCCChan::Init(int id_) // // コンストラクタ -MPSCCDevice::MPSCCDevice(const std::string& objname_) - : inherited(objname_) +MPSCCDevice::MPSCCDevice() + : inherited(OBJ_MPSCC) { for (int ch = 0; ch < mpscc.chan.size(); ch++) { auto& chan = mpscc.chan[ch]; @@ -119,7 +119,13 @@ MPSCCDevice::SetLogLevel(int loglevel_) bool MPSCCDevice::Init() { - gScheduler->ConnectMessage(MessageID::HOSTCOM_RX, this, + if (inherited::Init() == false) { + return false; + } + + interrupt = GetInterruptDevice(); + + scheduler->ConnectMessage(MessageID::HOSTCOM_RX, this, ToMessageCallback(&MPSCCDevice::RxMessageCallback)); return true; } @@ -159,7 +165,8 @@ MPSCCDevice::GetCR0(const MPSCCChan& cha /*static*/ void MPSCCDevice::SetCR3(MPSCCChan& chan, uint32 data) { - switch (data & MPSCC::CR3_RXBITS) { + uint cr3_rxbits = data & MPSCC::CR3_RXBITS; + switch (cr3_rxbits) { case MPSCC::RXBITS_5: chan.rxbits = 5; break; @@ -173,7 +180,7 @@ MPSCCDevice::SetCR3(MPSCCChan& chan, uin chan.rxbits = 8; break; default: - __unreachable(); + VMPANIC("corrupted cr3_rxbits=$%x", cr3_rxbits); } chan.auto_enable = (data & MPSCC::CR3_AUTO_EN); @@ -202,7 +209,7 @@ MPSCCDevice::GetCR3(const MPSCCChan& cha data |= MPSCC::RXBITS_8; break; default: - __unreachable(); + VMPANIC("corrupted chan.rxbits=%d", chan.rxbits); } if (chan.auto_enable) { data |= MPSCC::CR3_AUTO_EN; @@ -217,7 +224,8 @@ MPSCCDevice::GetCR3(const MPSCCChan& cha /*static*/void MPSCCDevice::SetCR4(MPSCCChan& chan, uint32 data) { - switch (data & MPSCC::CR4_CLKRATE) { + uint cr4_clkrate = data & MPSCC::CR4_CLKRATE; + switch (cr4_clkrate) { case MPSCC::CLKRATE_1: chan.clkrate = 1; break; @@ -231,7 +239,7 @@ MPSCCDevice::SetCR4(MPSCCChan& chan, uin chan.clkrate = 64; break; default: - __unreachable(); + VMPANIC("corrupted cr4_clkrate=$%x", cr4_clkrate); } chan.syncmode = (data & MPSCC::CR4_SYNCMODE); chan.stopbits = (data & MPSCC::CR4_STOPBITS) >> 2; @@ -259,7 +267,7 @@ MPSCCDevice::GetCR4(const MPSCCChan& cha data |= MPSCC::CLKRATE_64; break; default: - __unreachable(); + VMPANIC("corrupted chan.clkrate=%d", chan.clkrate); } data |= chan.syncmode; data |= chan.stopbits << 2; @@ -276,7 +284,8 @@ MPSCCDevice::GetCR4(const MPSCCChan& cha /*static*/ void MPSCCDevice::SetCR5(MPSCCChan& chan, uint32 data) { - switch (data & MPSCC::CR5_TXBITS) { + uint cr5_txbits = data & MPSCC::CR5_TXBITS; + switch (cr5_txbits) { case MPSCC::TXBITS_5: chan.txbits = 5; break; @@ -290,7 +299,7 @@ MPSCCDevice::SetCR5(MPSCCChan& chan, uin chan.txbits = 8; break; default: - __unreachable(); + VMPANIC("corrupted cr5_txbits=$%x", cr5_txbits); } chan.nDTR = (data & MPSCC::CR5_nDTR); chan.sendbreak = (data & MPSCC::CR5_SENDBREAK); @@ -320,7 +329,7 @@ MPSCCDevice::GetCR5(const MPSCCChan& cha data |= MPSCC::TXBITS_8; break; default: - __unreachable(); + VMPANIC("corrupted chan.txbits=%d", chan.txbits); } if (chan.nDTR) { data |= MPSCC::CR5_nDTR; @@ -392,7 +401,7 @@ MPSCCDevice::GetSR2B() const data |= bitrev(stat << 1); break; default: - __unreachable(); + VMPANIC("corrupted mpscc.vis=%d", (int)mpscc.vis); } return data; @@ -635,7 +644,7 @@ MPSCCDevice::TrySend(MPSCCChan& chan) // 送信する chan.tx_shiftreg = chan.txbuf; chan.txlen = 0; - gScheduler->StartEvent(txevent[chan.id]); + scheduler->StartEvent(txevent[chan.id]); putlog(2, "Ch%c send $%02x", chan.name, chan.tx_shiftreg); // XXX たぶん送信してから割り込みを上げるまでにいくらか遅れがあるはず @@ -664,8 +673,20 @@ MPSCCDevice::TxCallback(Event& event) void MPSCCDevice::HostRxCallback() { - // スレッドを超えるためにメッセージを投げる - gScheduler->SendMessage(MessageID::HOSTCOM_RX); + // XXX 暫定 + // HostCom からメッセージが大量に送られると、スケジューラの + // メッセージキューが溢れてしまうことがあったので、とりあえず + // ここでメッセージを送るかどうかを見ているが、 + // 本当はたぶんこうではなくて、送る側が速度調節するか、 + // またはスケジューラにメッセージではないなにか別の方法で + // 通知を出すようにする必要がある。 + + Event& ev = rxevent[COM_CH]; + + if (ev.IsRunning() == false) { + // スレッドを超えるためにメッセージを投げる + scheduler->SendMessage(MessageID::HOSTCOM_RX); + } } // 1バイト受信する。 @@ -706,7 +727,7 @@ MPSCCDevice::RxMessageCallback(MessageID // 受信ループが止まっていれば開始 if (ev.IsRunning() == false) { - gScheduler->StartEvent(ev); + scheduler->StartEvent(ev); } } @@ -722,7 +743,7 @@ MPSCCDevice::RxCallback(Event& ev) if (data >= 0) { Rx(ch, data); - gScheduler->StartEvent(ev); + scheduler->StartEvent(ev); } } @@ -792,8 +813,10 @@ MPSCCDevice::GetStopBits(MPSCCChan& chan return 0; case MPSCC::STOPBITS_2: return 2; + + default: + VMPANIC("corrupted chan.stopbits=$%x", chan.stopbits); } - __unreachable(); } // 受信イベントの時間を設定する。 @@ -810,6 +833,8 @@ MPSCCDevice::SetRxPeriod(MPSCCChan& chan bit += AdditionalBits(chan, chan.rx_enable); chan.rxframebits = bit; + rxevent[chan.id].time = bit * chan.bit12_ns / 12; + if (loglevel >= 1) { bool old_enable = chan.old_cr3 & MPSCC::CR3_RX_EN; bool new_enable = chan.rx_enable; @@ -855,7 +880,7 @@ MPSCCDevice::SetRxPeriod(MPSCCChan& chan if (chan.id == 0 && chan.rxbits == 5 && chan.stopbits == MPSCC::STOPBITS_2) { - gSync->PutlogRealtime(); + GetSyncer()->PutlogRealtime(); } } @@ -873,6 +898,8 @@ MPSCCDevice::SetTxPeriod(MPSCCChan& chan bit += AdditionalBits(chan, chan.tx_enable); chan.txframebits = bit; + txevent[chan.id].time = bit * chan.bit12_ns / 12; + if (loglevel >= 1) { bool old_enable = chan.old_cr5 & MPSCC::CR5_TX_EN; bool new_enable = chan.tx_enable; @@ -988,10 +1015,10 @@ MPSCCDevice::ChangeInterrupt() } // いずれかでもあれば割り込みをアサート - gInterrupt->ChangeINT(this, total_intpend); + interrupt->ChangeINT(this, total_intpend); } -// "9600,N,8,1" みたいなのを返す +// "9600,N,8,1" みたいなのを返す。最大13桁? std::string MPSCCDevice::GetParamStr(const MPSCCChan& chan) const {