Add vector table
This commit is contained in:
		
							parent
							
								
									08ffb6ee94
								
							
						
					
					
						commit
						417106b967
					
				
							
								
								
									
										86
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										86
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -1,90 +1,26 @@
 | 
			
		|||
# environment
 | 
			
		||||
include Makevars.mk
 | 
			
		||||
 | 
			
		||||
AARCH64_TOOLCHAIN ?= aarch64-linux-gnu
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Shortcuts
 | 
			
		||||
 | 
			
		||||
CC=clang --target=aarch64-none-elf -mcpu=cortex-a57
 | 
			
		||||
LD=ld.lld
 | 
			
		||||
OBJCOPY=$(AARCH64_TOOLCHAIN)-objcopy --target elf64-littleaarch64
 | 
			
		||||
 | 
			
		||||
CFLAGS += -O0
 | 
			
		||||
CFLAGS += -g
 | 
			
		||||
#CFLAGS += -nostdlib
 | 
			
		||||
#CFLAGS += -march=armv8-a
 | 
			
		||||
#CFLAGS += -std=c99
 | 
			
		||||
#CFLAGS += -pedantic
 | 
			
		||||
#CFLAGS += -Wall
 | 
			
		||||
#CFLAGS += -Wmissing-prototypes
 | 
			
		||||
#CFLAGS += -Wstrict-prototypes
 | 
			
		||||
#CFLAGS += -Wold-style-definition
 | 
			
		||||
 | 
			
		||||
BUILD_DIR=build
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Files
 | 
			
		||||
 | 
			
		||||
KERNEL_MEMMAP = aarch64/memmap
 | 
			
		||||
 | 
			
		||||
KERNEL_SOURCES = \
 | 
			
		||||
  aarch64/boot.s \
 | 
			
		||||
  sys/main.c \
 | 
			
		||||
  sys/uart.c \
 | 
			
		||||
 | 
			
		||||
KERNEL_LIST := $(wildcard $(KERNEL_SOURCES))
 | 
			
		||||
KERNEL_OBJS := $(addsuffix .o, $(addprefix $(BUILD_DIR)/, ${KERNEL_LIST}))
 | 
			
		||||
# Rules
 | 
			
		||||
 | 
			
		||||
all: kernel
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)kernel:
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
# compilation 
 | 
			
		||||
 | 
			
		||||
kernel: $(BUILD_DIR)/kernel.elf # $(BUILD_DIR)/kernel.sym
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)/kernel.elf: $(KERNEL_OBJS)
 | 
			
		||||
	$(info linking target: $@)
 | 
			
		||||
	$(LD) -T$(KERNEL_MEMMAP) -nostdlib $^ -o $@
 | 
			
		||||
	$(info done: $@)
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf
 | 
			
		||||
	$(OBJCOPY) -O binary $< $@
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)/kernel.sym: $(BUILD_DIR)/kernel.elf
 | 
			
		||||
	$(OBJCOPY) --only-keep-debug $< $@
 | 
			
		||||
	$(OBJCOPY) --strip-debug $@
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)/%.o: %
 | 
			
		||||
	$(info compiling file: $<)
 | 
			
		||||
	@mkdir -p $(dir ./$(BUILD_DIR)/$<)
 | 
			
		||||
	$(CC) $(CFLAGS) -c $< -o $@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.PHONY: clean run
 | 
			
		||||
 | 
			
		||||
# helpers
 | 
			
		||||
QEMU_CMD = \
 | 
			
		||||
  qemu-system-aarch64 \
 | 
			
		||||
    -M virt \
 | 
			
		||||
    -cpu cortex-a57 \
 | 
			
		||||
    -nographic \
 | 
			
		||||
    -smp 4 \
 | 
			
		||||
    -m 4096 \
 | 
			
		||||
    -kernel build/kernel.elf \
 | 
			
		||||
    -serial stdio \
 | 
			
		||||
    -monitor none \
 | 
			
		||||
.PHONY: clean run debug kernel
 | 
			
		||||
 | 
			
		||||
