Separate kernel code from test code

Eventually I want the kernel to be loaded from the SD card as well, but
it still needs to separate from user programs.

At some point there should be a folder just for the BIOS, which should
read from the boot block of the SD card and start executing, and thats
it.
This commit is contained in:
Byron Lathi
2022-04-16 21:58:37 -05:00
parent 238a4b6f98
commit c6098f2d1f
26 changed files with 5 additions and 5 deletions

57
sw/kernel/Makefile Normal file
View File

@@ -0,0 +1,57 @@
CC=cl65
CFLAGS=-T -t none -I. --cpu "65C02"
test: CFLAGS=-T -t sim65c02 -I.
LDFLAGS=-C link.ld -m $(NAME).map
SIM=sim65
SIMARGS=-v -c -x 1000000
NAME=bootrom
TEST_BIN=test.bin
BIN=$(NAME).bin
HEX=$(NAME).hex
LISTS=lists
TESTS=tests
SRCS=$(wildcard *.s) $(wildcard *.c)
SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*), $(wildcard **/*.c))
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
TEST_SRCS=$(wildcard $(TESTS)/*.s) $(wildcard $(TESTS)/*.c)
TEST_OBJS+=$(patsubst %.s,%.o,$(filter %s,$(TEST_SRCS)))
TEST_OBJS+=$(patsubst %.c,%.o,$(filter %c,$(TEST_SRCS)))
TEST_OBJS+=$(filter-out boot.o,$(filter-out main.o,$(filter-out vectors.o,$(OBJS))))
all: $(HEX)
test: $(TEST_BIN)
$(SIM) $(SIMARGS) $(TEST_BIN)
$(TEST_BIN): $(OBJS) $(TEST_OBJS)
$(CC) $(CFLAGS) $(TEST_OBJS) -o $@
$(HEX): $(BIN)
objcopy --input-target=binary --output-target=ihex $(BIN) $(HEX)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
%.o: %.s $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
$(LISTS):
$(info $$SRCS is [${SRCS}])
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
mkdir $(LISTS)/$(sort $(dir $(TEST_SRCS)))
.PHONY: clean
clean:
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
rm -rf $(TEST_OBJS) $(TEST_BIN)

53
sw/kernel/boot.s Normal file
View File

@@ -0,0 +1,53 @@
; ---------------------------------------------------------------------------
; crt0.s
; ---------------------------------------------------------------------------
;
; Startup code for cc65 (Single Board Computer version)
.export _init, _exit
.import _main
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import __SDRAM_START__, __SDRAM_SIZE__ ; Linker generated
.import copydata, zerobss, initlib, donelib
.include "zeropage.inc"
; ---------------------------------------------------------------------------
; Place the startup code in a special segment
.segment "STARTUP"
; ---------------------------------------------------------------------------
; A little light 6502 housekeeping
_init: LDX #$FF ; Initialize stack pointer to $01FF
TXS
CLD ; Clear decimal mode
; ---------------------------------------------------------------------------
; Set cc65 argument stack pointer
LDA #<(__SDRAM_START__ + __SDRAM_SIZE__)
STA sp
LDA #>(__SDRAM_START__ + __SDRAM_SIZE__)
STA sp+1
; ---------------------------------------------------------------------------
; Initialize memory storage
JSR zerobss ; Clear BSS segment
JSR copydata ; Initialize DATA segment
JSR initlib ; Run constructors
; ---------------------------------------------------------------------------
; Call main()
cli
JSR _main
; ---------------------------------------------------------------------------
; Back from main (this is also the _exit entry): force a software break
_exit: JSR donelib ; Run destructors
BRK

View File

@@ -0,0 +1,16 @@
#ifndef _BOARD_IO_H
#define _BOARD_IO_H
#include <stdint.h>
uint8_t hex_set_8(uint8_t val, uint8_t idx);
uint8_t hex_set_16(uint16_t val);
uint8_t hex_set_24(uint32_t val);
void hex_enable(uint8_t mask);
uint8_t sw_read();
void led_set(uint8_t val);
#endif

View File

@@ -0,0 +1,71 @@
.include "io.inc65"
.importzp sp, sreg
.export _hex_set_8
.export _hex_set_16
.export _hex_set_24
.export _hex_enable
.export _sw_read
.export _led_set
.autoimport on
.code
; @in A: idx Stack[0]: val
; @out A: 0 for success, 1 for failure.
; Sets one of the 3 pairs of hex digits.
_hex_set_8:
phx
cmp #$3 ; If idx >= 3 then fail
bcc @1
plx
lda #$1
rts
@1: tax ; Move idx into x
jsr popa ; put val into a
sta SEVEN_SEG,x ; write to val
lda #$0
plx
rts
; @in A/X: val
; @out A: 0 for success, 1 for failure
; Sets the low 2 pairs of hex digits
_hex_set_16:
sta SEVEN_SEG
stx SEVEN_SEG+1
lda #$0
rts
; @in A/X/sreg: val
; @out A: 0 for success, 1 for failure
; Sets the 3 pairs of hex digits for a 24 bit value
_hex_set_24:
sta SEVEN_SEG
stx SEVEN_SEG+1
lda sreg
sta SEVEN_SEG+2
lda #$0
rts
; @in A: mask
; Set the mask for seven seg enables
_hex_enable:
sta SEVEN_SEG+3
rts
; @out A: The Value of the switches
; Reads the current values of the switches.
_sw_read:
lda SW
ldx #$0
rts
; @in A: val
; @out A: 0 for success, 1 for failure
; Sets the LEDs
_led_set:
sta LED
rts

60
sw/kernel/devices/conio.s Normal file
View File

@@ -0,0 +1,60 @@
.importzp sp, sreg
.import _uart_txb_block
.import _lastchar
.export _cputc
.export gotoxy
.export _clrscr
.export _cgetc
.autoimport on
.code
; void __fastcall__ cputc (char c);
_cputc:
jsr _uart_txb_block
cmp #$0a
bne @1
lda #$0d
jsr _uart_txb_block
@1: rts
; void __fastcall__ gotoxy (unsigned char x, unsigned char y);
gotoxy:
phx
phy
tay ; Move y position to y
lda (sp)
tax ; Move x position to x
lda #$1b
jsr _uart_txb_block
lda #'['
jsr _uart_txb_block
tya
jsr _uart_txb_block
lda #';'
jsr _uart_txb_block
txa
jsr _uart_txb_block
lda #'H'
jsr _uart_txb_block
ply
plx
rts
_clrscr:
phx
lda #$1b
jsr _uart_txb_block
lda #'c'
jsr _uart_txb_block
pla
rts
_cgetc:
@2: lda _lastchar
beq @2
stz _lastchar
rts

View File

@@ -0,0 +1,15 @@
#ifndef _INTERRUPT_H
#define _INTERRUPT_H
#include <stdint.h>
#define BUTTON (1 << 0)
#define UART (1 << 1)
void irq_int();
void nmi_int();
uint8_t irq_get_status();
void irq_set_status(uint8_t);
#endif

View File

@@ -0,0 +1,58 @@
; ---------------------------------------------------------------------------
; interrupt.s
; ---------------------------------------------------------------------------
;
; Interrupt handler.
;
; Checks for a BRK instruction and returns from all valid interrupts.
.import _handle_irq
.export _irq_int, _nmi_int
.export _irq_get_status, _irq_set_status
.include "io.inc65"
.segment "CODE"
.PC02 ; Force 65C02 assembly mode
; ---------------------------------------------------------------------------
; Non-maskable interrupt (NMI) service routine
_nmi_int: RTI ; Return from all NMI interrupts
; ---------------------------------------------------------------------------
; Maskable interrupt (IRQ) service routine
_irq_int: PHX ; Save X register contents to stack
TSX ; Transfer stack pointer to X
PHA ; Save accumulator contents to stack
INX ; Increment X so it points to the status
INX ; register value saved on the stack
LDA $100,X ; Load status register contents
AND #$10 ; Isolate B status bit
BNE break ; If B = 1, BRK detected
; ---------------------------------------------------------------------------
; IRQ detected, return
irq: PLA ; Restore accumulator contents
PLX ; Restore X register contents
jsr _handle_irq ; Handle the IRQ
RTI ; Return from all IRQ interrupts
; ---------------------------------------------------------------------------
; BRK detected, stop
break: JMP break ; If BRK is detected, something very bad
; has happened, so stop running
_irq_get_status:
lda IRQ_STATUS
ldx #$00
rts
_irq_set_status:
sta IRQ_STATUS
rts

View File

@@ -0,0 +1,18 @@
SEVEN_SEG = $7ff0
UART = $7ff4
UART_TXB = UART
UART_RXB = UART
UART_STATUS = UART + 1
LED = $7ff6
SW = LED
MM_CTRL = $7ff7
MM_DATA = $7fe0
SD_ARG = $7ff8
SD_CMD = $7ffc
SD_DATA = $7ffd
IRQ_STATUS = $7fff

View File

@@ -0,0 +1,12 @@
#ifndef _MAPPER_H
#define _MAPPER_H
#include <stdint.h>
void mapper_enable(uint8_t en);
uint8_t mapper_read(uint8_t addr);
void mapper_write(uint8_t data, uint8_t addr);
#endif

View File

@@ -0,0 +1,32 @@
.include "io.inc65"
.importzp sp, sreg
.export _mapper_enable
.export _mapper_read, _mapper_write
.autoimport on
.code
; void mapper_enable(uint8_t en)
_mapper_enable:
sta MM_CTRL
rts
_mapper_read:
phx
tax
lda MM_DATA,x
ldx #$00
rts
_mapper_write:
phx
tax
jsr popa
sta MM_DATA,x
plx
rts

View File

@@ -0,0 +1,75 @@
#include <stdint.h>
#include <conio.h>
#include "devices/sd_card.h"
void sd_init() {
uint32_t resp;
sd_card_command(0, 0);
sd_card_command(0x000001aa, 8);
sd_card_resp(&resp);
//cprintf("CMD8: %lx\n", resp);
sd_card_command(0, 55);
sd_card_command(0x40180000, 41);
sd_card_resp(&resp);
//cprintf("CMD41: %lx\n", resp);
sd_card_command(0, 55);
sd_card_command(0x40180000, 41);
sd_card_resp(&resp);
//cprintf("CMD41: %lx\n", resp);
sd_card_command(0, 2);
sd_card_resp(&resp);
//cprintf("CMD2: %lx\n", resp);
}
uint16_t sd_get_rca() {
uint32_t resp;
sd_card_command(0, 3);
resp = 0;
sd_card_resp(&resp);
//cprintf("CMD3: %lx\n", resp);
return resp >> 16;
}
uint16_t sd_select_card(uint16_t rca) {
uint32_t resp;
sd_card_command((uint32_t)rca << 16, 7);
sd_card_resp(&resp);
return (uint16_t) resp;
}
uint16_t sd_get_status(uint16_t rca) {
uint32_t resp;
sd_card_command((uint32_t)rca << 16, 13);
sd_card_resp(&resp);
return (uint16_t) resp;
}
void sd_readblock(uint32_t addr, void* buf) {
uint32_t resp;
int i;
sd_card_command(addr, 17);
sd_card_resp(&resp);
//cprintf("CMD17: %lx\n", resp);
sd_card_wait_for_data();
//cprintf("Read data: \n");
for (i = 0; i < 512; i++){
((uint8_t*)buf)[i] = sd_card_read_byte();
}
//cprintf("\n");
}

View File

@@ -0,0 +1,18 @@
#ifndef _SD_CARD_H
#define _SD_CARD_H
#include <stdint.h>
void sd_init();
uint16_t sd_get_rca();
uint16_t sd_select_card(uint16_t rca);
uint16_t sd_get_status(uint16_t rca);
void sd_readblock(uint32_t addr, void* buf);
void sd_card_command(uint32_t arg, uint8_t cmd);
void sd_card_resp(uint32_t* resp);
uint8_t sd_card_read_byte();
void sd_card_wait_for_data();
#endif

View File

@@ -0,0 +1,66 @@
.include "io.inc65"
.importzp sp, sreg, ptr1
.export _sd_card_command
.export _sd_card_resp
.export _sd_card_read_byte
.export _sd_card_wait_for_data
.autoimport on
.code
; Send sd card command.
; command is in A register, the args are on the stack
; I think the order is high byte first?
_sd_card_command:
pha
jsr popeax
sta SD_ARG
stx SD_ARG+1
lda sreg
sta SD_ARG+2
lda sreg+1
sta SD_ARG+3
pla
sta SD_CMD
rts
; void sd_card_resp(uint32_t* resp);
_sd_card_resp:
phy
sta ptr1 ; store pointer
stx ptr1+1
@1: lda SD_CMD ; wait for status flag
and #$01
beq @1
lda SD_ARG
ldy #$0
sta (ptr1),y
lda SD_ARG+1
iny
sta (ptr1),y
lda SD_ARG+2
iny
sta (ptr1),y
lda SD_ARG+3
iny
sta (ptr1),y
ply
rts
_sd_card_read_byte:
lda SD_DATA
ldx #$00
rts
_sd_card_wait_for_data:
pha
@1: lda SD_CMD ; wait for status flag
and #$02
beq @1
pla
rts

13
sw/kernel/devices/uart.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef _UART_H
#define _UART_H
#include <stdint.h>
void uart_txb(uint8_t val);
void uart_txb_block(uint8_t val);
uint8_t uart_rxb();
uint8_t uart_status();
#endif

36
sw/kernel/devices/uart.s Normal file
View File

@@ -0,0 +1,36 @@
.include "io.inc65"
.importzp sp, sreg
.export _uart_txb, _uart_txb_block
.export _uart_rxb
.export _uart_status
.autoimport on
.code
; @in A: byte to transmit
; Transmits a byte over the UART
_uart_txb:
sta UART_TXB ; Just write value, don't wait
rts
_uart_txb_block:
pha
sta UART_TXB ; Write value
@1: lda UART_STATUS ; Wait for status[0] to be 0
bit #$01
bne @1
pla
rts
_uart_rxb:
lda UART_RXB ; Read value
ldx #$00
rts
_uart_status:
lda UART_STATUS
ldx #$00
rts

61
sw/kernel/exec.c Normal file
View File

@@ -0,0 +1,61 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include "filesystem/fat.h"
#include "filesystem/o65.h"
void exec(char* filename) {
o65_header_t* header;
o65_opt_t* o65_opt;
uint8_t* seg_ptr;
uint8_t* code_base;
uint8_t* data_base;
uint16_t code_len;
uint16_t data_len;
uint8_t (*exec)(void);
uint8_t ret;
fat_read(filename, fat_buf);
header = (o65_header_t*)fat_buf;
if (header->c64_marker == O65_NON_C64 &&
header->magic[0] == O65_MAGIC_0 &&
header->magic[1] == O65_MAGIC_1 &&
header->magic[2] == O65_MAGIC_2) {
code_base = (uint8_t*)header->tbase;
data_base = (uint8_t*)header->dbase;
code_len = header->tlen;
data_len = header->dlen;
o65_opt = (o65_opt_t*)(fat_buf + sizeof(o65_header_t));
while (o65_opt->olen)
{
o65_print_option(o65_opt);
o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen);
}
seg_ptr = (uint8_t*)o65_opt + 1;
memcpy((uint8_t*)code_base, seg_ptr, code_len);
seg_ptr+=code_len;
memcpy((uint8_t*)data_base, seg_ptr, data_len);
exec = (uint8_t (*)(void))code_base;
ret = 0;
ret = (*exec)();
cprintf("ret: %x\n", ret);
}
}

6
sw/kernel/exec.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _EXEC_H
#define _EXEC_H
void exec(char* filename);
#endif

View File

@@ -0,0 +1,73 @@
#include <conio.h>
#include <string.h>
#include "fat.h"
#include "devices/sd_card.h"
uint8_t fat_buf[512];
static full_bpb_t bpb;
static uint32_t data_region_start;
void fat_print_pbp_info(ebpb_t* epbp){
cprintf("Bytes per sector: %d\n", epbp->bpb3.bpb2.bytes_per_sector);
cprintf("Sectors per cluster: %d\n", epbp->bpb3.bpb2.sectors_per_cluster);
cprintf("Reserved Sectors: %d\n", epbp->bpb3.bpb2.reserved_sectors);
cprintf("Fat Count: %d\n", epbp->bpb3.bpb2.fat_count);
cprintf("Max Dir Entries: %d\n", epbp->bpb3.bpb2.max_dir_entries);
cprintf("Total Sector Count: %d\n", epbp->bpb3.bpb2.total_sector_count);
cprintf("Media Descriptor: 0x%x\n", epbp->bpb3.bpb2.media_descriptor);
cprintf("Sectors per Fat: %d\n", epbp->bpb3.bpb2.sectors_per_fat);
cprintf("\n");
cprintf("Sectors per track: %d\n", epbp->bpb3.sectors_per_track);
cprintf("Head Count: %d\n", epbp->bpb3.head_count);
cprintf("Hidden Sector Count: %ld\n", epbp->bpb3.hidden_sector_count);
cprintf("Logical Sector Count: %ld\n", epbp->bpb3.logical_sector_count);
cprintf("Sectors per Fat: %ld\n", epbp->bpb3.sectors_per_fat);
cprintf("Extended Flags: 0x%x\n", epbp->bpb3.extended_flags);
cprintf("Version: %d\n", epbp->bpb3.version);
cprintf("Root Cluster: 0x%lx\n", epbp->bpb3.root_cluster);
cprintf("System Information: 0x%x\n", epbp->bpb3.system_information);
cprintf("Backup Boot Sector: 0x%x\n", epbp->bpb3.backup_boot_sector);
cprintf("\n");
cprintf("Drive Number: %d\n", epbp->drive_num);
cprintf("Extended Signature: 0x%x\n", epbp->extended_signature);
cprintf("Volume ID: 0x%lx\n", epbp->volume_id);
cprintf("Partition Label: %.11s\n", &epbp->partition_label);
cprintf("Partition Label: %.8s\n", &epbp->filesystem_type);
cprintf("\n");
}
void fat_init(){
sd_readblock(0, fat_buf);
memcpy(&bpb, &fat_buf[11], sizeof(ebpb_t));
sd_readblock(1, fat_buf);
sd_readblock(32, fat_buf);
data_region_start = bpb.reserved_sectors + bpb.fat_count*bpb.sectors_per_fat_32;
}
void fat_read(char* filename, void* buf) {
vfat_dentry_t* vfat_dentry;
dos_dentry_t* dos_dentry;
uint32_t cluster;
(void)filename; //just ignore filename
sd_readblock(data_region_start, buf);
vfat_dentry = (vfat_dentry_t*)buf;
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
dos_dentry = (dos_dentry_t*)(vfat_dentry + 1);
cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
sd_readblock(data_region_start + (cluster - 2) * 8, buf);
}

111
sw/kernel/filesystem/fat.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef _FAT_H
#define _FAT_H
#include <stdint.h>
extern uint8_t fat_buf[];
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t max_dir_entries;
uint16_t total_sector_count;
uint8_t media_descriptor;
uint16_t sectors_per_fat;
} dos_2_bpb_t;
typedef struct {
dos_2_bpb_t bpb2;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sector_count;
uint32_t logical_sector_count;
uint32_t sectors_per_fat;
uint16_t extended_flags;
uint16_t version;
uint32_t root_cluster;
uint16_t system_information;
uint16_t backup_boot_sector;
uint8_t reserved[12];
} dos_3_bpb_t;
typedef struct {
dos_3_bpb_t bpb3;
uint8_t drive_num;
uint8_t reserved;
uint8_t extended_signature;
uint32_t volume_id;
uint8_t partition_label[11];
uint8_t filesystem_type[8];
} ebpb_t;
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t max_dir_entries;
uint16_t total_sector_count;
uint8_t media_descriptor;
uint16_t sectors_per_fat_16;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sector_count;
uint32_t logical_sector_count;
uint32_t sectors_per_fat_32;
uint16_t extended_flags;
uint16_t version;
uint32_t root_cluster;
uint16_t system_information;
uint16_t backup_boot_sector;
uint8_t reserved[12];
uint8_t drive_num;
uint8_t reserved2;
uint8_t extended_signature;
uint32_t volume_id;
uint8_t partition_label[11];
uint8_t filesystem_type[8];
} full_bpb_t;
typedef struct {
uint32_t sig;
uint8_t reserved[480];
uint32_t sig2;
uint32_t free_data_clusters;
uint32_t last_allocated_data_cluster;
uint32_t reserved2;
uint32_t sig3;
} fs_info_sector_t;
typedef struct {
uint8_t sequence_number;
uint16_t filename0[5];
uint8_t attributes;
uint8_t type;
uint8_t checksum;
uint16_t filename1[6];
uint16_t reserved;
uint16_t filename[2];
} vfat_dentry_t;
typedef struct {
uint8_t filename[8];
uint8_t extension[3];
uint8_t attributes;
uint8_t reserved;
uint8_t create_time_10ms;
uint32_t create_date;
uint16_t access_date;
uint16_t first_cluster_h;
uint32_t modify_cluster;
uint16_t first_cluster_l;
uint32_t file_size;
} dos_dentry_t;
void fat_print_pbp_info(ebpb_t* epbp);
void fat_init();
void fat_read(char* filename, void* buf);
#endif

View File

@@ -0,0 +1,28 @@
#include <conio.h>
#include "o65.h"
void o65_print_option(o65_opt_t* opt) {
int i;
cprintf("Option Length: %d\n", opt->olen);
cprintf("Option Type: %x ", opt->type);
switch (opt->type) {
case O65_OPT_FILENAME: cprintf("Filename\n"); break;
case O65_OPT_OS: cprintf("OS\n"); break;
case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break;
case O65_OPT_AUTHOR: cprintf("Author\n"); break;
case O65_OPT_DATE: cprintf("Creation Date\n"); break;
default: cprintf("Invalid\n"); break;
}
if (opt->type != O65_OPT_OS) {
for (i = 0; i < opt->olen - 2; i++) {
cprintf("%c", opt->data[i]);
}
} else {
cprintf("%x", opt->data[0]);
}
cprintf("\n\n");
}

View File

@@ -0,0 +1,65 @@
#ifndef _O65_H
#define _O65_H
#include <stdint.h>
#define O65_NON_C64 0x0001
#define O65_MAGIC_0 0x6f
#define O65_MAGIC_1 0x36
#define O65_MAGIC_2 0x35
#define O65_OPT_FILENAME 0
#define O65_OPT_OS 1
#define O65_OPT_ASSEMBLER 2
#define O65_OPT_AUTHOR 3
#define O65_OPT_DATE 4
#define O65_OS_OSA65 1
#define O65_OS_LUNIX 2
#define O65_OS_CC65 3
#define O65_OS_OPENCBM 4
#define O65_OS_SUPER6502 5
typedef union {
struct {
int cpu : 1;
int reloc : 1;
int size : 1;
int obj : 1;
int simple : 1;
int chain : 1;
int bsszero : 1;
int cpu2 : 4;
int align : 2;
};
uint16_t _mode;
} o65_mode_t;
typedef struct {
uint16_t c64_marker;
uint8_t magic[3];
uint8_t version;
o65_mode_t mode;
uint16_t tbase;
uint16_t tlen;
uint16_t dbase;
uint16_t dlen;
uint16_t bbase;
uint16_t blen;
uint16_t zbase;
uint16_t zlen;
uint16_t stack;
} o65_header_t;
typedef struct {
uint8_t olen;
uint8_t type;
uint8_t data[1]; //This is actually variable length
} o65_opt_t;
void o65_print_option(o65_opt_t* opt);
#endif

24
sw/kernel/irq.c Normal file
View File

@@ -0,0 +1,24 @@
#include <stdint.h>
#include <conio.h>
#include "devices/interrupt.h"
#include "devices/uart.h"
char lastchar;
void handle_irq() {
uint8_t status;
status = irq_get_status();
if (status & BUTTON) {
cputs("Button Interrupt!\n");
irq_set_status(status & ~BUTTON);
}
if (status & UART) {
lastchar = uart_rxb();
irq_set_status(status & ~UART);
}
}

35
sw/kernel/link.ld Normal file
View File

@@ -0,0 +1,35 @@
MEMORY
{
ZP: start = $0, size = $100, type = rw, define = yes;
SDRAM: start = $200, size = $7cf0, type = rw, define = yes;
ROM: start = $8000, size = $8000, fill = yes, fillval = $ff, file = %O;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
DATA: load = ROM, type = rw, define = yes, run = SDRAM;
BSS: load = SDRAM, type = bss, define = yes;
HEAP: load = SDRAM, type = bss, optional = yes;
STARTUP: load = ROM, type = ro;
ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
VECTORS: load = ROM, type = ro, start = $FFFA;
}
FEATURES {
CONDES: segment = STARTUP,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = STARTUP,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
}
SYMBOLS {
# Define the stack size for the application
__STACKSIZE__: value = $0200, type = weak;
__STACKSTART__: type = weak, value = $0800; # 2k stack
}

42
sw/kernel/main.c Normal file
View File

@@ -0,0 +1,42 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/mapper.h"
#include "devices/sd_card.h"
#include "filesystem/fat.h"
#include "exec.h"
uint8_t buf[512];
int main() {
int i;
uint16_t rca;
clrscr();
cprintf("Hello, world!\n");
for (i = 0; i < 16; i++){
//cprintf("Mapping %1xxxx to %2xxxx\n", i, i);
mapper_write(i, i);
}
cprintf("Enabling Mapper\n");
mapper_enable(1);
sd_init();
rca = sd_get_rca();
cprintf("rca: %x\n", rca);
sd_select_card(rca);
fat_init();
exec("/test.o65");
cprintf("Done!\n");
return 0;
}

View File

@@ -0,0 +1,89 @@
#include <stdio.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/interrupt.h"
int main(void)
{
int retval = 0;
int i;
printf("\nStarting tests...\n\n");
printf("Testing hex_set_8...\n");
for (i = 0; i < 3; i++) {
if (hex_set_8(i+1, i)) {
printf("Failed to write to idx %d!\n", i);
retval++;
}
if (*(uint8_t*)0x7ff0+i != i+1) {
printf("Incorrect value at idx %d!\n", i);
retval++;
}
}
if (!hex_set_8(0xab, 3)) {
printf("Writing to idx 3 should fail!\n");
retval++;
}
printf("Done!\n\n");
printf("Testing hex_set_16...\n");
if (hex_set_16(0xabcd)){
printf("Failed to write!\n");
}
if (*(uint16_t*)0x7ff0 != 0xabcd) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing hex_set_24...\n");
if (hex_set_24(0xabcdef)){
printf("Failed to write!\n");
}
if (*(uint16_t*)0x7ff0 != 0xcdef && *(uint8_t*)0x7ff2 != 0xab) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing hex_enable...\n");
hex_enable(0xa5);
if (*(uint8_t*)0x7ff3 != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing uart_txb_block...\n");
*(uint8_t*)0x7ff5 = 0;
uart_txb_block(0xa5);
if (*(uint8_t*)0x7ff4 != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing uart_status...\n");
*(uint8_t*)0x7ff5 = 0xa5;
if (uart_status() != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing irq_get_status...\n");
*(uint8_t*)0x7fff = 0xa5;
if (irq_get_status() != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
return retval != 0;
}

14
sw/kernel/vectors.s Normal file
View File

@@ -0,0 +1,14 @@
; ---------------------------------------------------------------------------
; vectors.s
; ---------------------------------------------------------------------------
;
; Defines the interrupt vector table.
.import _init
.import _nmi_int, _irq_int
.segment "VECTORS"
.addr _nmi_int ; NMI vector
.addr _init ; Reset vector
.addr _irq_int ; IRQ/BRK vector