From fd9ccdbce47d6d3ca1527626249f80e3689bb617 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Tue, 28 Nov 2023 22:54:26 -0800 Subject: [PATCH] Add serial driver and irq support --- sw/kernel/devices/sd_card.c | 12 +++- sw/kernel/devices/serial.h | 17 ++++++ sw/kernel/devices/serial.s | 94 ++++++++++++++++++++++++++++++++ sw/kernel/interrupts/interrupt.s | 4 +- sw/kernel/kernel.c | 15 ++++- 5 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 sw/kernel/devices/serial.h create mode 100644 sw/kernel/devices/serial.s diff --git a/sw/kernel/devices/sd_card.c b/sw/kernel/devices/sd_card.c index 8eaf708..4dd6a4e 100644 --- a/sw/kernel/devices/sd_card.c +++ b/sw/kernel/devices/sd_card.c @@ -339,12 +339,16 @@ token = 0xFF - response timeout *******************************************************************************/ uint8_t SD_writeSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token) { + + (void)addr; + (void)buf; + (void)token; + + /* uint16_t readAttempts; uint8_t res1, read; uint16_t i; - /* - // set token to none *token = 0xFF; @@ -391,9 +395,11 @@ uint8_t SD_writeSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token) spi_deselect(0); spi_exchange(0xFF); + return res1; + */ - return res1; + return 0; } /******************************************************************************* diff --git a/sw/kernel/devices/serial.h b/sw/kernel/devices/serial.h new file mode 100644 index 0000000..2f85df4 --- /dev/null +++ b/sw/kernel/devices/serial.h @@ -0,0 +1,17 @@ +#ifndef _SERIAL_H +#define _SERIAL_H + +#include + +void serial_handle_irq(); + +void serial_init(); + +void serial_putc(char c); +void serial_puts(char* s); + + +char serial_getc(); +char serial_getc_nb(); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/serial.s b/sw/kernel/devices/serial.s new file mode 100644 index 0000000..0203826 --- /dev/null +++ b/sw/kernel/devices/serial.s @@ -0,0 +1,94 @@ +.MACPACK generic + +.autoimport + +.import _enable_irq, _send_eoi, _uart_txb_block + +.importzp tmp1, ptr1 + +.export _serial_init +.export _serial_handle_irq + +.export _serial_putc, _serial_puts, _serial_getc, _serial_get_nb + +.zeropage + +last_char: .res 1 + + +.code + +UART = $efe6 +UART_TXB = UART +UART_RXB = UART +UART_STATUS = UART + 1 + +; Initialize Serial Port +; No initialization needed, just register irq handler. +.proc _serial_init + lda #<_serial_handle_irq + ldx #>_serial_handle_irq + jsr pushax + lda #$01 + jsr _register_irq + stz last_char + rts +.endproc + +; Serial Port IRQ Handler +; Get the character and store it. +.proc _serial_handle_irq + lda UART_RXB + sta last_char + ora #$80 ; set msb + jsr _send_eoi + rti +.endproc + +; Serial Port Get Character +; If a character has not been received, block until one is. +.proc _serial_getc +L1: lda last_char + bpl L1 + and #$7f + sta last_char + rts +.endproc + +; Serial Port Get Character Non-Blocking +; return last character, even if it has already been read. +; If the character is new, we still clear the new flag. +.proc _serial_get_nb + lda last_char + bpl L1 + and #$7f + sta last_char +L1: rts +.endproc + + +; Serial Port Put Character +; send a single character over the serial port. +.proc _serial_putc + jsr _uart_txb_block + cmp #$0a + bne @1 + lda #$0d + jsr _uart_txb_block +@1: rts +.endproc + +; Send a string over the serial port. Needs stlen +.proc _serial_puts + sta ptr1 ; Store pointer in ptr1 + stx ptr1+1 + ldy #$00 ; initialize y to 0 +L1: lda (ptr1),y ; load character from string + beq L2 ; Quit if NULL + jsr _uart_txb_block ; send character (does not change y or ptr1) + iny ; increment y + bne L1 ; If Y == 0, increment high byte of pointer + inc ptr1+1 + bne L1 ; if high byte wraps around, give up +L2: rts +.endproc \ No newline at end of file diff --git a/sw/kernel/interrupts/interrupt.s b/sw/kernel/interrupts/interrupt.s index 0344b0a..ede0000 100644 --- a/sw/kernel/interrupts/interrupt.s +++ b/sw/kernel/interrupts/interrupt.s @@ -48,7 +48,7 @@ rti sta IRQ_CMD_ADDR lda IRQ_DAT_ADDR ; shift by 2 (oh so only 128 interrupts are supported lol) - lsr + asl tax jmp (irq_table,x) ; use that to index jump table @@ -56,6 +56,7 @@ rti ; void register_irq(void* addr, uint8_t irqn); .proc _register_irq + asl tax jsr popa sta irq_table,x @@ -65,6 +66,7 @@ rti lda #$00 jsr pusha txa + lsr jsr _enable_irq rts .endproc diff --git a/sw/kernel/kernel.c b/sw/kernel/kernel.c index 6441fb3..6870a2e 100644 --- a/sw/kernel/kernel.c +++ b/sw/kernel/kernel.c @@ -3,6 +3,7 @@ #include "interrupts/interrupt.h" #include "devices/mapper.h" #include "devices/rtc.h" +#include "devices/serial.h" void handle_rtc_interrupt() { @@ -14,6 +15,8 @@ void handle_rtc_interrupt() { int main() { + uint8_t c; + cputs("Kernel\n"); cputs("Init Mapper\n"); @@ -32,9 +35,15 @@ int main() { asm volatile("cli"); - // cputs("Initialize Serial\n"); - // // init_serial(); - // enable_irq(2, IRQ_EDGE); + cputs("Initialize Serial\n"); + serial_init(); + + serial_puts("Hello from serial!\n"); + + c = serial_getc(); + + serial_puts("Got a character!: "); + serial_putc(c); while(1);