kernel: $(BUILD_DIR)kernel
 | 
			
		||||
	cd kernel && BUILD_DIR=../$(BUILD_DIR)kernel/ make
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -Rf ./$(BUILD_DIR)/*
 | 
			
		||||
	rm -Rf ./$(BUILD_DIR)*
 | 
			
		||||
 | 
			
		||||
run: kernel
 | 
			
		||||
	$(QEMU_CMD)
 | 
			
		||||
 | 
			
		||||
	$(AARCH64_QEMU)
 | 
			
		||||
 | 
			
		||||
debug: kernel
 | 
			
		||||
	$(QEMU_CMD) -S -gdb tcp::1234 & \
 | 
			
		||||
	$(AARCH64_QEMU) -S -gdb tcp::1234 & \
 | 
			
		||||
	gdb-multiarch -q \
 | 
			
		||||
  -ex 'file build/kernel.elf' \
 | 
			
		||||
	-ex 'file $(BUILD_DIR)kernel/kernel.elf' \
 | 
			
		||||
	-ex 'target remote localhost:1234'
 | 
			
		||||
	kill %1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
#
 | 
			
		||||
# build.mk
 | 
			
		||||
# Ilja Kartašov, 2019-11-29 17:38
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
BUILD_DIR ?= build/
 | 
			
		||||
 | 
			
		||||
AARCH64_TOOLCHAIN ?= aarch64-linux-gnu
 | 
			
		||||
AARCH64_CC = clang --target=aarch64-none-elf -mcpu=cortex-a57
 | 
			
		||||
AARCH64_LD = ld.lld
 | 
			
		||||
AARCH64_OBJCOPY = $(AARCH64_TOOLCHAIN)-objcopy --target elf64-littleaarch64
 | 
			
		||||
 | 
			
		||||
AARCH64_QEMU = \
 | 
			
		||||
  qemu-system-aarch64 \
 | 
			
		||||
    -M virt \
 | 
			
		||||
    -cpu cortex-a53 \
 | 
			
		||||
    -nographic \
 | 
			
		||||
    -smp 4 \
 | 
			
		||||
    -m 4096 \
 | 
			
		||||
    -kernel build/kernel/kernel.elf \
 | 
			
		||||
    -serial stdio \
 | 
			
		||||
    -monitor none \
 | 
			
		||||
 | 
			
		||||
# AARCH64_QEMU = \
 | 
			
		||||
#  qemu-system-aarch64 \
 | 
			
		||||
#    -M raspi3 \
 | 
			
		||||
#    -nographic \
 | 
			
		||||
#    -kernel build/kernel/kernel.elf \
 | 
			
		||||
#    -serial stdio \
 | 
			
		||||
#    -monitor none \
 | 
			
		||||
# vim:ft=make
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
	.globl _start
 | 
			
		||||
 | 
			
		||||
_start:
 | 
			
		||||
 | 
			
		||||
	mrs x0, mpidr_el1       // Check CPU ID
 | 
			
		||||
	mov x1, 0xC1000000
 | 
			
		||||
	bic x0, x0, x1
 | 
			
		||||
	cbz x0, set_stack
 | 
			
		||||
	b   idle
 | 
			
		||||
 | 
			
		||||
set_stack:
 | 
			
		||||
	ldr x30, =stack_ptr  // defined in sys/memmap
 | 
			
		||||
	mov sp,  x30
 | 
			
		||||
	bl  k_main
 | 
			
		||||
 | 
			
		||||
idle:
 | 
			
		||||
	b idle
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
# environment
 | 
			
		||||
 | 
			
		||||
include ../Makevars.mk
 | 
			
		||||
 | 
			
		||||
# CFLAGS
 | 
			
		||||
 | 
			
		||||
CFLAGS += -O0
 | 
			
		||||
CFLAGS += -g
 | 
			
		||||
CFLAGS += -nostdlib
 | 
			
		||||
CFLAGS += -march=armv8-a
 | 
			
		||||
# CFLAGS += -std=c99
 | 
			
		||||
# CFLAGS += -pedantic
 | 
			
		||||
CFLAGS += -Wall
 | 
			
		||||
CFLAGS += -Wmissing-prototypes
 | 
			
		||||
CFLAGS += -Wstrict-prototypes
 | 
			
		||||
CFLAGS += -Wold-style-definition
 | 
			
		||||
 | 
			
		||||
INCS += -I./
 | 
			
		||||
 | 
			
		||||
# SOURCES
 | 
			
		||||
 | 
			
		||||
LD_SCRIPT = aarch64/aarch64.ld
 | 
			
		||||
 | 
			
		||||
SOURCE_FILES = \
 | 
			
		||||
	aarch64/boot.S \
 | 
			
		||||
	aarch64/aarch64.S \
 | 
			
		||||
	\
 | 
			
		||||
	core/main.c \
 | 
			
		||||
	core/irq.c \
 | 
			
		||||
	core/timer.c \
 | 
			
		||||
	core/log.c \
 | 
			
		||||
	\
 | 
			
		||||
	device/uart/uart_mini.c \
 | 
			
		||||
	device/uart/uart_qemu.c \
 | 
			
		||||
 | 
			
		||||
SOURCE_LIST  := $(wildcard $(SOURCE_FILES))
 | 
			
		||||
OBJECT_FILES := $(addsuffix .o, $(addprefix $(BUILD_DIR), ${SOURCE_LIST}))
 | 
			
		||||
 | 
			
		||||
# rules 
 | 
			
		||||
 | 
			
		||||
all: kernel
 | 
			
		||||
 | 
			
		||||
default: kernel
 | 
			
		||||
 | 
			
		||||
kernel: $(BUILD_DIR)kernel.elf
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)kernel.elf: $(OBJECT_FILES)
 | 
			
		||||
	$(info linking target: $@)
 | 
			
		||||
	$(AARCH64_LD) -T$(LD_SCRIPT) -nostdlib $^ -o $@
 | 
			
		||||
	$(info done: $@)
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)kernel.bin: $(BUILD_DIR)/kernel.elf
 | 
			
		||||
	$(AARCH64_OBJCOPY) -O binary $< $@
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)kernel.sym: $(BUILD_DIR)/kernel.elf
 | 
			
		||||
	$(AARCH64_OBJCOPY) --only-keep-debug $< $@
 | 
			
		||||
	$(AARCH64_OBJCOPY) --strip-debug $@
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR)%.o: %
 | 
			
		||||
	$(info compiling file: $<)
 | 
			
		||||
	@mkdir -p $(dir ./$(BUILD_DIR)$<)
 | 
			
		||||
	$(AARCH64_CC) $(INCS) $(CFLAGS) -c $< -o $@
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,181 @@
 | 
			
		|||
#include "aarch64_irq.h"
 | 
			
		||||
 | 
			
		||||
.globl aarch64_init
 | 
			
		||||
aarch64_init:
 | 
			
		||||
	/* set vector table */
 | 
			
		||||
	adr x0, aarch64_vectors
 | 
			
		||||
	msr vbar_el1, x0
 | 
			
		||||
	mov x0, 0
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_get_el
 | 
			
		||||
aarch64_get_el:
 | 
			
		||||
	mrs x0, CurrentEL
 | 
			
		||||
	lsr x0, x0, 0x02
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_get32r
 | 
			
		||||
aarch64_get32r:
 | 
			
		||||
	ldr w0, [x0]
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_set32r
 | 
			
		||||
aarch64_set32r:
 | 
			
		||||
	str w1, [x0]
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_delay
 | 
			
		||||
aarch64_delay:
 | 
			
		||||
	subs x0, x0, 0x01
 | 
			
		||||
	bne aarch64_delay
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_irq_vector_init
 | 
			
		||||
irq_vector_init:
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_irq_enable
 | 
			
		||||
aarch64_irq_enable:
 | 
			
		||||
	msr daifclr, 2
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.globl aarch64_irq_disable
 | 
			
		||||
