sa1100/power_manager.cpp \
sa1100/os_timer.cpp \
sa1100/reset_controller.cpp \
- sa1100/uart.cpp
+ sa1100/uart.cpp \
+ sa1100/rtc.cpp
HEADERS += \
arm710.h \
sa1100/os_timer.h \
sa1100/reset_controller.h \
sa1100/serial_3.h \
- sa1100/uart.h
+ sa1100/uart.h \
+ sa1100/rtc.h
+
unix {
target.path = /usr/lib
INSTALLS += target
gpioController = new GPIOController();
serial3 = new Serial3(serialOutput);
resetController = new ResetController();
- intController = new IntController(lcdController, osTimer, gpioController, serial3);
+ rtc = new RTC();
+ intController = new IntController(lcdController, osTimer, gpioController, serial3, rtc);
powerManager = new PowerManager();
MemoryBlockC0 = new uint8_t[memoryMask+1];
MemoryBlockC8 = new uint8_t[memoryMask+1];
delete intController;
delete powerManager;
delete resetController;
+ delete rtc;
delete[] MemoryBlockC0;
delete[] MemoryBlockC8;
// delete[] MemoryBlockD0;
case 0x9001:
// RTC
printf("Getting RTC at 0x%08x\n", physAddr);
- return 0x0;
+ return rtc->get_data(physAddr);
case 0x9002:
// Power manager
printf("Getting power manager at 0x%08x\n", physAddr);
case 0x9001:
// RTC
printf("RTC write 0x%08x at 0x%08x\n", value, physAddr);
+ rtc->put_data(physAddr, value);
return true;
case 0x9002:
// Power manager
uart2.cpu = this;
nextTickAt = TICK_INTERVAL;
- rtc = getRTC();
+ nextRTCTick = 0;
memoryConfig.reset();
setProcessorID(0x4401A111);
powerManager->reset();
intController->reset();
gpioController->reset();
asic14->reset();
+ rtc->reset();
reset();
}
lcdController->reset();
intController->reset();
gpioController->reset();
+ rtc->reset();
reset();
}
if (passedCycles >= nextTickAt) {
// increment RTCDIV
if ((pwrsr & 0x3F) == 0x3F) {
- rtc++;
pwrsr &= ~0x3F;
} else {
pwrsr++;
if (passedCycles % TICKS_3_6864_MHZ == 0) {
osTimer->tick();
}
+ if (passedCycles >= nextRTCTick) {
+ printf("RTC tick\n");
+ rtc->run();
+ nextRTCTick += TICKS_1_HZ;
+ }
gpioController->run();
serial3->run();
intController->run();
#include "sa1100/os_timer.h"
#include "sa1100/reset_controller.h"
#include "sa1100/serial_3.h"
+#include "sa1100/rtc.h"
namespace SA1100 {
uint32_t pwrsr = 0x00002000; // cold start flag
uint32_t lcdControl = 0;
uint32_t lcdAddress = 0;
- uint32_t rtc = 0;
uint16_t lastSSIRequest = 0;
int ssiReadCounter = 0;
+ uint32_t nextRTCTick = 0;
uint32_t kScan = 0;
uint8_t keyboardColumns[8] = {0,0,0,0,0,0,0};
IntController* intController;
PowerManager* powerManager;
ResetController* resetController;
+ RTC* rtc;
Serial3* serial3;
ASIC14* asic14;
IntController::IntController(LCDController* const lcdController,
OsTimer* const osTimer,
GPIOController* const gpioController,
- Serial3* const serial3)
+ Serial3* const serial3,
+ RTC* const rtc)
: mOsTimer(osTimer),
mLCDController(lcdController),
mGPIOController(gpioController),
- mSerial3(serial3) {
+ mSerial3(serial3),
+ mRTC(rtc) {
init_register();
}
// check RTC
- // {
- // uint32_t const rtc_status = mp_rtc->get_interrupt_status();
+ {
+ uint32_t const rtc_status = mRTC->get_interrupt_status();
- // switch (rtc_status)
- // {
- // case 0:
- // m_ICPR &= ~(RTC_ALARM_BIT_MASK | RTC_HZ_BIT_MASK);
- // break;
+ switch (rtc_status)
+ {
+ case 0:
+ m_ICPR &= ~(RTC_ALARM_BIT_MASK | RTC_HZ_BIT_MASK);
+ break;
- // case RTC::STATUS_AL_BIT:
- // m_ICPR |= RTC_ALARM_BIT_MASK;
- // m_ICPR &= ~RTC_HZ_BIT_MASK;
- // break;
+ case RTC::STATUS_AL_BIT:
+ printf("RTC alarm fire\n");
+ m_ICPR |= RTC_ALARM_BIT_MASK;
+ m_ICPR &= ~RTC_HZ_BIT_MASK;
+ break;
- // case RTC::STATUS_HZ_BIT:
- // m_ICPR |= RTC_HZ_BIT_MASK;
- // m_ICPR &= ~RTC_ALARM_BIT_MASK;
- // break;
+ case RTC::STATUS_HZ_BIT:
+ printf("RTC 1hz fire\n");
+ m_ICPR |= RTC_HZ_BIT_MASK;
+ m_ICPR &= ~RTC_ALARM_BIT_MASK;
+ break;
- // case (RTC::STATUS_AL_BIT | RTC::STATUS_HZ_BIT):
- // m_ICPR |= (RTC_ALARM_BIT_MASK | RTC_HZ_BIT_MASK);
- // break;
+ case (RTC::STATUS_AL_BIT | RTC::STATUS_HZ_BIT):
+ printf("RTC 1hz and alarm fire\n");
+ m_ICPR |= (RTC_ALARM_BIT_MASK | RTC_HZ_BIT_MASK);
+ break;
- // default:
- // assert(!"Should not reach here.");
- // break;
- // }
- // }
+ default:
+ assert(!"Should not reach here.");
+ break;
+ }
+ }
// check LCD controller
#include "os_timer.h"
#include "serial_3.h"
#include "uart.h"
+#include "rtc.h"
namespace SA1100 {
LCDController* const mLCDController;
GPIOController* const mGPIOController;
Serial3* const mSerial3;
+ RTC* const mRTC;
// Register location
IntController(LCDController* const lcdController,
OsTimer* const osTimer,
GPIOController* const gpioController,
- Serial3* const serial3);
+ Serial3* const serial3,
+ RTC* const rtc);
// Operation
--- /dev/null
+// ARMware - an ARM emulator
+// Copyright (C) <2007> Wei Hu <wei.hu.tw@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "rtc.h"
+
+
+namespace SA1100 {
+
+RTC::RTC()
+{
+ init_register();
+}
+
+void RTC::run()
+{
+ // :SA-1110 Developer's Manual: Wei 2003-Dec-08:
+ //
+ // The counter is incremented on rising edges of the 1-Hz clock.
+ ++m_RCNR;
+
+ // :SA-1110 Developer's Manual: Wei 2003-Dec-08:
+ //
+ // If RTAR == RCNR and the enable bit (in status register) is set,
+ // then the alarm bit in the RTC status register is set.
+ switch (m_RTSR & STATUS_ENABLE_BIT_MASK)
+ {
+ case 0:
+ break;
+
+ case STATUS_ALE_BIT:
+ if (m_RTAR == m_RCNR)
+ {
+ #if TRACE_RTC
+ g_log_file << "RTC: enable alarm: " << std::hex << m_RCNR << std::endl;
+ #endif
+
+ m_RTSR |= STATUS_AL_BIT;
+ }
+ break;
+
+ case STATUS_HZE_BIT:
+ #if TRACE_RTC
+ g_log_file << "RTC: enable hz: " << std::hex << m_RCNR << std::endl;
+ #endif
+
+ m_RTSR |= STATUS_HZ_BIT;
+ break;
+
+ case (STATUS_ALE_BIT | STATUS_HZE_BIT):
+ if (m_RTAR == m_RCNR)
+ {
+ #if TRACE_RTC
+ g_log_file << "RTC: enable alarm: " << std::hex << m_RCNR << std::endl;
+ #endif
+
+ m_RTSR |= STATUS_AL_BIT;
+ }
+
+ #if TRACE_RTC
+ g_log_file << "RTC: enable hz: " << std::hex << m_RCNR << std::endl;
+ #endif
+
+ m_RTSR |= STATUS_HZ_BIT;
+ break;
+ }
+}
+
+void RTC::reset()
+{
+ // :SA-1110 Developer's Manual: Wei 2003-Dec-08:
+ //
+ // bit (4 ~ 31) of RTSR are set to 0 when reset,
+ // bit (0 ~ 3) have unknown value.
+ m_RTSR &= STATUS_VALID_BIT_MASK;
+
+ m_RTTR = 0;
+}
+
+uint32_t RTC::get_data(uint32_t const address) const
+{
+ #if TRACE_RTC
+ g_log_file << "RTC: get value at " << std::hex << address << std::endl;
+ #endif
+
+ switch (address)
+ {
+ case RTAR: return m_RTAR;
+ case RCNR: return m_RCNR;
+ case RTTR: return m_RTTR;
+ case RTSR: return m_RTSR;
+
+ default:
+ /*assert(!"Should not reach here.");*/
+ return 0;
+ }
+}
+
+void RTC::put_data(uint32_t const address, uint32_t const value)
+{
+ switch (address)
+ {
+ case RTAR:
+ #if TRACE_RTC
+ g_log_file << "RTC: set alarm: " << std::hex << value << std::endl;
+ #endif
+
+ m_RTAR = value;
+ break;
+
+ case RCNR:
+ #if TRACE_RTC
+ g_log_file << "RTC: set RCNR: " << std::hex << value << std::endl;
+ #endif
+
+ m_RCNR = value;
+ break;
+
+ case RTTR:
+ // :NOTE: Wei 2004-Jun-06:
+ //
+ // I don't support RTC Trim Procedure yet.
+ // Thus just let it pass by.
+ #if TRACE_RTC
+ g_log_file << "RTC: Trim Procedure, using " << value << std::endl;
+ #endif
+
+ m_RTTR = (value & 0x3FFFFFF);
+ break;
+
+ case RTSR:
+ #if TRACE_RTC
+ g_log_file << "RTC: setting RTSR: orig: " << std::hex << m_RTSR << ", value: " << value << std::endl;
+ #endif
+
+ // :SA-1110 Developer's Manual: p.90, p.91: Wei 2003-Dec-09:
+ //
+ // Each status bit may be cleared by writing a one to the status register in the desired bit position.
+ // ...
+ // The AL & HZ bits (bit 0 & 1) are cleared by writing ones to them.
+ // ...
+ // All reserved bits are read as 0s and are unaffected by writes.
+ m_RTSR &= ~(value & STATUS_VALID_BIT_MASK);
+
+ #if TRACE_RTC
+ g_log_file << "RTC: setting RTSR: new: " << std::hex << m_RTSR << std::endl;
+ #endif
+ break;
+
+ default:
+ /*assert(!"Should not reach here.");*/
+ break;
+ }
+}
+
+} // namespace SA1100
--- /dev/null
+#pragma once
+
+#include <stdint.h>
+
+namespace SA1100 {
+
+class RTC {
+ public:
+ enum
+ {
+ STATUS_AL_BIT = (1 << 0),
+ STATUS_HZ_BIT = (1 << 1),
+ STATUS_ALE_BIT = (1 << 2),
+ STATUS_HZE_BIT = (1 << 3),
+
+ STATUS_ENABLE_BIT_MASK = (STATUS_ALE_BIT |
+ STATUS_HZE_BIT),
+
+ STATUS_VALID_BIT_MASK = (STATUS_AL_BIT |
+ STATUS_HZ_BIT |
+ STATUS_ALE_BIT |
+ STATUS_HZE_BIT)
+ };
+ private:
+ enum
+ {
+ RTAR = 0x90010000,
+ RCNR = 0x90010004,
+ RTTR = 0x90010008,
+ RTSR = 0x90010010
+ };
+
+ uint32_t m_RTAR; // RTC alarm register
+ uint32_t m_RCNR; // RTC count register
+ uint32_t m_RTTR; // RTC timer trim register
+ uint32_t m_RTSR; // RTC status register
+
+ void init_register() {
+ m_RTAR = 0;
+ m_RCNR = 0;
+ m_RTTR = 0;
+ m_RTSR = 0;
+ }
+
+ public:
+ RTC();
+ inline uint32_t
+ get_interrupt_status() const
+ {
+ return m_RTSR;
+ }
+
+ void run();
+ void reset();
+
+ uint32_t get_data(uint32_t const address) const;
+
+ void put_data(uint32_t const address, uint32_t const value);
+};
+
+} // namespace SA1100