Draft: lab 3 irq wtf

This commit is contained in:
2025-03-24 10:48:35 +08:00
parent 9d19b8b3b6
commit 98327b148a
19 changed files with 386 additions and 142 deletions

View File

@@ -1,4 +1,5 @@
MAKE := make MAKE := make
MAKEFLAGS += -j 8
ARCH := aarch64 ARCH := aarch64
GNU := $(ARCH)-linux-gnu GNU := $(ARCH)-linux-gnu
@@ -14,6 +15,7 @@ CCFLAGS += -Wall -Wextra -O0 \
LD := $(GNU)-ld LD := $(GNU)-ld
LDFLAGS += -g -nostdlib -no-pie LDFLAGS += -g -nostdlib -no-pie
OBJCOPY := $(GNU)-objcopy OBJCOPY := $(GNU)-objcopy
OBJDUMP := $(GNU)-objdump
MISC_DIR := misc MISC_DIR := misc
QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb
@@ -43,15 +45,17 @@ TARGET_OBJS := $(TARGET_SRCS:%=%.o)
SRCS := $(shell find $(LIB_DIR) -name '*.c') SRCS := $(shell find $(LIB_DIR) -name '*.c')
OBJS := $(SRCS:%=%.o) OBJS := $(SRCS:%=%.o)
.PHONY: all build clean clean_target run kernel debug gdb .PHONY: all build clean clean_target run \
kernel bootloader userprog debug gdb objdump
all: $(CPIO) all: $(CPIO)
$(MAKE) build TARGET_DIR=./kernel TARGET=kernel8 $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8
$(MAKE) build TARGET_DIR=./bootloader TARGET=bootloader $(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader
build: $(IMG) build: $(IMG)
$(CPIO): $(shell find $(ROOTFS_DIR)) $(CPIO): $(shell find $(ROOTFS_DIR)) userprog
cp userprog.img $(ROOTFS_DIR)/userprog
cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@ cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@
$(IMG): $(ELF) $(IMG): $(ELF)
@@ -69,9 +73,10 @@ $(ELF): $(LD_SCRIPT) $(TARGET_OBJS) $(OBJS)
$(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS) $(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS)
clean: clean:
-rm $(OBJS) $(CPIO) -rm $(OBJS) $(CPIO) $(ROOTFS_DIR)/userprog
$(MAKE) clean_target TARGET_DIR=./kernel TARGET=kernel8 $(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=kernel TARGET=kernel8
$(MAKE) clean_target TARGET_DIR=./bootloader TARGET=bootloader $(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=bootloader TARGET=bootloader
$(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=userprog TARGET=userprog
clean_target: clean_target:
-rm $(TARGET_OBJS) $(ELF) $(IMG) -rm $(TARGET_OBJS) $(ELF) $(IMG)
@@ -80,15 +85,23 @@ run: all $(CPIO)
$(QEMU) -kernel bootloader.img $(QEMUFLAGS) -serial pty $(QEMU) -kernel bootloader.img $(QEMUFLAGS) -serial pty
kernel: $(CPIO) kernel: $(CPIO)
$(MAKE) build TARGET_DIR=kernel TARGET=kernel8 $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8
$(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio $(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio
bootloader: $(CPIO) bootloader: $(CPIO)
$(MAKE) build TARGET_DIR=./bootloader TARGET=bootloader $(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader
$(QEMU) -kernel bootloader.img $(QEMUFLAGS) $(QEMU) -kernel bootloader.img $(QEMUFLAGS)
debug: all $(CPIO) userprog:
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=userprog TARGET=userprog
debug: $(CPIO)
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8
$(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio -S -s $(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio -S -s
gdb: gdb:
$(GDB) $(GDB)
objdump:
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8
$(OBJDUMP) -D kernel8.elf

View File

@@ -6,3 +6,5 @@
#define ERR_OUT_OF_BOUND 0x00000004 #define ERR_OUT_OF_BOUND 0x00000004
#define ERR_INVALID_OP 0x00000005 #define ERR_INVALID_OP 0x00000005
#define ERR_INVALID_MEM 0x00000006 #define ERR_INVALID_MEM 0x00000006
#define ERR_NOT_EXIST 0x00000007
#define ERR_ADMINKILL 0x00114514

View File

@@ -70,7 +70,7 @@ logger_cur = _Generic((msg), \
FLUSH("[ERROR]: "); \ FLUSH("[ERROR]: "); \
} }
#else #else
#define ERROR(val) #define ERROR(val) CLEAN
#endif #endif
#if LOGLEVEL >= 1 #if LOGLEVEL >= 1
@@ -79,7 +79,7 @@ logger_cur = _Generic((msg), \
FLUSH("[INFOR]: "); \ FLUSH("[INFOR]: "); \
} }
#else #else
#define INFOR(val) #define INFOR(val) CLEAN
#endif #endif
#if LOGLEVEL >= 2 #if LOGLEVEL >= 2
@@ -87,14 +87,21 @@ logger_cur = _Generic((msg), \
LOG(val); \ LOG(val); \
FLUSH("[DEBUG]: "); \ FLUSH("[DEBUG]: "); \
} }
#define DEBUG_DTB(val) DEBUG(val) #else // #if LOGLEVEL >= 2
#define DEBUG(val) CLEAN
#endif // #if LOGLEVEL >= 2
// #define DEBUG_DTB(val) DEBUG(val)
#define DEBUG_DTB(val) CLEAN
#define DEBUG_EXCEP(val) DEBUG(val)
// #define DEBUG_EXCEP(val) CLEAN
// #define DEBUG_MEM(val) DEBUG(val) // #define DEBUG_MEM(val) DEBUG(val)
#define DEBUG_MEM(val) CLEAN #define DEBUG_MEM(val) CLEAN
#else // #if LOGLEVEL >= 2
#define DEBUG(val) // #define DEBUG_INITRD(val) DEBUG(val)
#define DEBUG_DTB(val) #define DEBUG_INITRD(val) CLEAN
#define DEBUG_MEM(val)
#endif // #if LOGLEVEL >= 2
extern char logger_buf[LOGGER_BUFLEN]; extern char logger_buf[LOGGER_BUFLEN];
extern char *logger_cur; extern char *logger_cur;

View File

@@ -44,10 +44,22 @@
_null_handler: _null_handler:
save_all save_all
bl not_implemented_interrupt bl not_implemented_handler
load_all load_all
eret eret
_synchronous_handler:
save_all
bl synchronous_handler
load_all
eret
_irq_handler:
save_all
bl irq_handler
load_all
eret
.align 11 .align 11
.global exception_vector_table .global exception_vector_table
exception_vector_table: exception_vector_table:
@@ -60,18 +72,18 @@ exception_vector_table:
b _null_handler b _null_handler
.align 7 .align 7
b _synchronous_handler
.align 7
b _irq_handler
.align 7
b _null_handler b _null_handler
.align 7 .align 7
b _null_handler b _null_handler
.align 7 .align 7
b _null_handler
.align 7 b _synchronous_handler
b _null_handler .align 7
.align 7 b _irq_handler
b _null_handler
.align 7
b _null_handler
.align 7 .align 7
b _null_handler b _null_handler
.align 7 .align 7

View File

@@ -0,0 +1,5 @@
#pragma once
void init_exception(void);
void not_implemented_handler(void);
void synchronous_handler(void);

3
kernel/include/exec.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void user_exec(void *text, void *sp);

View File

@@ -0,0 +1,17 @@
#pragma once
#include <stddef.h>
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060)
enum :uint32_t {
CNTPNSIRQ_INT = ((uint32_t)1 << 1),
GPU_INT = ((uint32_t)1 << 8)
};
void init_interrupt(void);
void irq_handler(void);
void enable_interrupt(void);
void disable_interrupt(void);

View File

@@ -1,15 +1,7 @@
#pragma once #pragma once
#include <initrd.h>
#include <stddef.h> #include <stddef.h>
#include <initrd.h>
void help(void);
void hello(void);
void hwinfo(void);
void memalloc(size_t size);
void ls(file_node_t *root);
void cat(file_node_t *root, const char *filename);
void reboot(void);
int // is continue int // is continue
shell(file_node_t *); shell(file_node_t *);

View File

@@ -43,8 +43,14 @@ void exit(int);
: [a] "=r" (ret) \ : [a] "=r" (ret) \
) )
#define W_SYSREG(val, reg) \ #define W_SYSREG(reg, val) \
asm volatile( \ asm volatile( \
"msr " #reg ", %[a]" \ "msr " #reg ", %[a]" \
: [a] "r" (val) \ :: [a] "r" (val) \
)
#define R_REG(ret, reg) \
asm volatile( \
"mov %[a], " #reg \
: [a] "=r" (ret) \
) )

View File

@@ -28,8 +28,8 @@ void _memory_traverse()
{ {
dtb_reserved_entries = make_vector(0); dtb_reserved_entries = make_vector(0);
while (fdt_memory_cur->address != 0 || fdt_memory_cur->size != 0) { while (fdt_memory_cur->address != 0 || fdt_memory_cur->size != 0) {
DEBUG(ntoh64(fdt_memory_cur->address)); DEBUG_DTB(ntoh64(fdt_memory_cur->address));
DEBUG(ntoh64(fdt_memory_cur->size)); DEBUG_DTB(ntoh64(fdt_memory_cur->size));
VEC_PUSH(dtb_reserved_entries, fdt_memory_cur++); VEC_PUSH(dtb_reserved_entries, fdt_memory_cur++);
} }
@@ -101,8 +101,8 @@ void fdt_traverse(const vector_t *struct_cbs)
dtb_end = dtb_start + dtb_end = dtb_start +
ntoh32(((fdt_header_t *)dtb_start)->totalsize); ntoh32(((fdt_header_t *)dtb_start)->totalsize);
DEBUG(fdt_memory_cur); DEBUG_DTB(fdt_memory_cur);
DEBUG(fdt_struct_cur); DEBUG_DTB(fdt_struct_cur);
_memory_traverse(); _memory_traverse();
DEBUG_DTB("memory traverse done"); DEBUG_DTB("memory traverse done");
_struct_traverse("", struct_cbs); _struct_traverse("", struct_cbs);

42
kernel/lib/exception.c Normal file
View File

@@ -0,0 +1,42 @@
#include <exception.h>
#include <errcode.h>
#include <stddef.h>
#include <logger.h>
#include <utils.h>
void init_exception()
{
asm volatile(
"adr x0, exception_vector_table" ENDL
"msr vbar_el1, x0" ENDL
::: "x0"
);
}
void not_implemented_handler()
{
DEBUG_EXCEP("not implemented caught");
}
void synchronous_handler()
{
static int count = 0;
if (count++ > 5)
exit(ERR_ADMINKILL);
DEBUG_EXCEP("synchronous caught");
uint64_t x0 = 0x0;
R_REG(x0, x0);
LOG(x0);
uint64_t spsr_el1 = 0x0;
R_SYSREG(spsr_el1, spsr_el1);
LOG(spsr_el1);
uint64_t elr_el1 = 0x0;
R_SYSREG(elr_el1, elr_el1);
LOG(elr_el1);
uint64_t esr_el1 = 0x0;
R_SYSREG(esr_el1, esr_el1);
DEBUG_EXCEP(esr_el1);
}

16
kernel/lib/exec.c Normal file
View File

@@ -0,0 +1,16 @@
#include <exec.h>
#include <utils.h>
void user_exec(void *text, void *sp)
{
// enable core timer
uint64_t cntkctl_el1 = 0x0;
R_SYSREG(cntkctl_el1, cntkctl_el1);
W_SYSREG(cntkctl_el1, cntkctl_el1 | 1);
W_SYSREG(cntp_ctl_el0, 1);
W_SYSREG(spsr_el1, 0);
W_SYSREG(elr_el1, text);
W_SYSREG(sp_el0, sp);
asm volatile("eret");
}

58
kernel/lib/interrupt.c Normal file
View File

@@ -0,0 +1,58 @@
#include <interrupt.h>
#include <utils.h>
#include <logger.h>
#include <errcode.h>
void init_interrupt(void)
{
uint64_t cntfrq_el0;
R_SYSREG(cntfrq_el0, cntfrq_el0);
W_SYSREG(cntp_tval_el0, cntfrq_el0);
*CORE0_TIMER_IRQ_CTRL = 0x2;
}
static inline
void _uart_irq_handler(void)
{
DEBUG_EXCEP("uart irq");
}
static inline
void _timer_irq_handler(void)
{
LOG("timer irq");
uint64_t cntpct_el0;
R_SYSREG(cntpct_el0, cntpct_el0);
DEBUG_EXCEP(cntpct_el0);
uint64_t cntfrq_el0;
R_SYSREG(cntfrq_el0, cntfrq_el0);
W_SYSREG(cntp_tval_el0, cntfrq_el0);
}
void irq_handler(void)
{
LOG("irq caught");
uint64_t irq_source = *CORE0_IRQ_SOURCE;
DEBUG_EXCEP(irq_source);
*CORE0_TIMER_IRQ_CTRL = 0x0;
if (irq_source & GPU_INT)
_uart_irq_handler();
if (irq_source & CNTPNSIRQ_INT)
_timer_irq_handler();
*CORE0_TIMER_IRQ_CTRL = 0x2;
}
void enable_interrupt(void)
{
asm volatile("msr DAIFClr, 0xf");
}
void disable_interrupt(void)
{
asm volatile("msr DAIFSet, 0xf");
}

View File

@@ -1,10 +1,13 @@
#include <stddef.h> #include <stddef.h>
#include <errcode.h>
#include <kmalloc.h> #include <kmalloc.h>
#include <utils.h> #include <utils.h>
#include <string.h> #include <string.h>
#include <uart.h> #include <uart.h>
#include <mbox.h> #include <mbox.h>
#include <shell.h> #include <shell.h>
#include <exec.h>
#include <mman.h>
#define INPUT_BUFLEN 1000 #define INPUT_BUFLEN 1000
@@ -13,25 +16,29 @@
#define PM_RSTC 0x3F10001c #define PM_RSTC 0x3F10001c
#define PM_WDOG 0x3F100024 #define PM_WDOG 0x3F100024
void help (void) static inline
void _help (void)
{ {
uart_puts( uart_puts(
"help : print this help menu" ENDL "help : print this help menu" ENDL
"hello : print Hello World!" ENDL "hello : print Hello World!" ENDL
"hwinfo : print hardware info" ENDL "hwinfo : print hardware info" ENDL
"memalloc : alloate memory and print" ENDL "memalloc <size>: alloate memory and print" ENDL
"ls : list directory contents" ENDL "ls : list directory contents" ENDL
"cat : concatenate files and print" ENDL "cat <file>: concatenate files and print" ENDL
"reboot : reboot the device" ENDL "exec <file>: execute file in usermode" ENDL
"reboot : reboot the device" ENDL
); );
} }
void hello (void) static inline
void _hello (void)
{ {
uart_puts("hello, world" ENDL); uart_puts("hello, world" ENDL);
} }
void hwinfo (void) static inline
void _hwinfo (void)
{ {
uart_puts( uart_puts(
"hwinfo: " ENDL "hwinfo: " ENDL
@@ -51,7 +58,8 @@ void hwinfo (void)
uart_puts(ENDL); uart_puts(ENDL);
} }
void memalloc(size_t size) static inline
void _memalloc(size_t size)
{ {
void *addr = kmalloc(size); void *addr = kmalloc(size);
uart_puts("size: "); uart_puts("size: ");
@@ -63,40 +71,60 @@ void memalloc(size_t size)
uart_puts(ENDL); uart_puts(ENDL);
} }
void ls_initrd_callback(file_node_t *tr) static inline
void _ls_initrd_callback(file_node_t *tr)
{ {
uart_puts(tr->filename); uart_puts(tr->filename);
uart_puts(ENDL); uart_puts(ENDL);
} }
void ls(file_node_t *root) static inline
void _ls(file_node_t *root)
{ {
initrd_traverse(root, ls_initrd_callback); initrd_traverse(root, _ls_initrd_callback);
} }
void cat(file_node_t *root, const char *filename) static inline
void _cat(file_node_t *root, const char *filename)
{ {
file_node_t *tr = initrd_get(root, filename); file_node_t *tr = initrd_get(root, filename);
if (tr) { if (tr) {
uart_puts((char *)tr->filecontent); uart_puts((char *)tr->filecontent);
} else { } else {
uart_puts("FILE NOT EXIST!" ENDL); exit(ERR_NOT_EXIST);
} }
} }
void set(long addr, unsigned int value) { static inline
volatile unsigned int* point = (unsigned int*)addr; void _exec(file_node_t *root, const char *filename)
*point = value;
}
void reset(int tick) { // reboot after watchdog timer expire
set(PM_RSTC, PM_PASSWORD | 0x20); // full reset
set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick
}
void reboot(void)
{ {
reset(1 << 16); file_node_t *tr = initrd_get(root, filename);
if (tr) {
void *userspace = allocate_page(1 << 6);
memcpy(userspace, tr->filecontent, tr->filesize);
user_exec(userspace, userspace + (1 << (12 + 6)) - 8);
kfree(userspace);
} else {
exit(ERR_NOT_EXIST);
}
}
static inline
void _set(long addr, unsigned int value) {
volatile unsigned int* point = (unsigned int*)addr;
*point = value;
}
static inline
void _reset(int tick) { // reboot after watchdog timer expire
_set(PM_RSTC, PM_PASSWORD | 0x20); // full reset
_set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick
}
static inline
void _reboot(void)
{
_reset(1 << 16);
} }
int shell(file_node_t *initrd_root) int shell(file_node_t *initrd_root)
@@ -127,19 +155,21 @@ int shell(file_node_t *initrd_root)
*j = '\0'; *j = '\0';
if (!strcmp(bin, "help")) { if (!strcmp(bin, "help")) {
help(); _help();
} else if (!strcmp(bin, "hello")) { } else if (!strcmp(bin, "hello")) {
hello(); _hello();
} else if (!strcmp(bin, "hwinfo")) { } else if (!strcmp(bin, "hwinfo")) {
hwinfo(); _hwinfo();
} else if (!strcmp(bin, "memalloc")){ } else if (!strcmp(bin, "memalloc")){
memalloc((size_t)atoi32(param)); _memalloc((size_t)atoi32(param));
} else if (!strcmp(bin, "ls")) { } else if (!strcmp(bin, "ls")) {
ls(initrd_root); _ls(initrd_root);
} else if (!strcmp(bin, "cat")) { } else if (!strcmp(bin, "cat")) {
cat(initrd_root, param); _cat(initrd_root, param);
} else if (!strcmp(bin, "exec")) {
_exec(initrd_root, param);
} else if (!strcmp(bin, "reboot")) { } else if (!strcmp(bin, "reboot")) {
reboot(); _reboot();
} }
return true; return true;

View File

@@ -7,23 +7,28 @@
#include <shell.h> #include <shell.h>
#include <vector.h> #include <vector.h>
#include <utils.h> #include <utils.h>
#include <exception.h>
#include <interrupt.h>
void init(void *dtb, file_node_t **initrd_root) void init(void *dtb, file_node_t **initrd_root)
{ {
init_exception();
init_interrupt();
// UART // UART
uart_init(); uart_init();
// Device tree // Device tree
INFOR(dtb); DEBUG_DTB(dtb);
dtb_start = dtb; dtb_start = dtb;
vector_t *dtb_struct_cbs = make_vector(0); vector_t *dtb_struct_cbs = make_vector(0);
VEC_PUSH(dtb_struct_cbs, &initrd_dtb_cb); VEC_PUSH(dtb_struct_cbs, &initrd_dtb_cb);
VEC_PUSH(dtb_struct_cbs, &mman_dtb_memory_cb); VEC_PUSH(dtb_struct_cbs, &mman_dtb_memory_cb);
fdt_traverse(dtb_struct_cbs); fdt_traverse(dtb_struct_cbs);
DEBUG("device tree parse done"); DEBUG_DTB("device tree parse done");
// Initramfs // Initramfs
INFOR(initrd_start); DEBUG_INITRD(initrd_start);
*initrd_root = initrd_init(); *initrd_root = initrd_init();
// Memory (Buddy system) // Memory (Buddy system)

View File

@@ -3,18 +3,20 @@
#include <stddef.h> #include <stddef.h>
/* Auxilary mini UART registers */ /* Auxilary mini UART registers */
#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) #define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE + 0x00215004))
#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) #define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE + 0x00215040))
#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) #define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE + 0x00215044))
#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) #define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE + 0x00215048))
#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) #define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE + 0x0021504C))
#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) #define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE + 0x00215050))
#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) #define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE + 0x00215054))
#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) #define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE + 0x00215058))
#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) #define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE + 0x0021505C))
#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) #define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE + 0x00215060))
#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) #define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE + 0x00215064))
#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) #define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE + 0x00215068))
#define ARMINT_En_IRQs1 ((volatile unsigned int*)(MMIO_BASE + 0x0000b210))
int is_uart_init = 0; int is_uart_init = 0;
@@ -23,49 +25,52 @@ int is_uart_init = 0;
*/ */
void uart_init() void uart_init()
{ {
register unsigned int r; register unsigned int r;
/* initialize UART */
*AUX_ENABLE |=1; // enable UART1, AUX mini uart
*AUX_MU_IER = 0;
*AUX_MU_CNTL = 0;
*AUX_MU_LCR = 3; // 8 bits
*AUX_MU_MCR = 0;
*AUX_MU_IER = 0;
*AUX_MU_IIR = 0xc6; // disable interrupts
*AUX_MU_BAUD = 270; // 115200 baud
/* map UART1 to GPIO pins */
r=*GPFSEL1;
r&=~((7<<12)|(7<<15)); // gpio14, gpio15
r|=(2<<12)|(2<<15); // alt5
*GPFSEL1 = r;
*GPPUD = 0; // enable pins 14 and 15
r=150; while(r--) { asm volatile("nop"); }
*GPPUDCLK0 = (1<<14)|(1<<15);
r=150; while(r--) { asm volatile("nop"); }
*GPPUDCLK0 = 0; // flush GPIO setup
*AUX_MU_CNTL = 3; // enable Tx, Rx
is_uart_init = 1; /* initialize UART */
*AUX_ENABLE |= 1; // enable UART1, AUX mini uart
*AUX_MU_IER = 1;
*AUX_MU_CNTL = 0;
*AUX_MU_LCR = 3; // 8 bits
*AUX_MU_MCR = 0;
*AUX_MU_IER = 0;
*AUX_MU_IIR = 0xc6; // disable interrupts
*AUX_MU_BAUD = 270; // 115200 baud
/* map UART1 to GPIO pins */
r = *GPFSEL1;
r &= ~((7 << 12) | (7 << 15)); // gpio14, gpio15
r |= (2 << 12) | (2 << 15); // alt5
*GPFSEL1 = r;
*GPPUD = 0; // enable pins 14 and 15
r = 150; while (r--) { asm volatile("nop"); }
*GPPUDCLK0 = (1 << 14) | (1 << 15);
r = 150; while (r--) { asm volatile("nop"); }
*GPPUDCLK0 = 0; // flush GPIO setup
*AUX_MU_CNTL = 3; // enable Tx, Rx
*ARMINT_En_IRQs1 |= (1 << 29);
is_uart_init = 1;
} }
/** /**
* Send a character * Send a character
*/ */
void uart_send(unsigned int c) { void uart_send(unsigned int c)
/* wait until we can send */ {
do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20)); /* wait until we can send */
/* write the character to the buffer */ do { asm volatile("nop"); } while (!(*AUX_MU_LSR & 0x20));
*AUX_MU_IO=c; /* write the character to the buffer */
*AUX_MU_IO = c;
} }
uint8_t uart_getb() uint8_t uart_getb()
{ {
uint8_t r; uint8_t r;
/* wait until something is in the buffer */ /* wait until something is in the buffer */
do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); do { asm volatile("nop"); } while (!(*AUX_MU_LSR & 0x01));
/* read it and return */ /* read it and return */
r=(uint8_t)(*AUX_MU_IO); r = (uint8_t)(*AUX_MU_IO);
return r; return r;
} }
@@ -73,38 +78,40 @@ uint8_t uart_getb()
/** /**
* Receive a character * Receive a character
*/ */
char uart_getc() { char uart_getc()
{
char r = (char)uart_getb(); char r = (char)uart_getb();
/* convert carrige return to newline */ /* convert carrige return to newline */
return r=='\r'?'\n':r; return r == '\r' ? '\n' : r;
} }
/** /**
* Display a string * Display a string
*/ */
void uart_puts(const char *s) { void uart_puts(const char *s)
while(*s) { {
/* convert newline to carrige return + newline */ while (*s) {
if(*s=='\n') /* convert newline to carrige return + newline */
uart_send('\r'); if(*s == '\n')
uart_send(*s++); uart_send('\r');
} uart_send(*s++);
}
} }
/** /**
* Display a binary value in hexadecimal * Display a binary value in hexadecimal
*/ */
void uart_hex(uint64_t d) { void uart_hex(uint64_t d)
unsigned int n; {
int c; unsigned int n;
for(c=28;c>=0;c-=4) { for (int c = 28; c >= 0; c -= 4) {
// get highest tetrad // get highest tetrad
n=(d>>c)&0xF; n = (d >> c) & 0xF;
// 0-9 => '0'-'9', 10-15 => 'A'-'F' // 0-9 => '0'-'9', 10-15 => 'A'-'F'
n+=n>9?0x37:0x30; n += n > 9 ? 0x37 : 0x30;
uart_send(n); uart_send(n);
} }
} }
void uart_int(int d) void uart_int(int d)

BIN
rootfs/userprog Executable file

Binary file not shown.

11
userprog/Start.S Normal file
View File

@@ -0,0 +1,11 @@
.section ".text"
.global _start
_start:
mov x0, 0
loop:
add x0, x0, 1
svc 0
cmp x0, 5
blt loop
wait:
b wait

18
userprog/linker.ld Normal file
View File

@@ -0,0 +1,18 @@
ENTRY(_start)
SECTIONS
{
.text : {
*(.text.start)
*(.text)
}
.rodata : {
*(.rodata)
}
.data : {
*(.data)
}
.bss : {
*(.bss)
}
}