From 34cfc01d1c8913255f978c1773b8db55dacf242b Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Thu, 3 Nov 2022 17:35:57 -0500 Subject: [PATCH] Potentially a valid zero stage boot loader based on cva6. --- tests/testsBP/zsbl/Makefile | 112 +++++++++++++++++++++++++++++++ tests/testsBP/zsbl/bios.s | 98 +++++++++++++++++++++++++++ tests/testsBP/zsbl/copyFlash.c | 40 +++++++++++ tests/testsBP/zsbl/gpt.c | 119 +++++++++++++++++++++++++++++++++ tests/testsBP/zsbl/gpt.h | 39 +++++++++++ tests/testsBP/zsbl/main.c | 26 +++++++ tests/testsBP/zsbl/sdcDriver.c | 69 +++++++++++++++++++ tests/testsBP/zsbl/sdcDriver.h | 10 +++ tests/testsBP/zsbl/smp.h | 52 ++++++++++++++ tests/testsBP/zsbl/uart.c | 91 +++++++++++++++++++++++++ tests/testsBP/zsbl/uart.h | 27 ++++++++ 11 files changed, 683 insertions(+) create mode 100644 tests/testsBP/zsbl/Makefile create mode 100644 tests/testsBP/zsbl/bios.s create mode 100644 tests/testsBP/zsbl/copyFlash.c create mode 100644 tests/testsBP/zsbl/gpt.c create mode 100644 tests/testsBP/zsbl/gpt.h create mode 100644 tests/testsBP/zsbl/main.c create mode 100644 tests/testsBP/zsbl/sdcDriver.c create mode 100644 tests/testsBP/zsbl/sdcDriver.h create mode 100644 tests/testsBP/zsbl/smp.h create mode 100644 tests/testsBP/zsbl/uart.c create mode 100644 tests/testsBP/zsbl/uart.h diff --git a/tests/testsBP/zsbl/Makefile b/tests/testsBP/zsbl/Makefile new file mode 100644 index 00000000..348a67cd --- /dev/null +++ b/tests/testsBP/zsbl/Makefile @@ -0,0 +1,112 @@ +CEXT := c +CPPEXT := cpp +AEXT := s +SEXT := S +SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\) +OBJEXT := o +DEPEXT := d +SRCDIR := . +BUILDDIR := OBJ + +SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort) +OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) + +TARGETDIR := bin +TARGET := $(TARGETDIR)/fpga-test-sdc +ROOT := .. +LIBRARY_DIRS := +LIBRARY_FILES := + +MARCH :=-march=rv64imfdc +MABI :=-mabi=lp64d +LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles +LINKER :=$(ROOT)/linker1000.x + + +AFLAGS =$(MARCH) $(MABI) -W +CFLAGS =$(MARCH) $(MABI) -mcmodel=medany -O2 +AS=riscv64-unknown-elf-as +CC=riscv64-unknown-elf-gcc +AR=riscv64-unknown-elf-ar + + +#Default Make +all: directories $(TARGET).memfile + +#Remake +remake: clean all + +#Make the Directories +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + + +#Needed for building additional library projects +ifdef LIBRARY_DIRS +LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%} +INC+=${LIBRARY_DIRS:%=-I%} + +${LIBRARY_DIRS}: + make -C $@ -j 1 + +.PHONY: $(LIBRARY_DIRS) $(TARGET) +endif + + +#Pull in dependency info for *existing* .o files +-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) + +#Link +$(TARGET): $(OBJECTS) $(LIBRARY_DIRS) + $(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER} + + +#Compile +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# gcc won't output dependencies for assembly files for some reason +# most asm files don't have dependencies so the echo will work for now. +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +# C++ +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# convert to hex +$(TARGET).memfile: $(TARGET) + @echo 'Making object dump file.' + @riscv64-unknown-elf-objdump -D $< > $<.objdump + @echo 'Making memory file' + riscv64-unknown-elf-elf2hex --bit-width 64 --input $^ --output $@ + extractFunctionRadix.sh $<.objdump + mkdir -p ../../imperas-riscv-tests/work/rv64BP/ + cp -f $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/ diff --git a/tests/testsBP/zsbl/bios.s b/tests/testsBP/zsbl/bios.s new file mode 100644 index 00000000..cf00b765 --- /dev/null +++ b/tests/testsBP/zsbl/bios.s @@ -0,0 +1,98 @@ +PERIOD = 11000000 +#PERIOD = 20 + +.section .init +.global _start +.type _start, @function + + +_start: + # Initialize global pointer + .option push + .option norelax + 1:auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) + .option pop + + li x1, 0 + li x2, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + + + # set the stack pointer to the top of memory - 8 bytes (pointer size) + li sp, 0x87FFFFF8 + + jal ra, main + + fence.i + # now toggle led so we know the copy completed. + + # write to gpio + li t2, 0xFF + la t3, 0x1006000C + li t4, 5 + +loop: + + # delay + li t0, PERIOD/2 +delay1: + addi t0, t0, -1 + bge t0, x0, delay1 + sw t2, 0x0(t3) + + li t0, PERIOD/2 +delay2: + addi t0, t0, -1 + bge t0, x0, delay2 + sw x0, 0x0(t3) + + addi t4, t4, -1 + bgt t4, x0, loop + + + # now that the card is copied and the led toggled we + # jump to the copied contents of the sd card. + +jumpToLinux: + csrr a0, mhartid + li s0, 0x80000000 + la a1, _dtb + jr s0 +end_of_bios: + + + +.section .dtb +.globl _dtb +.align 4, 0 +_dtb: +.incbin "wally-vcu118.dtb" + diff --git a/tests/testsBP/zsbl/copyFlash.c b/tests/testsBP/zsbl/copyFlash.c new file mode 100644 index 00000000..4165fe21 --- /dev/null +++ b/tests/testsBP/zsbl/copyFlash.c @@ -0,0 +1,40 @@ +/////////////////////////////////////////// +// copyFlash.sv +// +// Written: Ross Thompson September 25, 2021 +// Modified: +// +// Purpose: copies flash card into memory +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +#include "sdcDriver.h" + +void copyFlash(long int blockAddr, long int * Dst, int numBlocks) { + + setSDCCLK(4); // must be even, 1 gives no division. + waitInitSDC(); + + int index; + + for(index = 0; index < numBlocks; index++) { + copySDC512(blockAddr+(index*512), Dst+(index*512/8)); + } + + +} diff --git a/tests/testsBP/zsbl/gpt.c b/tests/testsBP/zsbl/gpt.c new file mode 100644 index 00000000..0c645d70 --- /dev/null +++ b/tests/testsBP/zsbl/gpt.c @@ -0,0 +1,119 @@ +#include "gpt.h" + +#include "sdcDriver.h" + +#include "uart.h" +#include + +int gpt_find_boot_partition(long int* dest, uint32_t size) +{ + //int ret = init_sd(); + int ret; + setSDCCLK(4); // must be even, 1 gives no division. + waitInitSDC(); + ret = 0; + if (ret != 0) { + print_uart("could not initialize sd... exiting\r\n"); + return -1; + } + + print_uart("sd initialized!\r\n"); + + // load LBA1 + size_t block_size = 512/8; + long int lba1_buf[block_size]; + + //int res = sd_copy(lba1_buf, 1, 1); + int res; + copySDC512(1, lba1_buf); + res = 0; + + if (res != 0) + { + print_uart("SD card failed!\r\n"); + print_uart("sd copy return value: "); + print_uart_addr(res); + print_uart("\r\n"); + return -2; + } + + gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; + + print_uart("gpt partition table header:"); + print_uart("\r\n\tsignature:\t"); + print_uart_addr(lba1->signature); + print_uart("\r\n\trevision:\t"); + print_uart_int(lba1->revision); + print_uart("\r\n\tsize:\t\t"); + print_uart_int(lba1->header_size); + print_uart("\r\n\tcrc_header:\t"); + print_uart_int(lba1->crc_header); + print_uart("\r\n\treserved:\t"); + print_uart_int(lba1->reserved); + print_uart("\r\n\tcurrent lba:\t"); + print_uart_addr(lba1->current_lba); + print_uart("\r\n\tbackup lda:\t"); + print_uart_addr(lba1->backup_lba); + print_uart("\r\n\tpartition entries lba: \t"); + print_uart_addr(lba1->partition_entries_lba); + print_uart("\r\n\tnumber partition entries:\t"); + print_uart_int(lba1->nr_partition_entries); + print_uart("\r\n\tsize partition entries: \t"); + print_uart_int(lba1->size_partition_entry); + print_uart("\r\n"); + + long int lba2_buf[block_size]; + + //res = sd_copy(lba2_buf, lba1->partition_entries_lba, 1); + copySDC512(lba1->partition_entries_lba, lba2_buf); + res = 0; + + if (res != 0) + { + print_uart("SD card failed!\r\n"); + print_uart("sd copy return value: "); + print_uart_addr(res); + print_uart("\r\n"); + return -2; + } + + for (int i = 0; i < 4; i++) + { + partition_entries_t *part_entry = (partition_entries_t *)(lba2_buf + (i * 128)); + print_uart("gpt partition entry "); + print_uart_byte(i); + print_uart("\r\n\tpartition type guid:\t"); + for (int j = 0; j < 16; j++) + print_uart_byte(part_entry->partition_type_guid[j]); + print_uart("\r\n\tpartition guid: \t"); + for (int j = 0; j < 16; j++) + print_uart_byte(part_entry->partition_guid[j]); + print_uart("\r\n\tfirst lba:\t"); + print_uart_addr(part_entry->first_lba); + print_uart("\r\n\tlast lba:\t"); + print_uart_addr(part_entry->last_lba); + print_uart("\r\n\tattributes:\t"); + print_uart_addr(part_entry->attributes); + print_uart("\r\n\tname:\t"); + for (int j = 0; j < 72; j++) + print_uart_byte(part_entry->name[j]); + print_uart("\r\n"); + } + + partition_entries_t *boot = (partition_entries_t *)(lba2_buf); + print_uart("copying boot image "); + //res = sd_copy(dest, boot->first_lba, boot->last_lba - boot->first_lba + 1); + copyFlash(boot->first_lba, dest, boot->last_lba - boot->first_lba + 1); + + if (res != 0) + { + print_uart("SD card failed!\r\n"); + print_uart("sd copy return value: "); + print_uart_addr(res); + print_uart("\r\n"); + return -2; + } + + print_uart(" done!\r\n"); + return 0; +} diff --git a/tests/testsBP/zsbl/gpt.h b/tests/testsBP/zsbl/gpt.h new file mode 100644 index 00000000..dcc27ae8 --- /dev/null +++ b/tests/testsBP/zsbl/gpt.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +// LBA 0: Protective MBR +// ignored here + +// Partition Table Header (LBA 1) +typedef struct gpt_pth +{ + uint64_t signature; + uint32_t revision; + uint32_t header_size; //! little endian, usually 0x5c = 92 + uint32_t crc_header; + uint32_t reserved; //! must be 0 + uint64_t current_lba; + uint64_t backup_lba; + uint64_t first_usable_lba; + uint64_t last_usable_lba; + uint8_t disk_guid[16]; + uint64_t partition_entries_lba; + uint32_t nr_partition_entries; + uint32_t size_partition_entry; //! usually 0x80 = 128 + uint32_t crc_partition_entry; +} gpt_pth_t; + +// Partition Entries (LBA 2-33) +typedef struct partition_entries +{ + uint8_t partition_type_guid[16]; + uint8_t partition_guid[16]; + uint64_t first_lba; + uint64_t last_lba; //! inclusive + uint64_t attributes; + uint8_t name[72]; //! utf16 encoded +} partition_entries_t; + +// Find boot partition and load it to the destination +int gpt_find_boot_partition(long int* dest, uint32_t size); diff --git a/tests/testsBP/zsbl/main.c b/tests/testsBP/zsbl/main.c new file mode 100644 index 00000000..898025c3 --- /dev/null +++ b/tests/testsBP/zsbl/main.c @@ -0,0 +1,26 @@ +#include "uart.h" +#include "sdcDriver.h" +#include "gpt.h" + +int main() +{ + init_uart(30000000, 115200); + print_uart("Hello World!\r\n"); + + int res = gpt_find_boot_partition((long int *)0x80000000UL, 2 * 16384); + + if (res == 0) + { + return 0; + } + + while (1) + { + // do nothing + } +} + +void handle_trap(void) +{ + // print_uart("trap\r\n"); +} diff --git a/tests/testsBP/zsbl/sdcDriver.c b/tests/testsBP/zsbl/sdcDriver.c new file mode 100644 index 00000000..edbe0677 --- /dev/null +++ b/tests/testsBP/zsbl/sdcDriver.c @@ -0,0 +1,69 @@ +/////////////////////////////////////////// +// SDC.sv +// +// Written: Ross Thompson September 25, 2021 +// Modified: +// +// Purpose: driver for sdc reader. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + + +#include "sdcDriver.h" + +#define SDC_MAIL_BOX 0x12100 + +void copySDC512(long int blockAddr, long int * Dst) { + + waitInitSDC(); + + volatile long int * mailBoxAddr; + volatile int * mailBoxCmd; + volatile int * mailBoxStatus; + volatile long int * mailBoxReadData; + mailBoxStatus = (int *) (SDC_MAIL_BOX + 0x4); + mailBoxCmd = (int *) (SDC_MAIL_BOX + 0x8); + mailBoxAddr = (long int *) (SDC_MAIL_BOX + 0x10); + mailBoxReadData = (long int *) (SDC_MAIL_BOX + 0x18); + + // write the SDC address register with the blockAddr + *mailBoxAddr = blockAddr; + *mailBoxCmd = 0x4; + + // wait until the mailbox has valid data + // this occurs when status[1] = 0 + while((*mailBoxStatus & 0x2) == 0x2); + + int index; + for(index = 0; index < 512/8; index++) { + Dst[index] = *mailBoxReadData; + } +} + +volatile void waitInitSDC(){ + volatile int * mailBoxStatus; + mailBoxStatus = (int *) (SDC_MAIL_BOX + 0x4); + while((*mailBoxStatus & 0x1) != 0x1); +} + +void setSDCCLK(int divider){ + divider = (1 - (divider >> 1)); + volatile int * mailBoxCLK; + mailBoxCLK = (int *) (SDC_MAIL_BOX + 0x0); + *mailBoxCLK = divider; +} diff --git a/tests/testsBP/zsbl/sdcDriver.h b/tests/testsBP/zsbl/sdcDriver.h new file mode 100644 index 00000000..3e738183 --- /dev/null +++ b/tests/testsBP/zsbl/sdcDriver.h @@ -0,0 +1,10 @@ +#ifndef __SDCDRIVER_H +#define __SDCDRIVER_H + + +void copySDC512(long int, long int *); +volatile void waitInitSDC(); +void setSDCCLK(int); +void copyFlash(long int, long int *, int); + +#endif diff --git a/tests/testsBP/zsbl/smp.h b/tests/testsBP/zsbl/smp.h new file mode 100644 index 00000000..bb037755 --- /dev/null +++ b/tests/testsBP/zsbl/smp.h @@ -0,0 +1,52 @@ +#pragma once + +// The hart that non-SMP tests should run on +#ifndef NONSMP_HART +#define NONSMP_HART 0 +#endif + +// The maximum number of HARTs this code supports +#define CLINT_CTRL_ADDR 0x2000000 +#ifndef MAX_HARTS +#define MAX_HARTS 256 +#endif +#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS * 4) + +/* If your test needs to temporarily block multiple-threads, do this: + * smp_pause(reg1, reg2) + * ... single-threaded work ... + * smp_resume(reg1, reg2) + * ... multi-threaded work ... + */ + +#define smp_pause(reg1, reg2) \ + li reg2, 0x8; \ + csrw mie, reg2; \ + li reg1, NONSMP_HART; \ + csrr reg2, mhartid; \ + bne reg1, reg2, 42f + +#define smp_resume(reg1, reg2) \ + li reg1, CLINT_CTRL_ADDR; \ + 41:; \ + li reg2, 1; \ + sw reg2, 0(reg1); \ + addi reg1, reg1, 4; \ + li reg2, CLINT_END_HART_IPI; \ + blt reg1, reg2, 41b; \ + 42:; \ + wfi; \ + csrr reg2, mip; \ + andi reg2, reg2, 0x8; \ + beqz reg2, 42b; \ + li reg1, CLINT_CTRL_ADDR; \ + csrr reg2, mhartid; \ + slli reg2, reg2, 2; \ + add reg2, reg2, reg1; \ + sw zero, 0(reg2); \ + 41:; \ + lw reg2, 0(reg1); \ + bnez reg2, 41b; \ + addi reg1, reg1, 4; \ + li reg2, CLINT_END_HART_IPI; \ + blt reg1, reg2, 41b diff --git a/tests/testsBP/zsbl/uart.c b/tests/testsBP/zsbl/uart.c new file mode 100644 index 00000000..a8084ee5 --- /dev/null +++ b/tests/testsBP/zsbl/uart.c @@ -0,0 +1,91 @@ +#include "uart.h" + +void write_reg_u8(uintptr_t addr, uint8_t value) +{ + volatile uint8_t *loc_addr = (volatile uint8_t *)addr; + *loc_addr = value; +} + +uint8_t read_reg_u8(uintptr_t addr) +{ + return *(volatile uint8_t *)addr; +} + +int is_transmit_empty() +{ + return read_reg_u8(UART_LINE_STATUS) & 0x20; +} + +void write_serial(char a) +{ + while (is_transmit_empty() == 0) {}; + + write_reg_u8(UART_THR, a); +} + +void init_uart(uint32_t freq, uint32_t baud) +{ + uint32_t divisor = freq / (baud << 4); + + write_reg_u8(UART_INTERRUPT_ENABLE, 0x00); // Disable all interrupts + write_reg_u8(UART_LINE_CONTROL, 0x80); // Enable DLAB (set baud rate divisor) + write_reg_u8(UART_DLAB_LSB, divisor); // divisor (lo byte) + write_reg_u8(UART_DLAB_MSB, (divisor >> 8) & 0xFF); // divisor (hi byte) + write_reg_u8(UART_LINE_CONTROL, 0x03); // 8 bits, no parity, one stop bit + write_reg_u8(UART_FIFO_CONTROL, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + write_reg_u8(UART_MODEM_CONTROL, 0x20); // Autoflow mode +} + +void print_uart(const char *str) +{ + const char *cur = &str[0]; + while (*cur != '\0') + { + write_serial((uint8_t)*cur); + ++cur; + } +} + +uint8_t bin_to_hex_table[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + +void bin_to_hex(uint8_t inp, uint8_t res[2]) +{ + res[1] = bin_to_hex_table[inp & 0xf]; + res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; + return; +} + +void print_uart_int(uint32_t addr) +{ + int i; + for (i = 3; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_addr(uint64_t addr) +{ + int i; + for (i = 7; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_byte(uint8_t byte) +{ + uint8_t hex[2]; + bin_to_hex(byte, hex); + write_serial(hex[0]); + write_serial(hex[1]); +} diff --git a/tests/testsBP/zsbl/uart.h b/tests/testsBP/zsbl/uart.h new file mode 100644 index 00000000..df3aef9c --- /dev/null +++ b/tests/testsBP/zsbl/uart.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#define UART_BASE 0x10000000 + +#define UART_RBR UART_BASE + 0 +#define UART_THR UART_BASE + 0 +#define UART_INTERRUPT_ENABLE UART_BASE + 4 +#define UART_INTERRUPT_IDENT UART_BASE + 8 +#define UART_FIFO_CONTROL UART_BASE + 8 +#define UART_LINE_CONTROL UART_BASE + 12 +#define UART_MODEM_CONTROL UART_BASE + 16 +#define UART_LINE_STATUS UART_BASE + 20 +#define UART_MODEM_STATUS UART_BASE + 24 +#define UART_DLAB_LSB UART_BASE + 0 +#define UART_DLAB_MSB UART_BASE + 4 + +void init_uart(); + +void print_uart(const char* str); + +void print_uart_int(uint32_t addr); + +void print_uart_addr(uint64_t addr); + +void print_uart_byte(uint8_t byte);