--- nono/vm/mpu.cpp 2026/04/29 17:04:36 1.1.1.3 +++ nono/vm/mpu.cpp 2026/04/29 17:04:45 1.1.1.5 @@ -7,6 +7,7 @@ // MPU 共通部 #include "mpu.h" +#include "config.h" std::unique_ptr gMPU; @@ -15,9 +16,55 @@ MPUDevice::MPUDevice() { logname = "mpu"; devname = "MPU"; + + // リセット例外を起こすイベント。 + // ハンドラは MPU ごとに異なるので継承クラス側で用意している。 + // (この時点ではまだ Scheduler インスタンスは存在してないが、イベントを + // 実際に Scheduler に登録するのは ResetHard() の時点なので問題ない) + event.dev = this; + event.SetName("MPU"); } // デストラクタ MPUDevice::~MPUDevice() { } + +bool +MPUDevice::Init() +{ + // MPU クロック + const ConfigItem& item = gConfig->Find("mpu-clock"); + const std::string& val = item.AsString(); + if (val.empty()) { + item.Err(); + return false; + } + // 文字列を double に変換 + char *end; + errno = 0; + double f = strtod(val.c_str(), &end); + if (end == val.c_str() || end[0] != '\0' || errno == ERANGE) { + item.Err(); + return false; + } + // 設定の "mpu-clock" は MHz 単位だが、変数 clock_khz は kHz 単位。 + clock_khz = (int)(f * 1000); + // 1MHz 以下はエラー。実際 10MHz 以下でもいい気がするけど + if (clock_khz < 1000) { + item.Err(); + return false; + } + + return true; +} + +// リセット +void +MPUDevice::ResetHard() +{ + // 0 サイクル後にリセット例外を起こす + event.time = 0; + event.code = (uint32)-1; + event.Start(); +}