diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2f670bf..d3f2fd2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,6 +96,8 @@ full sim: - make clean - TEST_PROGRAM=$REPO_TOP/sw/bios/bios.hex TEST_FOLDER=$REPO_TOP/sw/bios make full_sim needs: + - job: build toolchain + artifacts: true - job: build bios artifacts: true - job: build kernel diff --git a/doc/memory_mapper.drawio b/doc/memory_mapper/memory_mapper.drawio similarity index 76% rename from doc/memory_mapper.drawio rename to doc/memory_mapper/memory_mapper.drawio index 296e767..60b7619 100644 --- a/doc/memory_mapper.drawio +++ b/doc/memory_mapper/memory_mapper.drawio @@ -1,66 +1,66 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -68,52 +68,52 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -123,13 +123,13 @@ - + - + - + @@ -137,12 +137,12 @@ - + - + @@ -150,12 +150,12 @@ - + - + @@ -163,61 +163,61 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -225,31 +225,31 @@ - + - + - + - + - + - + - + @@ -259,32 +259,32 @@ - + - + - + - + - + - + - + - + diff --git a/doc/memory_mapper/memory_mapper.drawio.png b/doc/memory_mapper/memory_mapper.drawio.png new file mode 100644 index 0000000..c656da5 Binary files /dev/null and b/doc/memory_mapper/memory_mapper.drawio.png differ diff --git a/doc/memory_mapper/memory_mapper.md b/doc/memory_mapper/memory_mapper.md new file mode 100644 index 0000000..6f216ed --- /dev/null +++ b/doc/memory_mapper/memory_mapper.md @@ -0,0 +1,70 @@ +# Memory Mapper + +## Overview + +The memory mapper gives expands the CPU's address space from 16 bits to 25. +It can be expanded to be 28 bits, but only 25 are needed to access all of +sdram. + +Its architecture is show below: + +![memory_mapper.drawio.png](memory_mapper.drawio.png) + +There are 32 16 bit registers: One for each 4k page in the virtual address +space. The memory mapper is always enabled, but at reset it is identity +mapped, i.e. register _n_ will be reset to value _n_. + +## Interface + +The Memory mapper is composed of 32 identical 16 bit mapping registers + +The chip select should be calculated based on the virtual address. If not, +it will be possible for the CPU to map away access to the mapper, at which +point it is impossible to change the mappings without a reset. + +## Registers + +### Register Map + +| Address | Read | Write | +|--------- |-------------- |-------------- | +| 00 | MM0 Low | MM0 Low | +| 01 | MM0 High | MM0 High | +| 02 | MM1 Low | MM1 Low | +| 03 | MM1 High | MM1 High | +| 04 | MM2 Low | MM2 Low | +| 05 | MM2 High | MM2 High | +| 06 | MM3 Low | MM3 Low | +| 07 | MM3 High | MM3 High | +| 08 | MM4 Low | MM4 Low | +| 09 | MM4 High | MM4 High | +| 0A | MM5 Low | MM5 Low | +| 0B | MM5 High | MM5 High | +| 0C | MM6 Low | MM6 Low | +| 0D | MM6 High | MM6 High | +| 0E | MM7 Low | MM7 Low | +| 0F | MM7 High | MM7 High | +| 10 | MM8 Low | MM8 Low | +| 11 | MM8 High | MM8 High | +| 12 | MM9 Low | MM9 Low | +| 13 | MM9 High | MM9 High | +| 14 | MM10 Low | MM10 Low | +| 15 | MM10 High | MM10 High | +| 16 | MM11 Low | MM11 Low | +| 17 | MM11 High | MM11 High | +| 18 | MM12 Low | MM12 Low | +| 19 | MM12 High | MM12 High | +| 1A | MM13 Low | MM13 Low | +| 1B | MM13 High | MM13 High | +| 1C | MM14 Low | MM14 Low | +| 1D | MM14 High | MM14 High | +| 1E | MM15 Low | MM15 Low | +| 1F | MM15 High | MM15 High | + +### MMn Low + +Low memory map data. Becomes bits [19:12] of physical address. + +### MMn High + +High memory map data. Becomes bits [27:20] of physical address. \ No newline at end of file diff --git a/hw/efinix_fpga/.gitignore b/hw/efinix_fpga/.gitignore index 849df8d..5c4a7b4 100644 --- a/hw/efinix_fpga/.gitignore +++ b/hw/efinix_fpga/.gitignore @@ -7,4 +7,4 @@ outflow *.gtkw *.vvp -.mem \ No newline at end of file +*.mem \ No newline at end of file diff --git a/sw/kernel/devices/mapper.h b/sw/kernel/devices/mapper.h new file mode 100644 index 0000000..55adb2a --- /dev/null +++ b/sw/kernel/devices/mapper.h @@ -0,0 +1,10 @@ +#ifndef _MAPPER_H +#define _MAPPER_H + +#include + +void init_mapper(); + +void map(uint16_t p_page, uint8_t v_page); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/mapper.s b/sw/kernel/devices/mapper.s new file mode 100644 index 0000000..260323d --- /dev/null +++ b/sw/kernel/devices/mapper.s @@ -0,0 +1,38 @@ +.MACPACK generic + +.autoimport + +.export _init_mapper +.export _map + +MAPPER_BASE = $200 + +.code + +; void init_paging(); +; This should be identity mapped at reset, but we can do it again anyway +.proc _init_mapper + ldx #$00 +L1: + txa + lsr + sta MAPPER_BASE,x + lda #$00 + sta MAPPER_BASE+1,x + inx + inx + cpx #$20 + blt L1 + rts +.endproc + +; void map(uint16_t p_page, uint8_t v_page); +.proc _map + asl + tax ; x = v_page * 2 + jsr popa ; low byte of p_page + sta MAPPER_BASE,x ; write low byte to mm_low + jsr popa ; high byte of p_page + sta MAPPER_BASE+1,x ; write high byte to mm_high + rts +.endproc diff --git a/sw/kernel/devices/rtc.s b/sw/kernel/devices/rtc.s index 2d66d16..5f47134 100644 --- a/sw/kernel/devices/rtc.s +++ b/sw/kernel/devices/rtc.s @@ -15,13 +15,13 @@ RTC_OUTPUT = $30 RTC_CONTROL = $30 THRESHOLD_0 = $a0 -; THRESHOLD_1 = $0f -THRESHOLD_1 = $00 +THRESHOLD_1 = $0f +; THRESHOLD_1 = $00 THRESHOLD_2 = $00 THRESHOLD_3 = $00 -; IRQ_THRESHOLD_0 = $32 -IRQ_THRESHOLD_0 = $10 +IRQ_THRESHOLD_0 = $32 +; IRQ_THRESHOLD_0 = $10 IRQ_THRESHOLD_1 = $00 IRQ_THRESHOLD_2 = $00 IRQ_THRESHOLD_3 = $00 diff --git a/sw/kernel/interrupts/interrupt.h b/sw/kernel/interrupts/interrupt.h index 6aeadc2..9520205 100644 --- a/sw/kernel/interrupts/interrupt.h +++ b/sw/kernel/interrupts/interrupt.h @@ -6,6 +6,8 @@ #define BUTTON (1 << 0) #define UART (1 << 1) +void init_interrupts(); + void register_irq(void* addr, uint8_t irqn); uint8_t irq_get_status(); diff --git a/sw/kernel/interrupts/interrupt.s b/sw/kernel/interrupts/interrupt.s index 89e56ce..0344b0a 100644 --- a/sw/kernel/interrupts/interrupt.s +++ b/sw/kernel/interrupts/interrupt.s @@ -3,15 +3,38 @@ .autoimport .import _enable_irq +.import _map .export irq_int, nmi_int .export _register_irq +.export _init_interrupts IRQ_CMD_ADDR = $effc IRQ_DAT_ADDR = $effd IRQ_CMD_READIRQ = $00 +; void init_interrupts(); +; remap the upper page into ram, +; then load the new vector addresses. +.proc _init_interrupts + ; map(001f, f); + lda #$1f + jsr pushax + lda #$f + jsr _map + + lda #irq_int + sta $ffff + + lda #nmi_int + sta $fffb + rts +.endproc .proc nmi_int rti diff --git a/sw/kernel/kernel.c b/sw/kernel/kernel.c index b4a8f4a..6441fb3 100644 --- a/sw/kernel/kernel.c +++ b/sw/kernel/kernel.c @@ -1,11 +1,14 @@ #include #include "devices/interrupt_controller.h" #include "interrupts/interrupt.h" +#include "devices/mapper.h" #include "devices/rtc.h" void handle_rtc_interrupt() { - cputs("In IRQ interrupt!\n"); + // cputs("In IRQ interrupt!\n"); + cputc('A'); + send_eoi(); asm volatile ("rti"); } @@ -13,11 +16,11 @@ int main() { cputs("Kernel\n"); - // cputs("Init Paging\n") - // init_paging() + cputs("Init Mapper\n"); + init_mapper(); - // cputs("Initialize Interrupts\n"); - // init_interrupts(); + cputs("Initialize Interrupts\n"); + init_interrupts(); cputs("Initialize Interrupt Controller\n"); init_interrupt_controller();