A little update on the MKHBC-8-Rx project.
Recently having (mostly) completed my home improvement projects, I have some more time to play with my pet project.
I have been mainly working on code, cleaning it up and moving some essential parts to EPROM. It is still a mess, but I think it is good enough to be published, so I put it on github.
I moved assembly code of RTC DS-1685 driver to EPROM, enabled periodic interrupts from RTC and added interrupt routine for RTC. I also expanded kernel jump table and added some new functions to my so called 'enhanced shell', although calling this program a shell is a bit of an overkill. :-)
Below I present the current documentation of the OS / firmware fir this system:
System programming /
Operating System of MKHBC-8-Rx is divided into 2 parts:
- Firmware, which resides in EPROM.
- System programs, which are loaded to RAM via serial port.
Firmware consists of
hexadecimal machine code monitor, hardware drivers code, MOS-6502 mandatory
vectors: Reset, NMI, IRQ and Kernel Jump Table.
Firmware is
implemented in MOS 6502 assembly language.
Kernel Jump Table is
a series of jump commands that redirect to code performing certain system
functions.
These jump commands
are guaranteed to be always at the same memory locations, so the system
programs using them don't have to be rebuilt each time the implementation of
firmware is changed and some internal addresses has moved. The jump table is
always in the same place jumping from the same locations to the same functions
that they should perform, even if the functions themselves change the location
in the EPROM due to code refactoring or relocation of binary code.
The new entries can
be added to the Kernel Jump Table though, so it is guaranteed to be backwards
compatible.
Theory of operation:
When computer is
started, the reset circuit holds the reset line low long enough for CPU to
initialize, then the CPU performs startup routine which consists of reading the
Reset vector from the EPROM memory (which must be at fixed address) and
executes the routine pointed by that vector.
The routine contains
initialization code for OS and then goes into the eternal loop which sends the
output via serial port and expects input on the serial port. By connecting text
serial terminal device configured to be the same speed as computer's UART speed,
it is possible to interface with the computer to send commands and receive
output.
The command UI is
very simple and consists of very rudimentary hexadecimal machine code monitor
which allows to read/dump values in computer's memory, write/modify values in
Random Access Memory and execute code at provided address.
This UI is
rudimentary but sufficient for entering code into computer's RAM and executing
it.
Programming API /
Kernal Jump Table:
Function
|
Address (hex)
|
Parameters
|
Return
|
Description
|
CallDS1685Init
|
FFD2
|
RegB, RegA, RegXB,
RegXA
|
RegC in Acc
|
Initialize RTC
chip.
|
CallDS1685ReadClock
|
FFD5
|
n/a
|
Data is returned
via hardware stack. Calling subroutine is responsible for allocating 8 bytes
on stack before calling this function. Clock data are stored in following
order below the subroutine return address: seconds, minutes, hours,
dayofweek, date, month, year, century. Valid return data on stack only if Acc
> 0 (Acc = # of bytes on stack). Calling subroutine still should
de-allocate stack space by calling PLA x 8 after reading or discarding
returned data.
|
Read RTC clock
data.
|
CallDS1685SetClock
|
FFD8
|
Parameters are
passed via hardware stack: seconds, minutes, hours, day of week, day of
month, month, year, century. Calling subroutine is responsible for allocating
8 bytes on stack and filling the space with valid input data before calling
this function. Calling subroutine is also responsible for freeing stack space
(PLA x 8).
|
n/a
|
Set date/time of
RTC chip.
|
CallDS1685SetTime
|
FFDB
|
Parameters are
passed via hardware stack: seconds, minutes, hour. Calling subroutine is
responsible for allocating space on stack and filling it with valid input
data before calling this function.
Calling subroutine is also responsible for freeing stack space (PLA x
3).
|
n/a
|
Set time of RTC
chip.
|
CallDS1685StoreRam
|
FFDE
|
BankNum, RamAddr,
RamVal
|
n/a
|
Store a value in
non-volatile RTC memory bank.
|
CallDS1685ReadRam
|
FFE1
|
BankNum, RamAddr
|
value in Acc
|
Read value from
non-volatile RTC memory bank.
|
CallReadMem
|
FFE4
|
PromptLine
(contains hexadecimal address range)
|
n/a (output)
|
Machine code
monitor function - read memory.
|
CallWriteMem
|
FFE7
|
PromptLine
(contains hexadecimal address and values)
|
n/a (memory is
modified)
|
Machine code
monitor function - write memory.
|
CallExecute
|
FFEA
|
PromptLine
(contains hexadecimal address)
|
n/a (code is
executed)
|
Machine code
monitor function - execute code in memory.
|
CallGetCh
|
FFED
|
n/a
|
Character code in
Acc
|
Standard I/O
function - get character.
|
CallPutCh
|
FFF0
|
Character code in
Acc.
|
n/a (output)
|
Standard I/O
function - put/print character.
|
CallGets
|
FFF3
|
n/a (input)
|
PromptLine,
PromptLen
|
Standard I/O
function - get string.
|
CallPuts
|
FFF6
|
StrPtr
|
n/a (output)
|
Standard I/O
function - put/print string.
|
CallBankRamSel
|
FFCF
|
Banked RAM bank #
in Acc. (0..7)
|
n/a (selects RAM
bank, updates shadow register in RAM)
|
Banked RAM bank
selection.
|
WARNING:
Disable
interrupts before calling any RTC function:
SEI
<call
to RTC API>
CLI
Registers, buffers,
memory:
RTC
RAM shadow:
RegB = $F6
RegA = $F7
RegXB = $F8
RegXA = $F9
RegC = $FA
Temp = $FB
BankNum = $FC
RamAddr = $FD
RamVal = $FE
Uart
Queues (after stack)
UartTxQue = $200 ; 256 byte output queue
UartRxQue = $300 ; 256 byte input queue
MOS Prompt variables
PromptLine = $80 ; Prompt line (entered by user)
PromptMax = $50 ; An 80-character line is permitted
($80 to $CF)
PromptLen = $D0 ; Location of length variable
MOS I/O Function variables
StrPtr = $E0 ; String pointer for I/O functions
Other variables:
Timer64Hz
= $E2 ; 4-byte (32-bit)
counter incremented 64 times / sec
; $E2,$E3,$E4,$E5 (unsigned long, little
endian)
Customizable jump
vectors
Program loaded and run in RAM can
modify these vectors
to drive custom I/O console hardware
and attach/change
handler to IRQ procedure. Interrupt
flag should be
set before changes are applied and
cleared when ready.
Custom IRQ handler routine should
make a jump to standard
handler at the end. Custom I/O
function routine should
end with RTS.
StoreAcc = $11 ;
Temporary Accumulator store.
IrqVect = $0012 ;
Customizable IRQ vector
GetChVect = $0014 ;
Custom GetCh function jump vector
PutChVect = $0016 ;
Custom PutCh function jump vector
GetsVect = $0018 ;
Custom Gets function jump vector
PutsVect = $001a ;
Custom Puts function jump vector
I/O
space / address range:
$C000
.. $C7FF, 8 pages (8 x 256 bytes):
Internal
(non-buffered) I/O bus:
$C000
.. $C0FF - slot 0 (RAM bank switching register)
$C100
.. $C1FF - slot 1 (RTC registers)
$C200
.. $C2FF - slot 2 (Reserved for Prioritized Interrupt Controller)
$C300
.. $C3FF - slot 3 (Reserved for built in I/O parallel interface PIA or VIA)
External
(buffered/expansion) I/O bus:
$C400
.. $C4FF - slot 4 (UART)
$C500
.. $C5FF - slot 5
$C600
.. $C6FF - slot 6
$C700
.. $C7FF - slot 7
RAM
bank switching.
Address:
|
$C000
|
Value:
|
$00 .. $07
|
Banked memory:
|
$8000 .. $BFFF
|
Bank number RAM register:
|
$E6
|
Memory
map:
$0000
- $7FFF: Base RAM, 32 kB.
$6000
- $7FFF: Optional Video RAM, 8 kB.
$8000
- $BFFF: Banked RAM, 16 kB space x 8 banks = 128 kB.
$C000
- $C7FF: I/O space, 8 slots x 256 Bytes = 2 kB.
$C800
- $FFFF: EPROM, 14 kB.
System programs:
System
programs currently consist only one - enhanced shell.
It
is written in C and compiled with CC65.
Programs
written in C (CC65) or CA65 assembly for MKHBC-8-Rx computer / MKHBC OS use
library written in C and assembly languages which implements standard C library
(CC65), I/O console and RTC functions and are compiled into library archive
mkhbcos.lib.
Corresponding
C header files are:
- mkhbcos_ansi.h - ANSI terminal API
- mkhbcos_ds1685.h - DS1685 RTC API
- mkhbcos_lcd.h - standard LCD 16x2 API
- mkhbcos_ml.h - machine code monitor API
- mkhbcos_serialio.h - serial I/O API
That's all for today.
Thank you for visiting my blog.
Marek K. 2/4/2018.
No comments:
Post a Comment