aarch64_irq_disable:
 | 
			
		||||
	msr daifset, 2
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Exceptions Vector Table
 | 
			
		||||
 * */
 | 
			
		||||
	.macro KERNEL_ENTER
 | 
			
		||||
	sub sp, sp, 256
 | 
			
		||||
	stp x0, x1, [sp, 16 * 0]
 | 
			
		||||
	stp x2, x3, [sp, 16 * 1]
 | 
			
		||||
	stp x4, x5, [sp, 16 * 2]
 | 
			
		||||
	stp x6, x7, [sp, 16 * 3]
 | 
			
		||||
	stp x8, x9, [sp, 16 * 4]
 | 
			
		||||
	stp x10, x11, [sp, 16 * 5]
 | 
			
		||||
	stp x12, x13, [sp, 16 * 6]
 | 
			
		||||
	stp x14, x15, [sp, 16 * 7]
 | 
			
		||||
	stp x16, x17, [sp, 16 * 8]
 | 
			
		||||
	stp x18, x19, [sp, 16 * 9]
 | 
			
		||||
	stp x20, x21, [sp, 16 * 10]
 | 
			
		||||
	stp x22, x23, [sp, 16 * 11]
 | 
			
		||||
	stp x24, x25, [sp, 16 * 12]
 | 
			
		||||
	stp x26, x27, [sp, 16 * 13]
 | 
			
		||||
	stp x28, x29, [sp, 16 * 14]
 | 
			
		||||
	str x30, [sp, 16 * 15]
 | 
			
		||||
	.endm
 | 
			
		||||
 | 
			
		||||
	.macro KERNEL_LEAVE
 | 
			
		||||
	ldp x0, x1, [sp, 16 * 0]
 | 
			
		||||
	ldp x2, x3, [sp, 16 * 1]
 | 
			
		||||
	ldp x4, x5, [sp, 16 * 2]
 | 
			
		||||
	ldp x6, x7, [sp, 16 * 3]
 | 
			
		||||
	ldp x8, x9, [sp, 16 * 4]
 | 
			
		||||
	ldp x10, x11, [sp, 16 * 5]
 | 
			
		||||
	ldp x12, x13, [sp, 16 * 6]
 | 
			
		||||
	ldp x14, x15, [sp, 16 * 7]
 | 
			
		||||
	ldp x16, x17, [sp, 16 * 8]
 | 
			
		||||
	ldp x18, x19, [sp, 16 * 9]
 | 
			
		||||
	ldp x20, x21, [sp, 16 * 10]
 | 
			
		||||
	ldp x22, x23, [sp, 16 * 11]
 | 
			
		||||
	ldp x24, x25, [sp, 16 * 12]
 | 
			
		||||
	ldp x26, x27, [sp, 16 * 13]
 | 
			
		||||
	ldp x28, x29, [sp, 16 * 14]
 | 
			
		||||
	ldr x30, [sp, 16 * 15]
 | 
			
		||||
	add sp, sp, 256
 | 
			
		||||
	.endm
 | 
			
		||||
 | 
			
		||||
	.macro VECTOR_ENTRY GOTO_LABEL
 | 
			
		||||
	.align 7
 | 
			
		||||
	b \GOTO_LABEL
 | 
			
		||||
	.endm
 | 
			
		||||
 | 
			
		||||
	.macro EXCEPTION_FALLBACK EID
 | 
			
		||||
	KERNEL_ENTER
 | 
			
		||||
	mov x0, \EID
 | 
			
		||||
	mrs x1, esr_el1
 | 
			
		||||
	mrs x2, elr_el1
 | 
			
		||||
	bl k_irq_fallback
 | 
			
		||||
	b die
 | 
			
		||||
	.endm
 | 
			
		||||
 | 
			
		||||
die:
 | 
			
		||||
	b die
 | 
			
		||||
 | 
			
		||||
.align 11
 | 
			
		||||
.globl aarch64_vectors
 | 
			
		||||
aarch64_vectors:
 | 
			
		||||
	/* EL1t */
 | 
			
		||||
	VECTOR_ENTRY el1t_sync
 | 
			
		||||
	VECTOR_ENTRY el1t_irq
 | 
			
		||||
	VECTOR_ENTRY el1t_fiq
 | 
			
		||||
	VECTOR_ENTRY el1t_error
 | 
			
		||||
	/* EL1h */
 | 
			
		||||
	VECTOR_ENTRY el1h_sync
 | 
			
		||||
	VECTOR_ENTRY el1h_irq
 | 
			
		||||
	VECTOR_ENTRY el1h_fiq
 | 
			
		||||
	VECTOR_ENTRY el1h_error
 | 
			
		||||
	/* EL0 - 64bit */
 | 
			
		||||
	VECTOR_ENTRY el0_64_sync
 | 
			
		||||
	VECTOR_ENTRY el0_64_irq
 | 
			
		||||
	VECTOR_ENTRY el0_64_fiq
 | 
			
		||||
	VECTOR_ENTRY el0_64_error
 | 
			
		||||
	/* EL0 - 32bit */
 | 
			
		||||
	VECTOR_ENTRY el0_32_sync
 | 
			
		||||
	VECTOR_ENTRY el0_32_irq
 | 
			
		||||
	VECTOR_ENTRY el0_32_fiq
 | 
			
		||||
	VECTOR_ENTRY el0_32_error
 | 
			
		||||
 | 
			
		||||
el1t_sync:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1t_SYNC
 | 
			
		||||
 | 
			
		||||
el1t_irq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1t_IRQ
 | 
			
		||||
 | 
			
		||||
el1t_fiq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1t_FIQ
 | 
			
		||||
 | 
			
		||||
el1t_error:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1t_ERROR
 | 
			
		||||
 | 
			
		||||
el1h_sync:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1h_SYNC
 | 
			
		||||
 | 
			
		||||
el1h_irq:
 | 
			
		||||
	KERNEL_ENTER
 | 
			
		||||
	bl k_irq_handler
 | 
			
		||||
	KERNEL_LEAVE
 | 
			
		||||
	eret
 | 
			
		||||
 | 
			
		||||
el1h_fiq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1h_FIQ
 | 
			
		||||
 | 
			
		||||
el1h_error:
 | 
			
		||||
	EXCEPTION_FALLBACK EL1h_ERROR
 | 
			
		||||
 | 
			
		||||
el0_64_sync:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_64_SYNC
 | 
			
		||||
 | 
			
		||||
el0_64_irq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_64_IRQ
 | 
			
		||||
 | 
			
		||||
el0_64_fiq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_64_FIQ
 | 
			
		||||
 | 
			
		||||
el0_64_error:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_64_ERROR
 | 
			
		||||
 | 
			
		||||
el0_32_sync:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_32_SYNC
 | 
			
		||||
 | 
			
		||||
el0_32_irq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_32_IRQ
 | 
			
		||||
 | 
			
		||||
el0_32_fiq:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_32_FIQ
 | 
			
		||||
 | 
			
		||||
el0_32_error:
 | 
			
		||||
	EXCEPTION_FALLBACK EL0_32_ERROR
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file util.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef AARCH64_H_F3AA8888_CEB3_4C16_9835_C3F23B040BB5
 | 
			
		||||
#define AARCH64_H_F3AA8888_CEB3_4C16_9835_C3F23B040BB5
 | 
			
		||||
 | 
			
		||||
#include "aarch64_reg.h"
 | 
			
		||||
#include "aarch64_irq.h"
 | 
			
		||||
 | 
			
		||||
extern unsigned int
 | 
			
		||||
aarch64_init(void);
 | 
			
		||||
 | 
			
		||||
extern unsigned int
 | 
			
		||||
aarch64_get_el(void);
 | 
			
		||||
 | 
			
		||||
extern unsigned int
 | 
			
		||||
aarch64_get32r(unsigned long reg);
 | 
			
		||||
 | 
			
		||||
extern void
 | 
			
		||||
aarch64_set32r(unsigned long reg, unsigned int value);
 | 
			
		||||
 | 
			
		||||
extern void
 | 
			
		||||
aarch64_delay(unsigned long cycles);
 | 
			
		||||
 | 
			
		||||
extern void
 | 
			
		||||
aarch64_irq_enable(void);
 | 
			
		||||
 | 
			
		||||
extern void
 | 
			
		||||
aarch64_irq_disable(void);
 | 
			
		||||
 | 
			
		||||
#endif /* !AARCH64_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file aarch64_irq.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef AARCH64_IRQ_H_286AEC6E_325F_469E_B140_53DDDD63876C
 | 
			
		||||
#define AARCH64_IRQ_H_286AEC6E_325F_469E_B140_53DDDD63876C
 | 
			
		||||
 | 
			
		||||
