From b8fbfa141ee833361057e9a7d8c5995226f2572a Mon Sep 17 00:00:00 2001 From: George Wright Date: Wed, 24 Jun 2026 20:03:41 -0700 Subject: [PATCH] sa1100: hook up peripherals to core --- WindCore/series7/sa1100.cpp | 65 +++++++++++++++++++- WindCore/series7/sa1100.h | 35 ++++++++--- WindCore/series7/sa1100_memory.cpp | 99 +++++++++++++++++++++++++++--- 3 files changed, 181 insertions(+), 18 deletions(-) diff --git a/WindCore/series7/sa1100.cpp b/WindCore/series7/sa1100.cpp index ce3135b..c450711 100644 --- a/WindCore/series7/sa1100.cpp +++ b/WindCore/series7/sa1100.cpp @@ -6,7 +6,34 @@ namespace SA1100 { -Emulator::Emulator() : EmuBase(false) {} +Emulator::Emulator() : EmuBase(false) { + mOsTimer = new OsTimer(); + mLcdController = new LCDController(); + mGpioController = new GPIOController(); + mUart = new Uart(getSerialOutput()); + mResetController = new ResetController(); + mRtc = new RTC(getClockSpeed()); + mIntController = + new IntController(mLcdController, mOsTimer, mGpioController, mUart, mRtc); + mPowerManager = new PowerManager(); + + MemoryBlockC0 = new uint8_t[MemoryBlockMask + 1]; + MemoryBlockC8 = new uint8_t[MemoryBlockMask + 1]; + ROM = new uint8_t[0x1000000]; +} + +Emulator::~Emulator() { + delete mOsTimer; + delete mLcdController; + delete mGpioController; + delete mIntController; + delete mPowerManager; + delete mResetController; + delete mRtc; + delete[] MemoryBlockC0; + delete[] MemoryBlockC8; + delete[] ROM; +} uint32_t Emulator::getRTC() { return 0; } @@ -17,6 +44,15 @@ void Emulator::configure() { configured = true; srand(1000); nextTickAt = Series7::TICK_INTERVAL; + setProcessorID(0x4401A111); + + mMemoryController.reset(); + mPowerManager->reset(); + mOsTimer->reset(); + mLcdController->reset(); + mIntController->reset(); + mGpioController->reset(); + mRtc->reset(); reset(); } @@ -30,6 +66,18 @@ void Emulator::executeUntil(int64_t cycles) { if (!configured) configure(); + if (mResetController->resetRequested()) { + mResetController->reset(); + mMemoryController.reset(); + mPowerManager->reset(); + mOsTimer->reset(); + mLcdController->reset(); + mIntController->reset(); + mGpioController->reset(); + mRtc->reset(); + reset(); + } + while (!asleep && passedCycles < cycles) { if (passedCycles >= nextTickAt) { // increment RTCDIV @@ -42,6 +90,21 @@ void Emulator::executeUntil(int64_t cycles) { nextTickAt += Series7::TICK_INTERVAL; } + mRtc->run(passedCycles); + mGpioController->run(); + mUart->run(passedCycles); + mIntController->run(); + mOsTimer->tick(); + + if (mIntController->havePendingFiq() && canAcceptFIQ()) { + requestFIQ(); + halted = false; + } + if (mIntController->havePendingIrq() && canAcceptIRQ()) { + requestIRQ(); + halted = false; + } + // what's running? if (halted) { // keep the clock moving diff --git a/WindCore/series7/sa1100.h b/WindCore/series7/sa1100.h index 23d8e10..c73628e 100644 --- a/WindCore/series7/sa1100.h +++ b/WindCore/series7/sa1100.h @@ -4,6 +4,16 @@ #include "emubase.h" #include "series7_defs.h" +#include "gpio_controller.h" +#include "interrupt_controller.h" +#include "lcd_controller.h" +#include "memory_controller.h" +#include "os_timer.h" +#include "power_manager.h" +#include "reset_controller.h" +#include "rtc.h" +#include "uart.h" + namespace SA1100 { // Relatively simple implementation of a StrongARM SA-1100 CPU @@ -22,21 +32,30 @@ namespace SA1100 { class Emulator : public EmuBase { public: - // 16MB ROM - uint8_t ROM[0x1000000]; - // 16MB RAM/bank0, mapped at base addr 0xC0000000 - uint8_t MemoryBlockC0[0x1000000]; - // 16MB RAM/bank1, mapped at base addr 0xC8000000 + uint8_t* ROM; + // RAM/bank0, mapped at base addr 0xC0000000 + uint8_t* MemoryBlockC0; + // RAM/bank1, mapped at base addr 0xC8000000 // On the netBook, the OS.img minus the 256-byte wrapper is copied to this RAM // See the bookboot README file (linked above) - uint8_t MemoryBlockC8[0x1000000]; - enum { MemoryBlockMask = 0x0FFFFFF }; + uint8_t* MemoryBlockC8; + const uint32_t MemoryBlockMask = 0x0FFFFFF; private: uint32_t pwrsr = 0x00002000; // cold start flag bool halted = false, asleep = false; uint32_t getRTC(); + MemoryController mMemoryController; + GPIOController* mGpioController; + LCDController* mLcdController; + OsTimer* mOsTimer; + IntController* mIntController; + PowerManager* mPowerManager; + ResetController* mResetController; + RTC* mRtc; + Uart* mUart; + public: MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override; bool writePhysical(uint32_t value, uint32_t physAddr, @@ -75,6 +94,8 @@ private: public: Emulator(); + virtual ~Emulator(); + uint8_t* getROMBuffer() override; size_t getROMSize() override; void loadROM(uint8_t* buffer, size_t size) override; diff --git a/WindCore/series7/sa1100_memory.cpp b/WindCore/series7/sa1100_memory.cpp index fbb79da..443b366 100644 --- a/WindCore/series7/sa1100_memory.cpp +++ b/WindCore/series7/sa1100_memory.cpp @@ -30,12 +30,29 @@ uint8_t Emulator::readPCM8(uint32_t physAddr) { bool Emulator::writePCM8(uint8_t value, uint32_t physAddr) { return true; } uint32_t Emulator::readPCM32(uint32_t physAddr) { - // Peripheral Control Modules - return 0x0; + uint16_t region = (physAddr >> 16) & 0xFFFF; + + switch (region) { + case 0x8005: + // UART + return mUart->read32(physAddr); + default: + return 0x0; + } } -bool Emulator::writePCM32(uint32_t value, uint32_t physAddr) { return true; } +bool Emulator::writePCM32(uint32_t value, uint32_t physAddr) { + uint16_t region = (physAddr >> 16) & 0xFFFF; + switch (region) { + case 0x8005: + // UART + mUart->write32(physAddr, value); + return true; + default: + return true; + } +} uint8_t Emulator::readSCM8(uint32_t physAddr) { // System Control Modules return 0x0; @@ -44,11 +61,72 @@ uint8_t Emulator::readSCM8(uint32_t physAddr) { bool Emulator::writeSCM8(uint8_t value, uint32_t physAddr) { return true; } uint32_t Emulator::readSCM32(uint32_t physAddr) { - // System Control Modules - return 0x0; + uint16_t region = (physAddr >> 16) & 0xFFFF; + + switch (region) { + case 0x9000: + // OS Timer + return mOsTimer->read32(physAddr); + case 0x9001: + // RTC + return mRtc->read32(physAddr); + case 0x9002: + // Power manager + return mPowerManager->read32(physAddr); + case 0x9003: + // Reset controller + return mResetController->read32(physAddr); + case 0x9004: + // GPIO + return mGpioController->read32(physAddr); + case 0x9005: + // Interrupt Controller + return mIntController->read32(physAddr); + case 0x9006: + // PPC + return 0; + default: + printf("Tried to read %08x\n", physAddr); + return 0x0; + } } -bool Emulator::writeSCM32(uint32_t value, uint32_t physAddr) { return true; } +bool Emulator::writeSCM32(uint32_t value, uint32_t physAddr) { + uint16_t region = (physAddr >> 16) & 0xFFFF; + + switch (region) { + case 0x9000: + // OS Timer + mOsTimer->write32(physAddr, value); + return true; + case 0x9001: + // RTC + mRtc->write32(physAddr, value); + return true; + case 0x9002: + // Power manager + mPowerManager->write32(physAddr, value); + return true; + case 0x9003: + // Reset controller + mResetController->write32(physAddr, value); + return true; + case 0x9004: + // GPIO + mGpioController->write32(physAddr, value); + return true; + case 0x9005: + // Interrupt Controller + mIntController->write32(physAddr, value); + return true; + case 0x9006: + // PPC + return true; + default: + LOG_REG_W("Unknown", physAddr, value); + return true; + } +} uint8_t Emulator::readPhysical8(uint32_t physAddr) { uint8_t region = (physAddr >> 24) & 0xFF; @@ -466,11 +544,11 @@ uint32_t Emulator::readPhysical32(uint32_t physAddr) { break; case 0xA0: // Memory Control Registers - result = 0x0; + result = mMemoryController.read32(physAddr); break; case 0xB0: // LCD/DMA Control Registers - result = 0x0; + result = mLcdController->read32(physAddr); break; case 0xC0: case 0xC1: @@ -506,7 +584,6 @@ bool Emulator::writePhysical32(uint32_t value, uint32_t physAddr) { case 0x00: // Read-only return false; - break; case 0x20: case 0x21: case 0x22: @@ -617,9 +694,11 @@ bool Emulator::writePhysical32(uint32_t value, uint32_t physAddr) { return writeSCM32(value, physAddr); case 0xA0: // Memory Control Registers - return false; + mMemoryController.write32(physAddr, value); + return true; case 0xB0: // LCD/DMA Control Registers + mLcdController->write32(physAddr, value); return true; case 0xC0: case 0xC1: -- 2.45.2