diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index afdd6ae..aa9505a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -140,6 +140,24 @@ mapper_code sim: - TEST_PROGRAM_NAME=mapper_test make mapper_code_tb - ./mapper_code_tb +multiplier_code sim: + tags: + - linux + - iverilog + stage: simulate + needs: + - job: build toolchain + artifacts: true + artifacts: + paths: + - hw/efinix_fpga/simulation/mapper_code_tb.vcd + script: + - source init_env.sh + - cd hw/efinix_fpga/simulation + - make clean + - TEST_PROGRAM_NAME=multiplier_test make mapper_code_tb + - ./mapper_code_tb + interrupt_controller sim: tags: - linux diff --git a/sw/cc65 b/sw/cc65 index 58518b6..9824f6e 160000 --- a/sw/cc65 +++ b/sw/cc65 @@ -1 +1 @@ -Subproject commit 58518b6ff56a4e3339c6faeb1251d73d1a6a6b99 +Subproject commit 9824f6e3d40752e4bd8d0a4b40cb65d922e36fce diff --git a/sw/fsdir/test.txt b/sw/fsdir/test.txt new file mode 100644 index 0000000..1b99b87 --- /dev/null +++ b/sw/fsdir/test.txt @@ -0,0 +1 @@ +This is a text file, which is composed of text. \ No newline at end of file diff --git a/sw/fsdir/verylargetextwithverylongname.txt b/sw/fsdir/verylargetextwithverylongname.txt new file mode 100644 index 0000000..a5e31d9 --- /dev/null +++ b/sw/fsdir/verylargetextwithverylongname.txt @@ -0,0 +1,33 @@ +very large text file with a very long name +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ +ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ +abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz +~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>? diff --git a/sw/kernel/devices/io.inc65 b/sw/kernel/devices/io.inc65 index 42b0910..56ccdc1 100644 --- a/sw/kernel/devices/io.inc65 +++ b/sw/kernel/devices/io.inc65 @@ -10,4 +10,21 @@ SPI_BAUD = $efd8 SPI_INPUT = $efd9 SPI_OUTPUT = $efda SPI_CTRL = $efdb -SPI_STATUS = SPI_CTRL \ No newline at end of file +SPI_STATUS = SPI_CTRL + +MULTIPLIER_BASE = $eff0 + +MULTIPLIER_AL = MULTIPLIER_BASE + 0 +MULTIPLIER_AH = MULTIPLIER_BASE + 1 +MULTIPLIER_BL = MULTIPLIER_BASE + 2 +MULTIPLIER_BH = MULTIPLIER_BASE + 3 + +MULTIPLIER_OLL = MULTIPLIER_BASE + 4 +MULTIPLIER_OLH = MULTIPLIER_BASE + 5 +MULTIPLIER_OHL = MULTIPLIER_BASE + 6 +MULTIPLIER_OHH = MULTIPLIER_BASE + 7 + +GOLDEN_OUTPUT_0 = $03 +GOLDEN_OUTPUT_1 = $0a +GOLDEN_OUTPUT_2 = $08 +GOLDEN_OUTPUT_3 = $00 \ No newline at end of file diff --git a/sw/kernel/devices/multiplier.h b/sw/kernel/devices/multiplier.h new file mode 100644 index 0000000..e60764f --- /dev/null +++ b/sw/kernel/devices/multiplier.h @@ -0,0 +1,12 @@ +#ifndef _MULTIPLER_H +#define _MULTIPLER_H + +#include + +/* Multiply 2 integers into 1 long */ +uint32_t lmulii(uint16_t a, uint16_t b); + +/* Multiply 2 integers into 1 integer, discarding upper bits. */ +uint16_t imulii(uint16_t a, uint16_t b); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/multiplier.s b/sw/kernel/devices/multiplier.s new file mode 100644 index 0000000..7c3d6a3 --- /dev/null +++ b/sw/kernel/devices/multiplier.s @@ -0,0 +1,36 @@ +.include "io.inc65" + +.MACPACK generic + +.import popax +.importzp sreg + +.export _lmulii, _imulii + +.code + +.proc _lmulii + sta MULTIPLIER_BL + stx MULTIPLIER_BH + jsr popax + sta MULTIPLIER_AL + stx MULTIPLIER_AH + lda MULTIPLIER_OHL + sta sreg + lda MULTIPLIER_OHH + sta sreg+1 + lda MULTIPLIER_OLL + ldx MULTIPLIER_OLH + rts +.endproc + +.proc _imulii + sta MULTIPLIER_BL + stx MULTIPLIER_BH + jsr popax + sta MULTIPLIER_AL + stx MULTIPLIER_AH + lda MULTIPLIER_OLL + ldx MULTIPLIER_OLH + rts +.endproc \ No newline at end of file diff --git a/sw/kernel/filesystems/fat32.h b/sw/kernel/filesystems/fat32.h new file mode 100644 index 0000000..e9c97ad --- /dev/null +++ b/sw/kernel/filesystems/fat32.h @@ -0,0 +1,53 @@ +#ifndef _FAT32_H +#define _FAT32_H + +#include +#include + +void fat32_init(); + +extern uint32_t root_cluster; +extern uint16_t fat_start_sector; +extern uint32_t data_start_sector; +extern uint32_t fat_size; +extern uint8_t* sd_buf; +extern uint8_t sectors_per_cluster; +extern uint8_t log2_sectors_per_cluster; + +struct fat32_directory_entry { + char file_name[8]; + char file_ext[3]; + uint8_t attr1; + uint8_t attr2; + uint8_t create_time_10ms; + uint16_t create_time; + uint16_t create_date; + uint16_t access_date; + uint16_t cluster_high; + uint16_t modified_time; + uint16_t modified_date; + uint16_t cluster_low; + uint32_t file_size; +}; + +struct lfn_entry { + uint8_t sequence_number; + uint16_t name_0[5]; + uint8_t attributes; + uint8_t type; + uint8_t checksum; + uint16_t name_1[6]; + uint16_t cluster_low; + uint16_t name_2[2]; +}; + +int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry); +int8_t fat32_read_sector(uint32_t cluster, uint32_t sector, void* buf); +uint32_t fat32_next_cluster(uint32_t cluster); + +int8_t fat32_file_open(const char* filename); +size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes); +size_t fat32_file_write(int8_t fd, const void* buf, size_t nbytes); +int8_t fat32_file_close(int8_t fd); + +#endif diff --git a/sw/kernel/filesystems/fat32.s b/sw/kernel/filesystems/fat32.s new file mode 100644 index 0000000..6e6346f --- /dev/null +++ b/sw/kernel/filesystems/fat32.s @@ -0,0 +1,112 @@ +.MACPACK generic + +.autoimport +.feature string_escapes + +.importzp ptr1, sreg + +.import _SD_readSingleBlock + +.export _fat32_init + +.export _root_cluster, _fat_start_sector, _data_start_sector +.export _fat_size, _sd_buf, _sectors_per_cluster, _log2_sectors_per_cluster + + +.data +_root_cluster: .res 4 +_fat_start_sector: .res 2 +_data_start_sector: .res 4 +_fat_size: .res 4 +_sectors_per_cluster: .res 1 +_log2_sectors_per_cluster: .res 1 + +_sd_buf: .res 512 + +data_start_sect_str: .asciiz "Data sector start: 0x%lx\n" +starting_cluster_str: .asciiz "Root cluster num: %lx\n"; +value_str: .asciiz "Value: 0x%x\n" + +.code + +bytes_per_sector = _sd_buf + $0B +sectors_per_cluster = _sd_buf + $0D +reserved_sectors = _sd_buf + $0E +fat_count = _sd_buf + $10 +sectors_per_fat = _sd_buf + $24 +root_cluster_offs = _sd_buf + $2C + +.proc _fat32_init + ; load sector 0 into sd_buf + lda #$00 + ldx #$00 + stz sreg + stz sreg+1 + jsr pusheax + lda #<_sd_buf + ldx #>_sd_buf + jsr pushax + lda #ptr1 + jsr _SD_readSingleBlock + + lda sectors_per_cluster + sta _sectors_per_cluster + + ldx #$0 +@1: bit #$01 + bne L0 + inx + lsr + bra @1 + +L0: txa + sta _log2_sectors_per_cluster + + ldx #$00 +L1: lda root_cluster_offs,x + sta _root_cluster,x + inx + cpx #$4 + blt L1 + + ; Multiply reserved sectors and bytes per sector, then divide by 512 to get sd sectors + lda reserved_sectors + jsr pusha0 + lda bytes_per_sector + ldx bytes_per_sector+1 + jsr _imulii + txa + lsr + sta _fat_start_sector + stz _fat_start_sector + 1 + + ; multiply fat size and number of fats to get total fat size + lda fat_count + jsr pusha0 + lda sectors_per_fat + ldx sectors_per_fat+1 + jsr _lmulii + sta _fat_size + stx _fat_size+1 + lda sreg + sta _fat_size+2 + lda sreg+1 + sta _fat_size+3 + + + ; Add fat size to starting fat sector to get data start sector + clc + lda _fat_size + adc _fat_start_sector + sta _data_start_sector + lda _fat_size+1 + adc _fat_start_sector+1 + sta _data_start_sector+1 + lda _fat_size+2 + sta _data_start_sector+2 + lda _fat_size+3 + sta _data_start_sector+3 + + rts +.endproc diff --git a/sw/kernel/filesystems/fat32_c.c b/sw/kernel/filesystems/fat32_c.c new file mode 100644 index 0000000..a391212 --- /dev/null +++ b/sw/kernel/filesystems/fat32_c.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include + +#include "fat32.h" +#include "fs.h" + +static struct fops fat32_file_ops = {fat32_file_open, fat32_file_close, fat32_file_read, fat32_file_write}; + +int8_t fd_val; + + +//TODO +size_t fat32_file_write(int8_t fd, const void* buf, size_t nbytes) { + (void)fd; + (void)buf; + (void)nbytes; + return -1; +} + +/* + * file_close + * DESCRIPTION: close device abstracted as file + * INPUTS: fd -- file descriptor for file to be closed + * OUTPUTS: none + * RETURN VALUE: none + * SIDE EFFECTS: none + */ +int8_t fat32_file_close(int8_t fd) { + struct pcb* pcb; + pcb = get_pcb_ptr(); + + /* update pcb to remove process */ + pcb->file_desc_array[fd].flags = !IN_USE; + return 0; +} + +int8_t fat32_file_open(const char* filename) { + int8_t ret; + int8_t i; + int8_t fd; + + struct fat32_directory_entry dentry; + + struct pcb* pcb = get_pcb_ptr(); + + ret = fat32_get_cluster_by_name(filename, &dentry); + if (ret) { + cprintf("Error finding cluster for filename"); + return -1; + } + + /* try to find an empty file desciptor, fail otherwise */ + //TODO We start at 3 here because 0, 1, 2 will be reserved later + for (i = 3; i < FILE_DESC_SIZE; i++) { + if (pcb->file_desc_array[i].flags == !IN_USE) { + fd = i; + break; + } + } + if (fd == -1){ + return -1; + } + + /* add process */ + pcb->file_desc_array[fd].f32_dentry = dentry; + pcb->file_desc_array[fd].flags = IN_USE; + pcb->file_desc_array[fd].file_pos = 0; + + pcb->file_desc_array[fd].file_ops = &fat32_file_ops; + + return fd; +} + +size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { + uint16_t i; + size_t offset; + size_t leftover_length; + size_t bytes_read = 0; + size_t clusters; + uint32_t sector; + struct pcb* pcb = get_pcb_ptr(); + struct file_desc* fdesc = &pcb->file_desc_array[fd]; + + uint32_t cluster_seq = fdesc->file_pos >> (9 + log2_sectors_per_cluster); + + uint32_t cluster = ((uint32_t)fdesc->f32_dentry.cluster_high << 16) | fdesc->f32_dentry.cluster_low; + + /* validate starting position isn't past end of file */ + if (fdesc->file_pos >= fdesc->f32_dentry.file_size){ + return 0; + } + /* validate final pos isn't past end of file */ + if (fdesc->file_pos+nbytes > fdesc->f32_dentry.file_size){ + nbytes = fdesc->f32_dentry.file_size - fdesc->file_pos; + } + + + // This can stay for now, as long as cluster_seq is correct. + for (i = 0; i < cluster_seq; i++) { + cluster = fat32_next_cluster(cluster); + } + + clusters = nbytes >> (9 + log2_sectors_per_cluster); + + + /* Handle first unaligned block */ + offset = fdesc->file_pos % 512; // This is the offset into the sector, not the cluster + leftover_length = 512 - offset; + + sector = (fdesc->file_pos >> 9) & (sectors_per_cluster-1); + + if (leftover_length != 0) { + if (nbytes <= leftover_length) { + + fat32_read_sector(cluster, sector, sd_buf); + memcpy(buf, sd_buf + offset, nbytes); + bytes_read += nbytes; + fdesc->file_pos += bytes_read; + return bytes_read; + } else { + fat32_read_sector(cluster, sector, sd_buf); + memcpy(buf, sd_buf + offset, leftover_length); + bytes_read += leftover_length; + fdesc->file_pos += bytes_read; + } + } + + + /* Handle middle aligned blocks */ + for (i = 0; i < clusters; i++) { + cluster = fat32_next_cluster(cluster); + if (cluster >= 0xffffff00) { + // cprintf("Last cluster in file!\n"); + } + + if (nbytes - bytes_read > 512) { + leftover_length = 512; + } else { + leftover_length = nbytes - bytes_read; + } + + fat32_read_sector(cluster, cluster, sd_buf); + memcpy((uint8_t*)buf+bytes_read, sd_buf, leftover_length); + bytes_read += leftover_length; + fdesc->file_pos += bytes_read; + if (bytes_read == nbytes) { + return bytes_read; + } + } + + return bytes_read; +} + +// Read the sector offset from a given cluster into buf +// Why do we need this though, this is just doing a single multiplication? +// No, it is also doing an addition +int8_t fat32_read_sector(uint32_t cluster, uint32_t sector, void* buf) { + uint8_t error; + uint32_t addr = (cluster - 2) * sectors_per_cluster + sector + data_start_sector; + SD_readSingleBlock(addr, buf, &error); + return error; +} + +// This will not handle clusters numbers that leaves a sector +uint32_t fat32_next_cluster(uint32_t cluster) { + uint8_t error; + uint32_t addr = fat_start_sector; + uint32_t cluster_val; + SD_readSingleBlock(addr, sd_buf, &error); + cluster_val = ((uint32_t*)sd_buf)[cluster]; + return cluster_val; +} + +int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry) { + struct fat32_directory_entry* local_entry; + int i = 0; + + uint32_t cluster; + + cluster = fat32_next_cluster(root_cluster); + + cprintf("Sectors per cluster: %hhx\n", sectors_per_cluster); + + fat32_read_sector(root_cluster, 0, sd_buf); + for (i = 0; i < 16; i++){ + local_entry = (struct fat32_directory_entry*)(sd_buf + i*32); + if (local_entry->attr1 == 0xf || local_entry->attr1 & 0x8 || !local_entry->attr1) { + continue; + } + cprintf("Name: %.11s\n", local_entry->file_name, local_entry->file_ext); + if (!strncmp(local_entry->file_name, name, 11)) { + i = -1; + break; + } + } + if (i != -1) { + cprintf("Failed to find file.\n"); + return -1; + } + + cprintf("Found file!\n"); + memcpy(dentry, local_entry, 32); + return 0; +} diff --git a/sw/kernel/filesystems/fs.h b/sw/kernel/filesystems/fs.h new file mode 100644 index 0000000..29b7cc1 --- /dev/null +++ b/sw/kernel/filesystems/fs.h @@ -0,0 +1,22 @@ +#ifndef _FS_H +#define _FS_H + +#include +#include + +#include + +/* syscalls for files */ +size_t file_read(int8_t fd, void* buf, size_t nbytes); +size_t file_write(int8_t fd, const void* buf, size_t nbytes); +int8_t file_open(const char* filename); +int8_t file_close(int8_t fd); + +/* syscalls for directories */ +size_t directory_read(int8_t fd, void* buf, size_t nbytes); +size_t directory_write(int8_t fd, const void* buf, size_t nbytes); +int8_t directory_open(const char* filename); +int8_t directory_close(int8_t fd); + + +#endif \ No newline at end of file diff --git a/sw/kernel/kernel.c b/sw/kernel/kernel.c index e81a8fc..d96edf4 100644 --- a/sw/kernel/kernel.c +++ b/sw/kernel/kernel.c @@ -6,9 +6,10 @@ #include "devices/mapper.h" #include "devices/rtc.h" #include "devices/serial.h" - #include "devices/terminal.h" +#include "filesystems/fat32.h" + void handle_rtc_interrupt() { // cputs("In IRQ interrupt!\n"); @@ -20,18 +21,21 @@ void handle_rtc_interrupt() { char buf[128]; int main() { + int8_t fd; + size_t nbytes, i; + cputs("Kernel\n"); - // cputs("Init Mapper\n"); + cputs("Init Mapper\n"); init_mapper(); - // cputs("Initialize Interrupts\n"); + cputs("Initialize Interrupts\n"); init_interrupts(); - // cputs("Initialize Interrupt Controller\n"); + cputs("Initialize Interrupt Controller\n"); init_interrupt_controller(); - // cputs("Initialize RTC\n"); + cputs("Initialize RTC\n"); init_rtc(); register_irq(&handle_rtc_interrupt, 0); @@ -41,22 +45,26 @@ int main() { asm volatile("cli"); - // cputs("Initialize Serial\n"); + cputs("Initialize Serial\n"); serial_init(); serial_puts("Hello from serial!\n"); + + fat32_init(); - terminal_open(NULL); - terminal_write(0, "Terminal Write\n", 15); + /* This is what is going to be part of open */ + fd = fat32_file_open("VERYLA~1TXT"); + cprintf("fd: %x\n", fd); - while(1) { - if (terminal_read(0, buf, 128)) { - cprintf("Fail\n"); - break; + nbytes = fat32_file_read(fd, buf, 23); + for (i = 0; i < nbytes; i++) { + cprintf("%c", buf[i]); + } + + while ((nbytes = fat32_file_read(fd, buf, 128))){ + for (i = 0; i < nbytes; i++) { + cprintf("%c", buf[i]); } - terminal_write(0, "Got: ", 5); - terminal_write(0, buf, strlen(buf)); - terminal_write(0, "\n", 1); } return 0; diff --git a/sw/kernel/process/process.c b/sw/kernel/process/process.c new file mode 100644 index 0000000..cbc5210 --- /dev/null +++ b/sw/kernel/process/process.c @@ -0,0 +1,9 @@ +#include + + +struct pcb fake_pcb; + +//TODO +struct pcb* get_pcb_ptr() { + return &fake_pcb; +} \ No newline at end of file diff --git a/sw/kernel/process/process.h b/sw/kernel/process/process.h new file mode 100644 index 0000000..2a569df --- /dev/null +++ b/sw/kernel/process/process.h @@ -0,0 +1,46 @@ +#ifndef _PROCESS_H +#define _PROCESS_H + +#include + +#include +#include + +#define FILE_DESC_SIZE 8 + + +#define IN_USE 1 + + +struct fops { + int8_t (*open)(const char* filename); + int8_t (*close)(int8_t fd); + size_t (*read)(int8_t fd, void* buf, size_t nbytes); + size_t (*write)(int8_t fd, const void* buf, size_t nbytes); +}; + +struct file_desc { + struct fops* file_ops; + uint8_t fs_type; + union { + struct fat32_directory_entry f32_dentry; + }; + uint32_t file_pos; + uint32_t flags; +}; + +/* Process Control Block struct */ +struct pcb { + struct file_desc file_desc_array[FILE_DESC_SIZE]; + int32_t is_vidmapped; + uint8_t args[128]; + uint16_t execute_return; + uint16_t pid; + uint16_t parent_pid; + uint16_t parent_esp; +}; + + +struct pcb* get_pcb_ptr(); + +#endif \ No newline at end of file diff --git a/sw/script/create_verilog_image.sh b/sw/script/create_verilog_image.sh index 51249fd..a4dfe2c 100644 --- a/sw/script/create_verilog_image.sh +++ b/sw/script/create_verilog_image.sh @@ -35,6 +35,4 @@ udisksctl unmount -b $LOOP udisksctl loop-delete -b $LOOP -echo "$(tput bold setaf 11)Converting Image to Verilog$(tput sgr 0)" -objcopy --input-target=binary --output-target=verilog --verilog-data-width=1 $FILE $FILE.hex echo "$(tput bold setaf 10)Done!$(tput sgr 0)" diff --git a/sw/test_code/fs_test/Makefile b/sw/test_code/fs_test/Makefile new file mode 100644 index 0000000..c37e3e4 --- /dev/null +++ b/sw/test_code/fs_test/Makefile @@ -0,0 +1,49 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +SIM=../../cc65/bin/sim65 +CFLAGS=-T -t sim65c02 -I. -I $(REPO_TOP)/sw/kernel +LDFLAGS=-m $(NAME).map + +NAME=fs_test + +SIMARGS= + +BIN=$(NAME).bin + +FS=$(REPO_TOP)/sw/script/fs.fat + +LISTS=lists + +EXT_SRCS=$(REPO_TOP)/sw/kernel/filesystems/fat32.s $(REPO_TOP)/sw/kernel/filesystems/fat32_c.c + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +SRCS+=$(EXT_SRCS) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +run: all + $(SIM) $(SIMARGS) $(BIN) + +all: fs.fat $(BIN) + +$(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 $@ + +fs.fat: $(FS) + cp $^ . + + +$(LISTS): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/fs_test/asm_harness.s b/sw/test_code/fs_test/asm_harness.s new file mode 100644 index 0000000..c227854 --- /dev/null +++ b/sw/test_code/fs_test/asm_harness.s @@ -0,0 +1,5 @@ +.import _printf +.export _cprintf + +_cprintf: + jmp _printf \ No newline at end of file diff --git a/sw/test_code/fs_test/harness.c b/sw/test_code/fs_test/harness.c new file mode 100644 index 0000000..d11e150 --- /dev/null +++ b/sw/test_code/fs_test/harness.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +#define FILE_PATH "fs.fat" + +struct pcb fake_pcb; + +//TODO +struct pcb* get_pcb_ptr() { + return &fake_pcb; +} + +uint32_t lmulii(uint16_t a, uint16_t b) { + printf("lmulii: %x * %x = %x\n", a, b, a*b); + return a * b; +} + +uint16_t imulii(uint16_t a, uint16_t b) { + printf("imulii: %x * %x = %x\n", a, b, a*b); + return a * b; +} + +uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *error) { + FILE* f = fopen(FILE_PATH, "rb"); + (void)error; + fseek(f, addr * 512, SEEK_SET); + fread(buf, 512, 1, f); + fclose(f); + return 0; +} diff --git a/sw/test_code/fs_test/main.c b/sw/test_code/fs_test/main.c new file mode 100644 index 0000000..62042cf --- /dev/null +++ b/sw/test_code/fs_test/main.c @@ -0,0 +1,31 @@ +#include +#include +#include + +void fat32_init(void); + +char data [256]; + +int main(void) { + int8_t fd; + size_t i; + size_t nbytes; + fat32_init(); + + cprintf("log2 sectors per cluster: %x\n", log2_sectors_per_cluster); + + /* This is what is going to be part of open */ + fd = fat32_file_open("VERYLA~1TXT"); + cprintf("fd: %x\n", fd); + + nbytes = fat32_file_read(fd, data, 123); + for (i = 0; i < nbytes; i++) { + cprintf("%c", data[i]); + } + + while ((nbytes = fat32_file_read(fd, data, 256))){ + for (i = 0; i < nbytes; i++) { + cprintf("%c", data[i]); + } + } +} \ No newline at end of file diff --git a/sw/test_code/multiplier_test/Makefile b/sw/test_code/multiplier_test/Makefile new file mode 100644 index 0000000..1f04f9c --- /dev/null +++ b/sw/test_code/multiplier_test/Makefile @@ -0,0 +1,39 @@ +CC=../../cc65/bin/cl65 +LD=../../cc65/bin/cl65 +CFLAGS=-T -t none -I. --cpu "65C02" +LDFLAGS=-C link.ld -m $(NAME).map + +NAME=multiplier_test + +BIN=$(NAME).bin +HEX=$(NAME).hex + +LISTS=lists + +SRCS=$(wildcard *.s) $(wildcard *.c) +SRCS+=$(wildcard **/*.s) $(wildcard **/*.c) +OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) +OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) + +# Make sure the kernel linked to correct address, no relocation! +all: $(HEX) + +$(HEX): $(BIN) + objcopy --input-target=binary --output-target=verilog $(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): + mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + +.PHONY: clean +clean: + rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + diff --git a/sw/test_code/multiplier_test/link.ld b/sw/test_code/multiplier_test/link.ld new file mode 100644 index 0000000..66a42fe --- /dev/null +++ b/sw/test_code/multiplier_test/link.ld @@ -0,0 +1,35 @@ +MEMORY +{ + ZP: start = $0, size = $100, type = rw, define = yes; + SDRAM: start = $9200, size = $4d00, type = rw, define = yes; + ROM: start = $F000, size = $1000, 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 +} diff --git a/sw/test_code/multiplier_test/main.s b/sw/test_code/multiplier_test/main.s new file mode 100644 index 0000000..f3fa369 --- /dev/null +++ b/sw/test_code/multiplier_test/main.s @@ -0,0 +1,73 @@ +.MACPACK generic + +.export _init, _nmi_int, _irq_int + +MULTIPLIER_BASE = $eff0 + +MULTIPLIER_AL = MULTIPLIER_BASE + 0 +MULTIPLIER_AH = MULTIPLIER_BASE + 1 +MULTIPLIER_BL = MULTIPLIER_BASE + 2 +MULTIPLIER_BH = MULTIPLIER_BASE + 3 + +MULTIPLIER_OLL = MULTIPLIER_BASE + 4 +MULTIPLIER_OLH = MULTIPLIER_BASE + 5 +MULTIPLIER_OHL = MULTIPLIER_BASE + 6 +MULTIPLIER_OHH = MULTIPLIER_BASE + 7 + +GOLDEN_OUTPUT_0 = $03 +GOLDEN_OUTPUT_1 = $0a +GOLDEN_OUTPUT_2 = $08 +GOLDEN_OUTPUT_3 = $00 + +.zeropage +finish: .res 1 + +.data + +output: .res 4 + +.code + +_nmi_int: +_irq_int: + +_init: + ldx #$ff + txs + + lda #$01 + sta MULTIPLIER_AL + lda #$02 + sta MULTIPLIER_AH + + lda #$03 + sta MULTIPLIER_BL + lda #$04 + sta MULTIPLIER_BH + + ldx #$00 +L1: lda MULTIPLIER_OLL,x + sta output,x + inx + cpx #$4 + bne L1 + + lda output + cmp #GOLDEN_OUTPUT_0 + bne fail + lda output+1 + cmp #GOLDEN_OUTPUT_1 + bne fail + lda output+2 + cmp #GOLDEN_OUTPUT_2 + bne fail + lda output+3 + cmp #GOLDEN_OUTPUT_3 + bne fail + + lda #$6d + sta finish + +fail: + lda #$bd + sta finish \ No newline at end of file diff --git a/sw/test_code/multiplier_test/vectors.s b/sw/test_code/multiplier_test/vectors.s new file mode 100644 index 0000000..81ae6e0 --- /dev/null +++ b/sw/test_code/multiplier_test/vectors.s @@ -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 \ No newline at end of file