#define EL1t_SYNC    0
 | 
			
		||||
#define EL1t_IRQ     1
 | 
			
		||||
#define EL1t_FIQ     2
 | 
			
		||||
#define EL1t_ERROR   3
 | 
			
		||||
#define EL1h_SYNC    4
 | 
			
		||||
#define EL1h_IRQ     5
 | 
			
		||||
#define EL1h_FIQ     6
 | 
			
		||||
#define EL1h_ERROR   7
 | 
			
		||||
#define EL0_64_SYNC  8
 | 
			
		||||
#define EL0_64_IRQ   9
 | 
			
		||||
#define EL0_64_FIQ   10
 | 
			
		||||
#define EL0_64_ERROR 11
 | 
			
		||||
#define EL0_32_SYNC  12
 | 
			
		||||
#define EL0_32_IRQ   13
 | 
			
		||||
#define EL0_32_FIQ   14
 | 
			
		||||
#define EL0_32_ERROR 15
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* !AARCH64_IRQ_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file aarch64_reg.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef AARCH64_REG_H_C74FE7BF_C8A6_4718_867A_C125CBF326BD
 | 
			
		||||
#define AARCH64_REG_H_C74FE7BF_C8A6_4718_867A_C125CBF326BD
 | 
			
		||||
 | 
			
		||||
/* Saved Program Status Register (SPSR)
 | 
			
		||||
 * Exception Level 3 (EL3)
 | 
			
		||||
 * See page 389 of AArch64-Reference-Manual
 | 
			
		||||
 * */
 | 
			
		||||
#define SPSR_MASK_ALL (7 << 6)
 | 
			
		||||
#define SPSR_EL1h     (5 << 0)
 | 
			
		||||
#define SPSR_VALUE    (SPSR_MASK_ALL | SPSR_EL1h)
 | 
			
		||||
 | 
			
		||||
/* Secure Configuration Register (SCR)
 | 
			
		||||
 * Exception Level 3 (EL3)
 | 
			
		||||
 * See page 2648 of AArch64-Reference-Manual
 | 
			
		||||
 * */
 | 
			
		||||
#define SCR_RESERVED (3 << 4)
 | 
			
		||||
#define SCR_RW       (1 << 10)
 | 
			
		||||
#define SCR_NS       (1 << 0)
 | 
			
		||||
#define SCR_VALUE    (SCR_RESERVED | SCR_RW | SCR_NS)
 | 
			
		||||
 | 
			
		||||
/* Hypervisor Configuration Register (HCR)
 | 
			
		||||
 * Exception Level 2 (EL2)
 | 
			
		||||
 * See page 2487 of AArch64-Reference-Manual
 | 
			
		||||
 * */
 | 
			
		||||
#define HCR_RW    (1 << 31)
 | 
			
		||||
#define HCR_VALUE HCR_RW
 | 
			
		||||
 | 
			
		||||
/* System Control REgister (SCTLR_EL1)
 | 
			
		||||
 * Exception Level 1 (EL1)
 | 
			
		||||
 * See page 2654 of AArch64-Reference-Manual
 | 
			
		||||
 * */
 | 
			
		||||
#define SCTLR_RESERVED          (3 << 28) | (3 << 22) | (1 << 20) | (1 << 11)
 | 
			
		||||
#define SCTLR_EE_LITTLE_ENDIAN  (0 << 25)
 | 
			
		||||
#define SCTLR_EOE_LITTLE_ENDIAN (0 << 24)
 | 
			
		||||
#define SCTLR_I_CACHE_DISABLED  (0 << 12)
 | 
			
		||||
#define SCTLR_D_CACHE_DISABLED  (0 << 2)
 | 
			
		||||
#define SCTLR_MMU_DISABLED      (0 << 0)
 | 
			
		||||
#define SCTLR_MMU_ENABLED       (1 << 0)
 | 
			
		||||
 | 
			
		||||
#define SCTLR_VALUE_MMU_DISABLED (SCTLR_RESERVED | SCTLR_EE_LITTLE_ENDIAN \
 | 
			
		||||
		| SCTLR_I_CACHE_DISABLED | SCTLR_D_CACHE_DISABLED | SCTLR_MMU_DISABLED)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* !AARCH64_REG_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file bcm2837.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef BCM2837_H_13CD1DB9_AAD7_4F1C_8669_37DED77135D1
 | 
			
		||||
#define BCM2837_H_13CD1DB9_AAD7_4F1C_8669_37DED77135D1
 | 
			
		||||
 | 
			
		||||
#define PERIPHERAL_BASE 0x3F000000
 | 
			
		||||
 | 
			
		||||
/* GPIO */
 | 
			
		||||
#define GPFSEL1   (PERIPHERAL_BASE + 0x00200004)
 | 
			
		||||
#define GPSET0    (PERIPHERAL_BASE + 0x0020001C)
 | 
			
		||||
#define GPCLR0    (PERIPHERAL_BASE + 0x00200028)
 | 
			
		||||
#define GPPUD     (PERIPHERAL_BASE + 0x00200094)
 | 
			
		||||
#define GPPUDCLK0 (PERIPHERAL_BASE + 0x00200098)
 | 
			
		||||
 | 
			
		||||
/* UART MINI */
 | 
			
		||||
#define AUX_ENABLES     (PERIPHERAL_BASE + 0x00215004)
 | 
			
		||||
#define AUX_MU_IO_REG   (PERIPHERAL_BASE + 0x00215040)
 | 
			
		||||
#define AUX_MU_IER_REG  (PERIPHERAL_BASE + 0x00215044)
 | 
			
		||||
#define AUX_MU_IIR_REG  (PERIPHERAL_BASE + 0x00215048)
 | 
			
		||||
#define AUX_MU_LCR_REG  (PERIPHERAL_BASE + 0x0021504C)
 | 
			
		||||
#define AUX_MU_MCR_REG  (PERIPHERAL_BASE + 0x00215050)
 | 
			
		||||
#define AUX_MU_LSR_REG  (PERIPHERAL_BASE + 0x00215054)
 | 
			
		||||
#define AUX_MU_MSR_REG  (PERIPHERAL_BASE + 0x00215058)
 | 
			
		||||
#define AUX_MU_SCRATCH  (PERIPHERAL_BASE + 0x0021505C)
 | 
			
		||||
#define AUX_MU_CNTL_REG (PERIPHERAL_BASE + 0x00215060)
 | 
			
		||||
#define AUX_MU_STAT_REG (PERIPHERAL_BASE + 0x00215064)
 | 
			
		||||
#define AUX_MU_BAUD_REG (PERIPHERAL_BASE + 0x00215068)
 | 
			
		||||
 | 
			
		||||
/* IRQ */
 | 
			
		||||
#define IRQ_BASIC_PENDING  (PERIPHERAL_BASE + 0x0000B200)
 | 
			
		||||
