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

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