From 20fa8584e31d55b7f2953f917adcc190adab236f Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Tue, 31 Aug 2021 08:31:10 -0700 Subject: Initial Commit --- .gitignore | 3 ++ Makefile | 50 ++++++++++++++++++++++ README.md | 4 ++ gdbinit | 7 ++++ linker.ld | 34 +++++++++++++++ src/boot.S | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/irq.S | 0 src/kernel.S | 24 +++++++++++ src/uart.S | 46 ++++++++++++++++++++ 9 files changed, 303 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 gdbinit create mode 100644 linker.ld create mode 100644 src/boot.S create mode 100644 src/irq.S create mode 100644 src/kernel.S create mode 100644 src/uart.S diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..215dd1b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/ +obj/ +mk.old diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..174ca3f --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +C_SOURCES = $(wildcard src/*.c) +C_HEADERS = $(wildcard src/*.h) +C_OBJECTS = ${C_SOURCES:.c=.o} +C_OBJECTD = ${subst src,obj,${C_OBJECTS}} +A_SOURCES = $(wildcard src/*.S) +A_OBJECTS = ${A_SOURCES:.S=.o} +A_OBJECTD = ${subst src,obj,${A_OBJECTS}} + +CROSS = arm-none-eabi +CC = ${CROSS}-gcc +AS = ${CROSS}-as +OBJCOPY = ${CROSS}-objcopy +QEMU = qemu-system-arm +GDB = gdb-multiarch +CFLAGS = -mcpu=cortex-a7 -fpic -ffreestanding -std=gnu99 -O2 -Wall -Wextra -nostdlib -g +AFLAGS = -mcpu=cortex-a7 + +.PHONY: clean run run-debug debug export + +default: clean build/kernel7.img + +build/kernel7.img: build/kernel.elf + ${OBJCOPY} $< -O binary $@ + +build/kernel.list: build/kernel.elf + ${OBJDUMP} -D $< > $@ + +build/kernel-g.elf: ${A_OBJECTD} ${C_OBJECTD} + ${CC} -T linker.ld -o $@ ${CFLAGS} $^ -lgcc + +build/kernel.elf: ${A_OBJECTD} ${C_OBJECTD} + ${CC} -T linker.ld -o $@ -ffreestanding -O2 -nostdlib $^ -lgcc + +export: build/kernel.list + cp build/kernel.elf /mnt/c/Local/ + +obj/%.o: src/%.S + ${AS} ${AFLAGS} -g -c $< -o $@ + +clean: + rm -f obj/*.o build/*.elf build/*.list build/*.img + +run: build/kernel.elf + ${QEMU} -M raspi2 -kernel $< -m 1G -serial mon:stdio + +run-debug: build/kernel-g.elf + ${QEMU} -M raspi2 -cpu arm1176 -kernel $< -m 1G -s -S -serial mon:stdio -nographic + +debug: build/kernel-g.elf build/kernel.list + ${GDB} $< -command=gdbinit diff --git a/README.md b/README.md new file mode 100644 index 0000000..c48b8c5 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ + +This simple example uart rx interrupt on QEMU raspi2 model. +This program only supports QEMU raspi2 model, and does not work on real hardware. + diff --git a/gdbinit b/gdbinit new file mode 100644 index 0000000..6ce85b0 --- /dev/null +++ b/gdbinit @@ -0,0 +1,7 @@ +set arch arm +layout regs +target remote localhost:1234 +b _start +winheight regs +3 +set scheduler-locking on +thread 1 diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..5c1b1a5 --- /dev/null +++ b/linker.ld @@ -0,0 +1,34 @@ +ENTRY(_start) + +SECTIONS +{ + /* Starts at LOADER_ADDR. */ + . = 0x8000; + __start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + . = ALIGN(4096); /* align to page size */ + __text_end = .; + + __data_start = .; + .data : + { + *(.data) + } + . = ALIGN(4096); /* align to page size */ + __data_end = .; + + __bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(4096); /* align to page size */ + __bss_end = .; + __end = .; +} diff --git a/src/boot.S b/src/boot.S new file mode 100644 index 0000000..f0caebc --- /dev/null +++ b/src/boot.S @@ -0,0 +1,135 @@ +// To keep this in the first portion of the binary. +.section ".text.boot" + +// Make _start global. +.globl _start + +_start: +reset: + // disable core0,1,2. + mrc p15, #0, r1, c0, c0, #5 + and r1, r1, #3 + cmp r1, #0 + bne io_halt + + // set vector address. + ldr r0, =vector + mcR P15, 0, r0, c12, c0, 0 + + // save cpsr. + mrs r0, cpsr + + // setup sp in IRQ mode. + bic r1, r0, #0x1f + orr r1, r1, #0x12 + msr cpsr_c,r1 + mov sp,#0x4000 + + // restore cpsr. + msr cpsr_c, r0 + + // setup the stack in SVC mode. + mov sp, #0x8000 + + // Clear out bss. + ldr r4, =__bss_start + ldr r9, =__bss_end + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0 + b 2f + +1: + // store multiple at r4. + stmia r4!, {r5-r8} + + // If we are still below bss_end, loop. +2: + cmp r4, r9 + blo 1b + + // Call kernel_main + ldr r3, =kernel_main + blx r3 + +irq: + push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} + bl a_irq_handler + pop {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} + subs pc, lr, #4 + +.globl io_halt +io_halt: + wfi + b io_halt + +.globl enable_irq +enable_irq: + cpsie i + bx lr + +.globl disable_irq +disable_irq: + cpsid i + bx lr + +.align 5 +vector: + ldr pc, reset_handler + ldr pc, undefined_handler + ldr pc, swi_handler + ldr pc, prefetch_handler + ldr pc, data_handler + ldr pc, unused_handler + ldr pc, irq_handler + ldr pc, fiq_handler + +reset_handler: .word reset +undefined_handler: .word io_halt +swi_handler: .word io_halt +prefetch_handler: .word io_halt +data_handler: .word io_halt +unused_handler: .word io_halt +irq_handler: .word irq +fiq_handler: .word io_halt + +.global a_irq_handler +a_irq_handler: + push {lr} + bl disable_irq + // r2 = CORE0_INTERRUPT_SOURCE + // if r2 & 0b100000000 + mov r2, #0x40000000 + ldr r3, [r2, #0x60] + tst r3, #256 + beq a_irq_handler.exit + // r2 = IRQ_PEND2 + // r2 & 1 << 25 + mov r2, #0xB208 + movt r2, #0x3F00 + ldr r3, [r2] + tst r3, #0x2000000 + beq a_irq_handler.exit + mov r2, #0x1040 + movt r2, #0x3F20 + ldr r3, [r2] + tst r3, #16 + beq a_irq_handler.exit + mov r2, #0x1000 + movt r2, #0x3F20 + ldrb r0, [r2] + push {r0} + bl enable_irq + pop {r0} + bl uart_char + ldr r0, =amsg + bl uart_string + pop {pc} +a_irq_handler.exit: + bl enable_irq + pop {pc} + +.section ".data" +amsg: + .asciz " a_irq_handler\n" diff --git a/src/irq.S b/src/irq.S new file mode 100644 index 0000000..e69de29 diff --git a/src/kernel.S b/src/kernel.S new file mode 100644 index 0000000..02894a6 --- /dev/null +++ b/src/kernel.S @@ -0,0 +1,24 @@ +.section ".text.kernel" + +.globl kernel_main +kernel_main: + push {lr} + bl uart_init + bl enable_irq + ldr r0, =os_info + bl uart_string + mov r0, #0x00 +kernel_main.a: + cmp r0, #0x100 + beq kernel_main.loop + bl uart_char + add r0, #1 + b kernel_main.a +kernel_main.loop: + bl io_halt + b kernel_main.loop + pop {lr} + +.section ".data" +os_info: + .asciz "Sergey Bilovytskyy's Real Time Operating System\n Version 0.0a\n Interrupt 01: uart rx interrupt\n Exit : Ctrl-A x\n Monitor : Ctrl-A c\n\n" diff --git a/src/uart.S b/src/uart.S new file mode 100644 index 0000000..bd98bac --- /dev/null +++ b/src/uart.S @@ -0,0 +1,46 @@ +.section ".text" + +.globl uart_init +uart_init: + //*UART0_IMSC = 1 << 4; + mov r2, #0x1038 + movt r2, #0x3F20 + mov r3, #0b10000 + str r3, [r2] + //*IRQ_ENABLE2 = 1 << 25; + mov r2, #0xB214 + movt r2, #0x3F00 + mov r3, #0 + movt r3, #0b1000000000 + str r3, [r2] + //*GPU_INTERRUPTS_ROUTING = 0x00; + mov r2, #0x000C + movt r2, #0x4000 + eor r3, r3 + str r3, [r2] + bx lr + +.globl uart_char +uart_char: + mov r2, #0x1000 + movt r2, #0x3f20 +uart_char.loop: + ldr r3, [r2, #24] + tst r3, #0b100000 + bne uart_char.loop + str r0, [r2] + bx lr + +.globl uart_string +uart_string: + push {r4, lr} + mov r4, r0 + ldrb r0, [r0] + cmp r0, #0 + popeq {r4, pc} +uart_string.loop: + bl uart_char + ldrb r0, [r4, #1]! + cmp r0, #0 + bne uart_string.loop + pop {r4, pc} -- cgit v1.2.1