#define IRQ_PENDING_1      (PERIPHERAL_BASE + 0x0000B204)
 | 
			
		||||
#define IRQ_PENDING_2      (PERIPHERAL_BASE + 0x0000B208)
 | 
			
		||||
#define FIQ_CONTROL        (PERIPHERAL_BASE + 0x0000B20C)
 | 
			
		||||
#define ENABLE_IRQS_1      (PERIPHERAL_BASE + 0x0000B210)
 | 
			
		||||
#define ENABLE_IRQS_2      (PERIPHERAL_BASE + 0x0000B214)
 | 
			
		||||
#define ENABLE_BASIC_IRQS  (PERIPHERAL_BASE + 0x0000B218)
 | 
			
		||||
#define DISABLE_IRQS_1     (PERIPHERAL_BASE + 0x0000B21C)
 | 
			
		||||
#define DISABLE_IRQS_2     (PERIPHERAL_BASE + 0x0000B220)
 | 
			
		||||
#define DISABLE_BASIC_IRQS (PERIPHERAL_BASE + 0x0000B224)
 | 
			
		||||
 | 
			
		||||
/* SYSTEM TIMER */
 | 
			
		||||
#define SYSTEM_TIMER_IRQ_0 (1 << 0)
 | 
			
		||||
#define SYSTEM_TIMER_IRQ_1 (1 << 1)
 | 
			
		||||
#define SYSTEM_TIMER_IRQ_2 (1 << 2)
 | 
			
		||||
#define SYSTEM_TIMER_IRQ_3 (1 << 3)
 | 
			
		||||
 | 
			
		||||
/* TIMER */
 | 
			
		||||
#define TIMER_CS  (PERIPHERAL_BASE + 0x00003000)
 | 
			
		||||
#define TIMER_CLO (PERIPHERAL_BASE + 0x00003004)
 | 
			
		||||
#define TIMER_CHI (PERIPHERAL_BASE + 0x00003008)
 | 
			
		||||
#define TIMER_C0  (PERIPHERAL_BASE + 0x0000300C)
 | 
			
		||||
#define TIMER_C1  (PERIPHERAL_BASE + 0x00003010)
 | 
			
		||||
#define TIMER_C2  (PERIPHERAL_BASE + 0x00003014)
 | 
			
		||||
#define TIMER_C3  (PERIPHERAL_BASE + 0x00003018)
 | 
			
		||||
 | 
			
		||||
#define TIMER_CS_M0 (1 << 0)
 | 
			
		||||
#define TIMER_CS_M1 (1 << 1)
 | 
			
		||||
#define TIMER_CS_M2 (1 << 2)
 | 
			
		||||
#define TIMER_CS_M3 (1 << 3)
 | 
			
		||||
 | 
			
		||||
#endif /* !BCM2837_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
 | 
			
		||||
#include "aarch64_reg.h"
 | 
			
		||||
 | 
			
		||||
	.globl _start
 | 
			
		||||
 | 
			
		||||
_start:
 | 
			
		||||
	mrs x0, mpidr_el1       /* Check CPU ID */
 | 
			
		||||
	mov x1, 0xC1000000
 | 
			
		||||
	bic x0, x0, x1
 | 
			
		||||
	cbz x0, set_el
 | 
			
		||||
idle:
 | 
			
		||||
	b idle
 | 
			
		||||
 | 
			
		||||
set_el:
 | 
			
		||||
	/* check current exception level */
 | 
			
		||||
	bl aarch64_get_el
 | 
			
		||||
	cmp x0, 0x03
 | 
			
		||||
	bne set_stack
 | 
			
		||||
	/* set SCTRL_EL1 */
 | 
			
		||||
	ldr x0, =SCTLR_VALUE_MMU_DISABLED
 | 
			
		||||
	msr sctlr_el1, x0
 | 
			
		||||
	/* set HCR_EL2 */
 | 
			
		||||
	ldr x0, =HCR_VALUE
 | 
			
		||||
	msr hcr_el2, x0
 | 
			
		||||
	/* set SCR_EL3 */
 | 
			
		||||
	ldr x0, =SCR_VALUE
 | 
			
		||||
	msr scr_el3, x0
 | 
			
		||||
	/* set SPSR_EL3 */
 | 
			
		||||
	ldr x0, =SPSR_VALUE
 | 
			
		||||
	msr spsr_el3, x0
 | 
			
		||||
	/* set elr_el3 */
 | 
			
		||||
	adr x0, set_stack
 | 
			
		||||
	msr elr_el3, x0
 | 
			
		||||
	eret
 | 
			
		||||
 | 
			
		||||
set_stack:
 | 
			
		||||
	ldr x30, =stack_ptr  /* defined in aarch64.ld */
 | 
			
		||||
	mov sp,  x30
 | 
			
		||||
	bl  k_main
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file arch.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ARCH_H_F63C116D_51C9_4E25_9B1F_126833937268
 | 
			
		||||
#define ARCH_H_F63C116D_51C9_4E25_9B1F_126833937268
 | 
			
		||||
 | 
			
		||||
#include <aarch64/aarch64.h>
 | 
			
		||||
 | 
			
		||||
#define k_arch_init(...) aarch64_init(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#endif /* !ARCH_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file irq.c
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <aarch64/bcm2837.h>
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "irq.h"
 | 
			
		||||
 | 
			
		||||
