aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cunningham <cc@localhost>2021-08-31 08:31:10 -0700
committerChristian Cunningham <cc@localhost>2021-08-31 08:33:05 -0700
commit20fa8584e31d55b7f2953f917adcc190adab236f (patch)
treee46eb99ea64e993ed5f5c2648853941d9db9c4a4
Initial Commit
-rw-r--r--.gitignore3
-rw-r--r--Makefile50
-rw-r--r--README.md4
-rw-r--r--gdbinit7
-rw-r--r--linker.ld34
-rw-r--r--src/boot.S135
-rw-r--r--src/irq.S0
-rw-r--r--src/kernel.S24
-rw-r--r--src/uart.S46
9 files changed, 303 insertions, 0 deletions
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
--- /dev/null
+++ b/src/irq.S
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}