added TextIO module for outputting text

master
Anton Lydike 3 years ago
parent ab19abe12b
commit 26e70d2f60

@ -11,12 +11,15 @@ GCC_PREF=riscv32-unknown-elf-
CC=$(GCC_PREF)gcc CC=$(GCC_PREF)gcc
OBJDUMP=$(GCC_PREF)objdump OBJDUMP=$(GCC_PREF)objdump
CFLAGS=-I$(KLIBDIR) -O3 -MD -mcmodel=medany -Wall -Wextra -pedantic-errors CFLAGS=-I$(KLIBDIR) -MD -mcmodel=medany -Wall -Wextra -pedantic-errors
KERNEL_CFLAGS=-nostdlib -T linker.ld KERNEL_CFLAGS=-nostdlib -T linker.ld
ARCH = rv32im # here you ARCH = rv32im # here you
### Build configuration: ### Build configuration:
# comment out if you don't have any text IO device memory mapped
CFLAGS += -DTEXT_IO_ADDR=0xff0000 -DTEXT_IO_BUFLEN=64
# uncomment these to build with only the rv32i standard # uncomment these to build with only the rv32i standard
#CFLAGS += -D__risc_no_ext=1 #CFLAGS += -D__risc_no_ext=1
#ARCH = rv32i #ARCH = rv32i
@ -30,10 +33,10 @@ ARCH = rv32im # here you
CFLAGS += -march=$(ARCH) CFLAGS += -march=$(ARCH)
# dependencies that need to be built: # dependencies that need to be built:
_DEPS = ecall.c csr.c sched.c _DEPS = ecall.c csr.c sched.c io.o
# dependencies as object files: # dependencies as object files:
_OBJ = ecall.o sched.o boot.o csr.o _OBJ = ecall.o sched.o boot.o csr.o io.o
DEPS = $(patsubst %,$(KLIBDIR)/%,$(_DEPS)) DEPS = $(patsubst %,$(KLIBDIR)/%,$(_DEPS))

@ -1,6 +1,7 @@
#include "kernel.h" #include "kernel.h"
#include "ecall.h" #include "ecall.h"
#include "sched.h" #include "sched.h"
#include "io.h"
void create_processes_from_bin_table(); void create_processes_from_bin_table();
@ -8,10 +9,14 @@ extern ProcessControlBlock processes[PROCESS_COUNT];
loaded_binary binary_table[NUM_BINARIES] __attribute__ ((section (".data"))); loaded_binary binary_table[NUM_BINARIES] __attribute__ ((section (".data")));
extern void memset(unsigned int, void*, void*);
extern void init() extern void init()
{ {
init_ecall_table(); init_ecall_table();
dbgln("Kernel started!", 15);
create_processes_from_bin_table(); create_processes_from_bin_table();
scheduler_run_next(); scheduler_run_next();

@ -20,7 +20,7 @@
typedef struct loaded_binary { typedef struct loaded_binary {
int binid; int binid;
int entrypoint; int entrypoint;
int bounds[2]; void* bounds[2];
} loaded_binary; } loaded_binary;
// create a global table holding all loaded binaries. // create a global table holding all loaded binaries.

@ -106,18 +106,21 @@ trap_vector:
jal trap_handle jal trap_handle
// make memset global
.global memset
.type memset, @function
#ifdef __risc_no_ext #ifdef __risc_no_ext
// "dumb" memset, if RV32M is not present on the target // "dumb" memset, if RV32M is not present on the target
// since memset is currently only used at startup, the performance implications // since memset is currently only used at startup, the performance implications
// should be minimal. // should be minimal.
memset: memset:
bge a1, a2, 2f bge a1, a2, 2f
1: 1:
sw a0, 0(a1) sw a0, 0(a1)
addi a1, a1, 4 addi a1, a1, 4
blt a1, a2, 1b blt a1, a2, 1b
2: 2:
ret ret
#else #else

@ -1,6 +1,7 @@
#include "ecall.h" #include "ecall.h"
#include "sched.h" #include "sched.h"
#include "csr.h" #include "csr.h"
#include "io.h"
typedef int (*ecall_handler)(int*,ProcessControlBlock*); typedef int (*ecall_handler)(int*,ProcessControlBlock*);
@ -44,6 +45,13 @@ int ecall_handle_exit(int* args, ProcessControlBlock* pcb)
pcb->status = PROC_DEAD; pcb->status = PROC_DEAD;
pcb->exit_code = *args; pcb->exit_code = *args;
char msg[34] = "process exited with code ";
itoa(pcb->pid, &msg[8], 10);
itoa(*args % 10, &msg[28], 10);
dbgln(msg, 34);
return 0; return 0;
} }
@ -54,7 +62,7 @@ void trap_handle_ecall() {
}; };
ProcessControlBlock* pcb = get_current_process(); ProcessControlBlock* pcb = get_current_process();
int *regs = pcb->regs; int *regs = pcb->regs;
int code = regs[16]; int code = regs[16]; // code is inside a7
// check if the code is too large/small or if the handler is zero // check if the code is too large/small or if the handler is zero
if (code < 0 || code > ECALL_TABLE_LEN || ecall_table[code] == 0) { if (code < 0 || code > ECALL_TABLE_LEN || ecall_table[code] == 0) {
@ -129,5 +137,6 @@ void init_ecall_table()
void handle_exception(int ecode, int mtval) void handle_exception(int ecode, int mtval)
{ {
dbgln("Trap encountered!", 17);
__asm__("ebreak");
} }

@ -17,7 +17,7 @@ enum ecall_codes {
#define ECALL_TABLE_LEN 16 #define ECALL_TABLE_LEN 16
enum ecall_errors { enum error_code {
ENOCODE = -1, // invalid syscall code ENOCODE = -1, // invalid syscall code
EINVAL = -2, // invalid argument value EINVAL = -2, // invalid argument value
ENOMEM = -3, // not enough memory ENOMEM = -3, // not enough memory

@ -0,0 +1,63 @@
#include "io.h"
#ifdef TEXT_IO_ADDR
#ifndef TEXT_IO_BUFLEN
#error "When defining TEXT_IO_ADDR, please also provide TEXT_IO_BUFLEN, otherwise textIO won't work!"
#endif
void dbgln(char* text, int len)
{
while (len > TEXT_IO_BUFLEN) {
dbgln(text, TEXT_IO_BUFLEN);
text += TEXT_IO_BUFLEN;
len -= TEXT_IO_BUFLEN;
}
char* ioaddr = (char*) TEXT_IO_ADDR + 4;
for (int i = 0; i < len; i++) {
if (*text == 0)
break;
*ioaddr++ = *text++;
}
if (len < TEXT_IO_BUFLEN)
*ioaddr = '\n';
// write a 1 to the start of the textIO to signal a buffer flush
*((char*) TEXT_IO_ADDR) = 1;
}
#else
/* if no textIO module loaded, dbgln is a noop :( */
void dbgln(char*, int){}
#endif
/* alphabet for itoa */
char alpha[16] = "0123456789abcdef";
char* itoa (int value, char* str, int base)
{
if (base > 16 || base < 2) {
*str++ = '?';
return str;
}
if (value < 0) {
*str++ = '-';
value *= -1;
}
int num;
do {
num = value % base;
value = value / base;
*str++ = alpha[num];
}
while (value > 0);
return str;
}

@ -0,0 +1,10 @@
#ifndef H_IO
#define H_IO
/* print a line to the debug textIO module */
void dbgln(char* text, int len);
/* alphabet for itoa */
char* itoa (int value, char* str, int base);
#endif
Loading…
Cancel
Save