static const char *m_types[] = {
 | 
			
		||||
	"EL1t_SYNC",
 | 
			
		||||
	"EL1t_IRQ",
 | 
			
		||||
	"EL1t_FIQ",
 | 
			
		||||
	"EL1t_ERROR",
 | 
			
		||||
	"EL1h_SYNC",
 | 
			
		||||
	"EL1h_IRQ",
 | 
			
		||||
	"EL1h_FIQ",
 | 
			
		||||
	"EL1h_ERROR",
 | 
			
		||||
	"EL0_64_SYNC",
 | 
			
		||||
	"EL0_64_IRQ",
 | 
			
		||||
	"EL0_64_FIQ",
 | 
			
		||||
	"EL0_64_ERROR",
 | 
			
		||||
	"EL0_32_SYNC",
 | 
			
		||||
	"EL0_32_IRQ",
 | 
			
		||||
	"EL0_32_FIQ",
 | 
			
		||||
	"EL0_32_ERROR"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_irq_enable_controller()
 | 
			
		||||
{
 | 
			
		||||
	aarch64_set32r(ENABLE_IRQS_1, SYSTEM_TIMER_IRQ_1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_irq_handler(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int irq = aarch64_get32r(IRQ_PENDING_1);
 | 
			
		||||
	switch(irq) {
 | 
			
		||||
	case SYSTEM_TIMER_IRQ_1:
 | 
			
		||||
		k_timer_irq_handler();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		k_logs("Unhandled irq: ");
 | 
			
		||||
		k_logu(irq, 16);
 | 
			
		||||
		k_logs("\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_irq_fallback(int type, unsigned long esr, unsigned long address)
 | 
			
		||||
{
 | 
			
		||||
	k_logs(m_types[type]);
 | 
			
		||||
	k_logs(" -> ESR: ");
 | 
			
		||||
	k_logu(esr, 16);
 | 
			
		||||
	k_logs(", address: ");
 | 
			
		||||
	k_logu(address, 16);
 | 
			
		||||
	k_logs("\n");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file irq.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef IRQ_H_037ADD8D_3AAA_4541_A876_843DFF3A59E8
 | 
			
		||||
#define IRQ_H_037ADD8D_3AAA_4541_A876_843DFF3A59E8
 | 
			
		||||
 | 
			
		||||
#include <aarch64/aarch64.h>
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_irq_enable_controller(void);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_irq_handler(void);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_irq_fallback(int type, unsigned long esr, unsigned long address);
 | 
			
		||||
 | 
			
		||||
#define k_irq_enable(...) aarch64_irq_enable(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#define k_irq_disable(...) aarch64_irq_disable(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#endif /* !IRQ_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file log.c
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <device/uart/uart.h>
 | 
			
		||||
#include "log.h"
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_log_init(void)
 | 
			
		||||
{
 | 
			
		||||
	uart_init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ki32
 | 
			
		||||
k_logs(const Ki8 *string)
 | 
			
		||||
{
 | 
			
		||||
	Ki8 c;
 | 
			
		||||
	const Ki8 *p = string;
 | 
			
		||||
	while((c = *p) != 0) {
 | 
			
		||||
		if (uart_write(c))
 | 
			
		||||
			return -1;
 | 
			
		||||
		p++;
 | 
			
		||||
	}
 | 
			
		||||
	return (Ki32)(p - string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ki32
 | 
			
		||||
k_logi(Ki64 value, Ku8 base)
 | 
			
		||||
{
 | 
			
		||||
	Ki32 result;
 | 
			
		||||
 | 
			
		||||
	if (value < 0) {
 | 
			
		||||
		if (uart_write('-'))
 | 
			
		||||
			return -1;
 | 
			
		||||
		value = -value;
 | 
			
		||||
		result = 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		result = 0;
 | 
			
		||||
	}
 | 
			
		||||
	result += k_logu(value, base);
 | 
			
		||||
	return (result) ? result : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ki32
 | 
			
		||||
k_logu(Ku64 value, Ku8 base)
 | 
			
		||||
{
 | 
			
		||||
	Ki32 i = 0, result;
 | 
			
		||||
	Ku8 buffer[64];
 | 
			
		||||
 | 
			
		||||
	if (!value) {
 | 
			
		||||
		return (uart_write('0')) ? -1 : 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		if (!(i < (sizeof(buffer) / sizeof(buffer[0]))))
 | 
			
		||||
			return -1;
 | 
			
		||||
 | 
			
		||||
		Ku64 r = value % base;
 | 
			
		||||
		buffer[i++] = (r < 0x0A) ? '0' + r : 'A' + r - 0x0A;
 | 
			
		||||
    value /= base; 
 | 
			
		||||
	} while (value);
 | 
			
		||||
 | 
			
		||||
	result = i;
 | 
			
		||||
 | 
			
		||||
	while (i--) {
 | 
			
		||||
		if (uart_write(buffer[i]))
 | 
			
		||||
			return -1;
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file print.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LOG_H_AE38CD54_2822_47A5_AFB1_E785739FA01D
 | 
			
		||||
#define LOG_H_AE38CD54_2822_47A5_AFB1_E785739FA01D
 | 
			
		||||
 | 
			
		||||
#include <core/types.h>
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_log_init(void);
 | 
			
		||||
 | 
			
		||||
Ki32
 | 
			
		||||
k_logs(const Ki8 *string);
 | 
			
		||||
 | 
			
		||||
Ki32
 | 
			
		||||
k_logi(Ki64 value, Ku8 base);
 | 
			
		||||
 | 
			
		||||
Ki32
 | 
			
		||||
k_logu(Ku64 value, Ku8 base);
 | 
			
		||||
 | 
			
		||||
#endif /* !LOG_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file main.c
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <core/log.h>
 | 
			
		||||
#include <core/arch.h>
 | 
			
		||||
#include <core/irq.h>
 | 
			
		||||
#include <core/timer.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_main(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_main(void)
 | 
			
		||||
{
 | 
			
		||||
	k_log_init();
 | 
			
		||||
 | 
			
		||||
	k_logs("Starting Lowe OS (EL");
 | 
			
		||||
	k_logi(aarch64_get_el(), 10);
 | 
			
		||||
	k_logs(")\n");
 | 
			
		||||
 | 
			
		||||
	if (k_arch_init())
 | 
			
		||||
		goto panic;
 | 
			
		||||
 | 
			
		||||
	k_timer_init();
 | 
			
		||||
	k_irq_enable_controller();
 | 
			
		||||
	k_irq_enable();
 | 
			
		||||
 | 
			
		||||
	goto ok;
 | 
			
		||||
	/*
 | 
			
		||||
	k_logs("\tclock");
 | 
			
		||||
	if (k_clock_init())
 | 
			
		||||
		goto panic;
 | 
			
		||||
 | 
			
		||||
	k_logs(" - ok\n\tscheduler");
 | 
			
		||||
	if (k_scheduler_init())
 | 
			
		||||
		goto panic;
 | 
			
		||||
 | 
			
		||||
	k_logs(" - ok\n");
 | 
			
		||||
 | 
			
		||||
	k_scheduler_run();
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
panic:
 | 
			
		||||
	k_logs(" - ERROR\n");
 | 
			
		||||
ok:
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		__asm__("WFE");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file task.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TASK_H_AE13C166_79B5_4256_ABF3_74DF04E1CD18
 | 
			
		||||
#define TASK_H_AE13C166_79B5_4256_ABF3_74DF04E1CD18
 | 
			
		||||
 | 
			
		||||
#include <core/types.h>
 | 
			
		||||
 | 
			
		||||
typedef Ku32 KTaskId;
 | 
			
		||||
typedef void (*KTaskCallback)(void *p_ctx);
 | 
			
		||||
 | 
			
		||||
struct k_task {
 | 
			
		||||
	KByte name[K_CONFIG_TASK_MAX_NAME_LEN + 1];
 | 
			
		||||
	KTaskCallback callback;
 | 
			
		||||
	Ku32 *stack;
 | 
			
		||||
	Ku32 stack_size;
 | 
			
		||||
	Ku32 priority;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
KTaskId
 | 
			
		||||
k_task_create(struct k_task *p_task, KTaskCallback callback, Ku32 *stack
 | 
			
		||||
		, Ku32 stack_size);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* !TASK_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file timer.c
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <aarch64/aarch64.h>
 | 
			
		||||
#include <aarch64/bcm2837.h>
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
 | 
			
		||||
const unsigned int m_interval = 200000;
 | 
			
		||||
unsigned int m_current = 0;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_timer_init(void)
 | 
			
		||||
{
 | 
			
		||||
	m_current = aarch64_get32r(TIMER_CLO);
 | 
			
		||||
	m_current += m_interval;
 | 
			
		||||
	aarch64_set32r(TIMER_C1, m_current);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_timer_irq_handler(void)
 | 
			
		||||
{
 | 
			
		||||
	m_current += m_interval;
 | 
			
		||||
	aarch64_set32r(TIMER_C1, m_current);
 | 
			
		||||
	aarch64_set32r(TIMER_CS, TIMER_CS_M1);
 | 
			
		||||
	k_logs("Timer interrupt\n");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,29 +6,20 @@
 | 
			
		|||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file main.c
 | 
			
		||||
 * @file timer.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
 | 
			
		||||
#ifndef TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F
 | 
			
		||||
#define TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_main(void);
 | 
			
		||||
 | 
			
		||||
k_timer_init(void);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
k_main(void)
 | 
			
		||||
{
 | 
			
		||||
	uart_init();
 | 
			
		||||
 | 
			
		||||
	uart_puts((unsigned char *) "Lowe OS\n");
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		__asm__("WFE");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
k_timer_irq_handler(void);
 | 
			
		||||
 | 
			
		||||
#endif /* !TIMER_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file types.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TYPES_H_BC3DA9C0_C9EE_4853_B5F5_EAA4B801664C
 | 
			
		||||
#define TYPES_H_BC3DA9C0_C9EE_4853_B5F5_EAA4B801664C
 | 
			
		||||
 | 
			
		||||
typedef int KRetCode;
 | 
			
		||||
 | 
			
		||||
typedef int Ki32;
 | 
			
		||||
typedef unsigned int Ku32;
 | 
			
		||||
typedef long long Ki64;
 | 
			
		||||
typedef unsigned long long Ku64;
 | 
			
		||||
typedef char Ki8;
 | 
			
		||||
typedef unsigned char Ku8;
 | 
			
		||||
typedef char KByte;
 | 
			
		||||
 | 
			
		||||
#endif /* !TYPES_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file uart.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0
 | 
			
		||||
#define UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0
 | 
			
		||||
 | 
			
		||||
#include "uart_mini.h"
 | 
			
		||||
#include "uart_qemu.h"
 | 
			
		||||
 | 
			
		||||
#define UART_MINI 0
 | 
			
		||||
#define UART_QEMU 1
 | 
			
		||||
 | 
			
		||||
#ifndef UART_DEFAULT
 | 
			
		||||
#define UART_DEFAULT UART_QEMU
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if UART_DEFAULT == UART_MINI
 | 
			
		||||
 | 
			
		||||
#define uart_init(...) uart_mini_init(__VA_ARGS__)
 | 
			
		||||
#define uart_read(...) uart_mini_read(__VA_ARGS__)
 | 
			
		||||
#define uart_write(...) uart_mini_write(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#elif UART_DEFAULT == UART_QEMU
 | 
			
		||||
 | 
			
		||||
#define uart_init(...)
 | 
			
		||||
#define uart_read(...)
 | 
			
		||||
#define uart_write(...) uart_qemu_write(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#warning "Unsopported default UART"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* !UART_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file uart_mini.c
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <aarch64/aarch64.h>
 | 
			
		||||
#include <aarch64/bcm2837.h>
 | 
			
		||||
 | 
			
		||||
#include "uart_mini.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
uart_mini_init(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int sel;
 | 
			
		||||
 | 
			
		||||
	/* Enable UART Mini and its registers*/
 | 
			
		||||
	aarch64_set32r(AUX_ENABLES, 1);
 | 
			
		||||
	/* Disable auto flow control, TX and RX */
 | 
			
		||||
	aarch64_set32r(AUX_MU_CNTL_REG, 0);
 | 
			
		||||
	/* Disable TX and RX interrupts */
 | 
			
		||||
	aarch64_set32r(AUX_MU_IER_REG, 0);
 | 
			
		||||
	/* Set 8bit mode */
 | 
			
		||||
	aarch64_set32r(AUX_MU_LCR_REG, 0);
 | 
			
		||||
	/* Set RTS line HIGH */
 | 
			
		||||
	aarch64_set32r(AUX_MU_MCR_REG, 0);
 | 
			
		||||
	/* Set baud rate 115200 */
 | 
			
		||||
	aarch64_set32r(AUX_MU_BAUD_REG, 0x10E);
 | 
			
		||||
 | 
			
		||||
	sel = aarch64_get32r(GPFSEL1);
 | 
			
		||||
	/* clean and set ALT5 for GPIO14 */
 | 
			
		||||
	sel &= ~(7 << 12);
 | 
			
		||||
	sel |= (2 << 12);
 | 
			
		||||
	/* clean and set ALT5 for GPIO15 */
 | 
			
		||||
	sel &= ~(7 << 15);
 | 
			
		||||
	sel |= (2 << 15);
 | 
			
		||||
	aarch64_set32r(GPFSEL1, sel);
 | 
			
		||||
 | 
			
		||||
	aarch64_set32r(GPPUD, 0);
 | 
			
		||||
	aarch64_delay(150);
 | 
			
		||||
	aarch64_set32r(GPPUDCLK0, (1 << 14) | (1 << 15));
 | 
			
		||||
	aarch64_delay(150);
 | 
			
		||||
	aarch64_set32r(GPPUDCLK0, 0);
 | 
			
		||||
 | 
			
		||||
	/* Enable TX and RX */
 | 
			
		||||
	aarch64_set32r(AUX_MU_CNTL_REG, 0x03);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
uart_mini_write(char c)
 | 
			
		||||
{
 | 
			
		||||
	while (1) {
 | 
			
		||||
		if (aarch64_get32r(AUX_MU_LSR_REG) & 0x20)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	aarch64_set32r(AUX_MU_IO_REG, c);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
uart_mini_read(char *pc)
 | 
			
		||||
{
 | 
			
		||||
	while (1) {
 | 
			
		||||
		if (aarch64_get32r(AUX_MU_LSR_REG) & 0x01)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	*pc = aarch64_get32r(AUX_MU_IO_REG) & 0xFF;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,28 +6,23 @@
 | 
			
		|||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file uart.h
 | 
			
		||||
 * @file uart_mini.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0
 | 
			
		||||
#define UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0
 | 
			
		||||
#ifndef UART_MINI_H_B0DFA3CF_5B4F_4EB0_B393_391C0069A04F
 | 
			
		||||
#define UART_MINI_H_B0DFA3CF_5B4F_4EB0_B393_391C0069A04F
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
uart_mini_init(void);
 | 
			
		||||
 | 
			
		||||
#define UART_BASE 0x09000000
 | 
			
		||||
int
 | 
			
		||||
uart_mini_write(char c);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
uart_init(void);
 | 
			
		||||
int
 | 
			
		||||
uart_mini_read(char *pc);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
uart_putc(unsigned char c);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
uart_puts(const unsigned char *s);
 | 
			
		||||
 | 
			
		||||
#endif /* !UART_H */
 | 
			
		||||
#endif /* !UART_MINI_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -13,29 +13,18 @@
 | 
			
		|||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
#include "uart_qemu.h"
 | 
			
		||||
 | 
			
		||||
#define UART_BASE 0x09000000;
 | 
			
		||||
 | 
			
		||||
volatile unsigned int *UART0 = (unsigned int *)UART_BASE;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
uart_init(void)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
uart_putc(unsigned char c)
 | 
			
		||||
int
 | 
			
		||||
uart_qemu_write(unsigned char c)
 | 
			
		||||
{
 | 
			
		||||
	*UART0 = (unsigned int) c;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
uart_puts(const unsigned char *s)
 | 
			
		||||
{
 | 
			
		||||
	while(*s) {
 | 
			
		||||
		*UART0 = (unsigned int) *(s++);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *                Copyright (c) 2017-2019 by Löwenware Ltd
 | 
			
		||||
 *             Please, refer LICENSE file for legal information
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file uart_qemu.h
 | 
			
		||||
 * @author Ilja Kartašov <ik@lowenware.com>
 | 
			
		||||
 * @brief 
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://lowenware.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UART_QEMU_H_EDB39A0E_9BED_4A47_91CD_E804A9B4E8ED
 | 
			
		||||
#define UART_QEMU_H_EDB39A0E_9BED_4A47_91CD_E804A9B4E8ED
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
uart_qemu_write(unsigned char c);
 | 
			
		||||
 | 
			
		||||
#endif /* !UART_QEMU_H */
 | 
			
		||||
							
								
								
									
										38
									
								
								sys/core.s
								
								
								
								
							
							
						
						
									
										38
									
								
								sys/core.s
								
								
								
								
							| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
# file:    core.s
 | 
			
		||||
# project: Löwe OS
 | 
			
		||||
# authors: Elias Löwe <elias@lowenware.com>
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  .global _core_init
 | 
			
		||||
  .extern _uart_puts
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  .text
 | 
			
		||||
 | 
			
		||||
_core_init:
 | 
			
		||||
  # set up stack pointer using x30 register
 | 
			
		||||
  LDR     x30, =0x40001000
 | 
			
		||||
  MOV     sp,  x30
 | 
			
		||||
  bl      1f
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  LDR     x0,  =some_int
 | 
			
		||||
  BL      _uart_putx
 | 
			
		||||
  LDR     x0,  =greeting
 | 
			
		||||
  BL      _uart_puts
 | 
			
		||||
2:
 | 
			
		||||
  B       2b
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  .data
 | 
			
		||||
 | 
			
		||||
greeting:
 | 
			
		||||
  .asciz "\nStarting Lowe OS\n"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  .equ some_int, 0x1234567890ABCDEF
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										93
									
								
								sys/uart.s
								
								
								
								
							
							
						
						
									
										93
									
								
								sys/uart.s
								
								
								
								
							| 
						 | 
				
			
			@ -1,93 +0,0 @@
 | 
			
		|||
// file    : uart.s
 | 
			
		||||
// project : Löwe OS
 | 
			
		||||
// authors : Elias Löwe <elias@lowenware.com>
 | 
			
		||||
 | 
			
		||||
// address of UART for virt device in qemu
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  .global _uart_putc    // print single character uart
 | 
			
		||||
  .global _uart_putx    // print integer in HEX format to uart
 | 
			
		||||
  .global _uart_puts    // print null-terminated string to uart
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  .text
 | 
			
		||||
 | 
			
		||||
// helper to avoid extra data moving
 | 
			
		||||
// @x1 character print
 | 
			
		||||
uart_putc:
 | 
			
		||||
  STP     x2, lr, [sp, -16]!
 | 
			
		||||
 | 
			
		||||
  MOV     x2, 0x09000000              // set UART address
 | 
			
		||||
  STRB    w1, [x2]                    // put character out
 | 
			
		||||
 | 
			
		||||
  LDP     x2, lr, [sp], 16
 | 
			
		||||
  RET
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// print character to uart
 | 
			
		||||
// @x0 character print
 | 
			
		||||
_uart_putc:
 | 
			
		||||
  STR     lr, [sp, -16]!
 | 
			
		||||
 | 
			
		||||
  MOV     x1, x0                      // set arguments
 | 
			
		||||
  BL      uart_putc                   // put character out
 | 
			
		||||
 | 
			
		||||
  LDR     lr, [sp], 16
 | 
			
		||||
  RET
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// @x0 integer to print
 | 
			
		||||
_uart_putx:
 | 
			
		||||
  STP     lr, x3, [sp, -32]!
 | 
			
		||||
  STP     x0, x1, [sp, 16]
 | 
			
		||||
 | 
			
		||||
  LDR     x3, =60                     // init bits counter 64-4
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  LSR     x1, x0, x3                  // shift to digit
 | 
			
		||||
  AND     x1, x1, 0xF                 // keep only digit
 | 
			
		||||
  CMP     x1, 9                       // compare it to 9
 | 
			
		||||
  BLS     2f                          // less or equal
 | 
			
		||||
  ADD     x1, x1, 0x37                // turn into ASCII HEX char
 | 
			
		||||
  B       3f                          // continue to output
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
  ADD     x1, x1, 0x30                // turn into ASCII num char
 | 
			
		||||
 | 
			
		||||
3:
 | 
			
		||||
  BL      uart_putc                   // output carachter
 | 
			
		||||
  CBZ     x3, 0f                      // if counter == 0 return
 | 
			
		||||
  SUB     x3, x3, 4                   // otherwise subtract counter by 4
 | 
			
		||||
  B       1b                          // repeat
 | 
			
		||||
 | 
			
		||||
0:
 | 
			
		||||
  LDP     lr, x3, [sp], 16
 | 
			
		||||
  LDP     x0, x1, [sp], 16
 | 
			
		||||
  RET
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// @x0 pointer to string
 | 
			
		||||
 | 
			
		||||
_uart_puts:
 | 
			
		||||
  STR     lr, [sp, -16]!
 | 
			
		||||
  STP     x0, x1, [sp, -16]!
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  LDRB    w1, [x0], 1                  // load byte of string from address in x0
 | 
			
		||||
  CBZ     w1, 0f                       // return if zero
 | 
			
		||||
  BL      uart_putc                    // put charcter out
 | 
			
		||||
  B       1b                           // loop
 | 
			
		||||
 | 
			
		||||
0:
 | 
			
		||||
  LDP     x0, x1, [sp], 16
 | 
			
		||||
  LDR     lr, [sp], 16
 | 
			
		||||
  RET
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
		Loading…
	
		Reference in New Issue