Compare commits

..
7 Commits
Author SHA1 Message Date
elias 21a25ec4e8 Update to work on real hardware 2020-01-29 12:01:32 +01:00
elias 85b0df56bb Add task creation and fix Task_yield procedure 2020-01-21 11:02:38 +01:00
elias 26f05b04d7 Add context switching and basic scheduler 2020-01-20 09:14:13 +01:00
elias a93f257f2e Repair compilability of code 2020-01-17 10:13:01 +01:00
elias a0c215e954 Update code due to new rules 2020-01-15 10:56:04 +01:00
elias 6c4dba0929 Fix uart_mini initialization and emulation 2019-12-02 12:59:40 +01:00
elias 417106b967 Add vector table 2019-12-01 22:57:02 +01:00
43 changed files with 2205 additions and 296 deletions
+1 -1
View File
@@ -1 +1 @@
Elias Löwe <elias@lowenware.com>
Ilja Kartaschoff <ik@lowenware.com>
-2
View File
@@ -1,2 +0,0 @@
# Lion's Share License -> LSL
# Löwenware Software Distribution -> LSD
+39
View File
@@ -0,0 +1,39 @@
# License
Leos (the "Software") is an intellectual property of Löwenware s.r.o.
distributed under terms of [Attribution-NoDerivatives 4.0 International](https://creativecommons.org/licenses/by-nd/4.0/legalcode)
**(CC BY-ND 4.0)** license.
## Highlights
Information below highlights only key features and terms of the
[license](https://creativecommons.org/licenses/by-nd/4.0/legalcode). It is
recommended to read its full text before using licensed Software.
### You are free to:
**Share** — copy and redistribute the Software in any medium or format
for any purpose, even commercially. The licensor cannot revoke these freedoms
as long as you follow the license terms.
### Under the following terms:
**Attribution** — You must give appropriate credit, provide a link to the license,
and indicate if changes were made. You may do so in any reasonable manner, but
not in any way that suggests the licensor endorses you or your use.
**NoDerivatives** — If you remix, transform, or build upon the Software, you may
not distribute the modified material.
**No additional restrictions** — You may not apply legal terms or technological
measures that legally restrict others from doing anything the license permits.
### Disclaimer
The Software is provided "AS IS" without warranty of any kind. In no
event shall the authors or copyright holders be liable for any claim, damages
or other liability, whether out of or in connection with the Software or its
usage.
The license may not give you all of the permissions necessary for your
intended use. For example, other rights such as publicity, privacy,
or moral rights may limit how you use the material.
+18 -77
View File
@@ -1,90 +1,31 @@
# environment
ROOT = ./
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}))
include ${ROOT}Makevars.mk
# 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 & \
gdb-multiarch -q \
-ex 'file build/kernel.elf' \
-ex 'target remote localhost:1234'
$(AARCH64_QEMU) -S -gdb tcp::1234 & \
gdb-multiarch -q \
-ex 'file $(BUILD_DIR)kernel/kernel.elf' \
-ex 'target remote localhost:1234'
kill %1
console:
sudo picocom -b 115200 -r -l /dev/ttyUSB0
+46
View File
@@ -0,0 +1,46 @@
#
# build.mk
# Ilja Kartašov, 2019-11-29 17:38
#
include ${ROOT}kernel/config.mk
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 /dev/null \
-serial stdio \
-monitor none \
# -kernel /home/elias/git/rpi/boards/pi3/aarch64/uart02/kernel8.img \
# vim:ft=make
#
CONFIG_CFLAGS = -D"CONFIG_ARCH=\"${CONFIG_ARCH}\""
CONFIG_CFLAGS = -DCONFIG_ARM_TIMER=${CONFIG_ARM_TIMER}
#ifeq (${CONFIG_HARDWARE}, rpi3)
#CONFIG_CFLAGS += -DCONFIG_HARDWARE_RPI3=1
#else ifeq (${CONFIG_HARDWARE}, qemu)
#CONFIG_CFLAGS += -DCONFIG_HARDWARE_QEMU=1
#endif
+87 -2
View File
@@ -1,3 +1,88 @@
# Löwe OS
Operating System for ARMv8 (aarch64) architecture.
# LeOS
Operating System for ARMv8 (aarch64) Architecture
* [The Idea](#The Idea)
* [Hardware](#Hardware)
* [Documentation](#Documentation)
* [Compilation](#Compilation)
* [Run](#Run)
* [Debug](#Debug)
* [Roadmap](#Roadmap)
* [Contribution](#Contribution)
---
## The Idea
Löwe OS is being developed to be a lightweight desktop operating system for
ARM-based computers, tablets, mobile phones etc. Here are some concepts behind
it:
1. The OS is free with open source codes, distributed under terms of [CC BY-ND 4.0](LICENSE.md).
2. The OS will have POSIX-compliant API.
3. The OS will include graphical system, shell and generic utilities as a part
of it, being designed to work as a solid product.
4. The OS will respect user's privacy and will not track his/her actions and data.
5. The OS will stive to be secure and robust.
## Hardware
Early development is going for **Raspberry PI3** board and its emulation using
**QEMU**.
## Documentation
* [Project structure](docs/project-structure.md)
* [Coding style](docs/coding-style.md)
* Task scheduling
* Memory management
## Compilation
To compile Löwe OS run `make` from repository root, make sure
[Clang](https://clang.llvm.org/) compiler is installed on your system.
```
$ make
```
Output files will be stored inside newly created `build` folder.
## Run
To run Löwe OS on QEMU, execute `make run` command for the repository root.
To run Löwe OS on Raspberry PI3, follow these steps:
1. Compile project and copy `build/kernel8.img` and `config.txt` files to
Micro SD card
2. Make sure latest `bootcode.bin` and `start.elf` files are copied to the SD card
3. Insert SD card into your Raspberry PI3 and power it up
## Debug
If you have `gdb-multiarch` and **QEMU** installed, then debugging should be as
easy as `make debug`.
## Roadmap
1. Generic kernel features:
[x] Loadable Kernel file
[x] UART logging
[x] Memory pages avalability bitmap
[x] Interrupt vectors table
[x] Basic task scheduler
[x] Context switching
[ ] MMU and entering user level
2. Input/output:
[ ] Graphical driver
[ ] USB driver
[ ] Keyboard input driver
[ ] Mouse input driver
3. Graphical system
4. Shell and utilities
5. Networking
6. Sound system
## Contribution
-18
View File
@@ -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
-16
View File
@@ -1,16 +0,0 @@
ENTRY(_start)
SECTIONS
{
/* For some reason qemu UART doesn't work with smaller address */
. = 0x40000000;
.boot . : { boot.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000;
stack_ptr = . ;
}
+3
View File
@@ -0,0 +1,3 @@
arm_control=0x200
kernel_old=1
disable_commandline_tags=1
+79
View File
@@ -0,0 +1,79 @@
# LeOS Coding Style
## Files names
1. Only lower case
2. Words separated with underscore:
```
aarch64/aarch64_boot.S
```
## Preprocessor macro constants
1. Only upper case
2. Words separated with underscore:
```
#define AARCH64_CORE0_TIMER_IRQCTL (*((uint32_t *) 0x40000040))
```
## Types
1. Camel case started from upper case
2. Do not typedef transparent structures
3. Members of structre should be named in camel case started from lower case
```
struct Task {
void *sp;
void *stackStart;
uint32_t pid;
uint32_t stackSize;
uint32_t lock;
uint32_t counter;
uint32_t cycles;
int32_t priority;
uint32_t state;
char name[CONFIG_TASK_MAX_NAME_LEN + 1];
struct Task *next;
};
```
## Constants and variables
1. Global constants and variablesmust be prefixed with `g_`
2. Module (static) constants and variable must be prefixed `m_`
3. Camel case
```
static struct Task *m_currentTask = NULL;
```
## Functions
1. Camel case
2. Prefix separated from function identifier by underscore
3. Static functions may have no prefix
4. Prefix always starts from capital letter
5. Function identifier always starts from lower case verb
```
unsigned int
AArch64_getEL(void);
static struct Task *
scheduleNext(void);
```
## Namespaces and prefixes
1. Due to C has no native namespaces, prefixes should always be used
2. Prefix should match with file name
```
/* file : task.h */
void
Task_initSheduler(void);
```
+10
View File
@@ -0,0 +1,10 @@
# Project Structure
* `build/` - temporary output folder
* `docs/` - documentation folder
* `kernel/` - kernel source codes
* `aarch64/` - core AArch64 architecture code
* `drivers/` - code for various drivers
* `leos/` - code of the core LeOS features
* `Makefile` - kernel specific makefile
* `Makefile` - root project makefile
+71
View File
@@ -0,0 +1,71 @@
# environment
ROOT = ../
include ${ROOT}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/aarch64_boot.S \
aarch64/aarch64.S \
\
leos/irq.c \
leos/leos.c \
leos/log.c \
leos/memory.c \
leos/task.c \
\
drivers/timer/timer.c \
drivers/uart/uart_mini.c \
drivers/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.list $(BUILD_DIR)kernel.bin
$(BUILD_DIR)kernel.elf: $(OBJECT_FILES)
$(info linking target: $@)
$(AARCH64_LD) -T$(LD_SCRIPT) -nostdlib $^ -o $@
$(info done: $@)
$(BUILD_DIR)kernel.list: $(BUILD_DIR)kernel.elf
$(AARCH64_OBJCOPY) -D $(BUILD_DIR)kernel.elf > $@
$(BUILD_DIR)kernel.bin: $(BUILD_DIR)/kernel.elf
$(AARCH64_OBJCOPY) -O binary $< $@
cp $@ $(BUILD_DIR)kernel8.img
$(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) $(CONFIG_CFLAGS) -c $< -o $@
+282
View File
@@ -0,0 +1,282 @@
#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_getEL
AArch64_getEL:
mrs x0, CurrentEL
lsr x0, x0, 0x02
ret
.globl AArch64_getReg32
AArch64_getReg32:
ldr w0, [x0]
ret
.globl AArch64_setReg32
AArch64_setReg32:
str w1, [x0]
ret
.globl AArch64_idle
AArch64_idle:
subs x0, x0, 1
bne AArch64_idle
ret
/*
.globl AArch64_initIRQVector
AArch64_initIRQVector:
ret
*/
.globl AArch64_enableIRQ
AArch64_enableIRQ:
msr daifclr, 2
ret
.globl AArch64_disableIRQ
AArch64_disableIRQ:
msr daifset, 2
ret
.globl AArch64_memzero
AArch64_memzero:
str xzr, [x0], 8
subs x1, x1, 8
b.gt AArch64_memzero
ret
/* Exceptions Vector Table
* */
.macro SAVE_REGISTERS
sub sp, sp, 272
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]
mrs x22, elr_el1
mrs x23, spsr_el1
stp x30, x22, [sp, 16 * 15]
str x23, [sp, 16 * 16]
.endm
.macro LOAD_REGISTERS
ldr x23, [sp, 16 * 16]
ldp x30, x22, [sp, 16 * 15]
msr elr_el1, x22
msr spsr_el1, x23
ldp x28, x29, [sp, 16 * 14]
ldp x26, x27, [sp, 16 * 13]
ldp x24, x25, [sp, 16 * 12]
ldp x22, x23, [sp, 16 * 11]
ldp x20, x21, [sp, 16 * 10]
ldp x18, x19, [sp, 16 * 9]
ldp x16, x17, [sp, 16 * 8]
ldp x14, x15, [sp, 16 * 7]
ldp x12, x13, [sp, 16 * 6]
ldp x10, x11, [sp, 16 * 5]
ldp x8, x9, [sp, 16 * 4]
ldp x6, x7, [sp, 16 * 3]
ldp x4, x5, [sp, 16 * 2]
ldp x2, x3, [sp, 16 * 1]
ldp x0, x1, [sp, 16 * 0]
add sp, sp, 272
.endm
.macro VECTOR_ENTRY GOTO_LABEL
.align 7
b \GOTO_LABEL
.endm
.macro EXCEPTION_FALLBACK EID
SAVE_REGISTERS
mov x0, \EID
mrs x1, esr_el1
mrs x2, elr_el1
bl IRQ_fallback
b die
.endm
die:
b die
.globl AArch64_startTask
AArch64_startTask:
bl Task_unlockScheduler
mov x0, x20
blr x21
hang:
/* todo: implement task exit here */
WFE
b hang
.globl AArch64_getPState
AArch64_getPState:
mrs x23, NZCV
mrs x3, DAIF
orr x23, x23, x3
mrs x3, CurrentEL
lsr x3, x3, 0x02
/* set third bit: todo: find out its real meaning (registers width?) */
orr x3, x3, 0x04
orr x0, x23, x3
ret
.globl AArch64_switchContext
AArch64_switchContext:
/* Save current task context */
sub sp, sp, 272
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]
mrs x23, NZCV
mrs x3, DAIF
orr x23, x23, x3
mrs x3, CurrentEL
lsr x3, x3, 0x02
orr x23, x23, x3
stp x30, x30, [sp, 16 * 15]
str x23, [sp, 16 * 16]
mov x2, sp
str x2, [x0]
/* Restore next task context */
ldr x2, [x1]
mov sp, x2
ldr x30, [sp, 16 * 15]
ldp x28, x29, [sp, 16 * 14]
ldp x26, x27, [sp, 16 * 13]
ldp x24, x25, [sp, 16 * 12]
ldp x22, x23, [sp, 16 * 11]
ldp x20, x21, [sp, 16 * 10]
ldp x18, x19, [sp, 16 * 9]
ldp x16, x17, [sp, 16 * 8]
ldp x14, x15, [sp, 16 * 7]
ldp x12, x13, [sp, 16 * 6]
ldp x10, x11, [sp, 16 * 5]
ldp x8, x9, [sp, 16 * 4]
ldp x6, x7, [sp, 16 * 3]
ldp x4, x5, [sp, 16 * 2]
ldp x2, x3, [sp, 16 * 1]
ldp x0, x1, [sp, 16 * 0]
add sp, sp, 272
ret
.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:
SAVE_REGISTERS
mov x0, sp
bl Task_setStackPointer
bl IRQ_onInterrupt
bl Task_getStackPointer
mov sp, x0
load_regs:
LOAD_REGISTERS
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
+56
View File
@@ -0,0 +1,56 @@
/******************************************************************************
*
* 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 <leos/types.h>
#include "aarch64_reg.h"
#include "aarch64_irq.h"
extern unsigned int
AArch64_init(void);
extern unsigned int
AArch64_getEL(void);
extern unsigned int
AArch64_getReg32(unsigned long reg);
extern void
AArch64_setReg32(unsigned long reg, unsigned int value);
extern void
AArch64_idle(unsigned long cycles);
extern void
AArch64_enableIRQ(void);
extern void
AArch64_disableIRQ(void);
extern void
AArch64_memzero(void *addr, unsigned long size);
extern void
AArch64_startTask(void *arg, void *callback);
extern uint32_t
AArch64_getPState(void);
extern void
AArch64_switchContext(void *currentTask, void *nextTask);
#endif /* !AARCH64_H */
+15
View File
@@ -0,0 +1,15 @@
SECTIONS
{
.text.boot : { *(.text.boot) }
.text : { *(.text) }
.rodata : { *(.rodata) }
.data : { *(.data) }
. = ALIGN(0x8);
bss_begin = .;
.bss : { *(.bss*) }
bss_end = .;
. = ALIGN(8);
. = . + 0x4000;
ld_stackPtr = . ;
}
+41
View File
@@ -0,0 +1,41 @@
#include "aarch64_reg.h"
.section ".text.boot"
.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:
/* 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, =ld_stackPtr /* defined in aarch64.ld */
mov sp, x30
bl skip
skip:
bl Leos_run
hang: b hang
+37
View File
@@ -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 */
+163
View File
@@ -0,0 +1,163 @@
/******************************************************************************
*
* 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
#define AARCH64_LOCAL_INT_ROUTING *((uint32_t *) 0x40000024)
#define AARCH64_LOCAL_TIMER_STATCTL *((uint32_t *) 0x40000034)
#define AARCH64_LOCAL_TIMER_RECLR *((uint32_t *) 0x40000038)
/* Timers interrupt control registers
* */
#define AARCH64_CORE0_TIMER_IRQCTL *((uint32_t *) 0x40000040)
#define AARCH64_CORE1_TIMER_IRQCTL *((uint32_t *) 0x40000044)
#define AARCH64_CORE2_TIMER_IRQCTL *((uint32_t *) 0x40000048)
#define AARCH64_CORE3_TIMER_IRQCTL *((uint32_t *) 0x4000004C)
/* Timer interrupr routing
* */
#define AARCH64_TIMER0_IRQ 0x01
#define AARCH64_TIMER1_IRQ 0x02
#define AARCH64_TIMER2_IRQ 0x04
#define AARCH64_TIMER3_IRQ 0x08
#define AARCH64_TIMER0_FIQ 0x10
#define AARCH64_TIMER1_FIQ 0x20
#define AARCH64_TIMER2_FIQ 0x40
#define AARCH64_TIMER3_FIQ 0x80
/* Mailbox control registers
* */
#define AARCH64_CORE0_MBOX_IRQCTL *((uint32_t *) 0x40000050)
#define AARCH64_CORE1_MBOX_IRQCTL *((uint32_t *) 0x40000054)
#define AARCH64_CORE2_MBOX_IRQCTL *((uint32_t *) 0x40000058)
#define AARCH64_CORE3_MBOX_IRQCTL *((uint32_t *) 0x4000005C)
/* Mailbox interrupr routing
* */
#define AARCH64_MBOX0_IRQ 0x01
#define AARCH64_MBOX1_IRQ 0x02
#define AARCH64_MBOX2_IRQ 0x04
#define AARCH64_MBOX3_IRQ 0x08
#define AARCH64_MBOX0_FIQ 0x10
#define AARCH64_MBOX1_FIQ 0x20
#define AARCH64_MBOX2_FIQ 0x40
#define AARCH64_MBOX3_FIQ 0x80
/* Source registers for IRQ / FIQ
* */
#define AARCH64_CORE0_IRQSRC *((uint32_t *) 0x40000060)
#define AARCH64_CORE1_IRQSRC *((uint32_t *) 0x40000064)
#define AARCH64_CORE2_IRQSRC *((uint32_t *) 0x40000068)
#define AARCH64_CORE3_IRQSRC *((uint32_t *) 0x4000006C)
#define AARCH64_CORE0_FIQSRC *((uint32_t *) 0x40000070)
#define AARCH64_CORE1_FIQSRC *((uint32_t *) 0x40000074)
#define AARCH64_CORE2_FIQSRC *((uint32_t *) 0x40000078)
#define AARCH64_CORE3_FIQSRC *((uint32_t *) 0x4000007C)
/* Interrupt source bits
* */
#define AARCH64_TIMER0_INTSRC 0x0001
#define AARCH64_TIMER1_INTSRC 0x0002
#define AARCH64_TIMER2_INTSRC 0x0004
#define AARCH64_TIMER3_INTSRC 0x0008
#define AARCH64_MBOX0_INTSRC 0x0010
#define AARCH64_MBOX1_INTSRC 0x0020
#define AARCH64_MBOX2_INTSRC 0x0040
#define AARCH64_MBOX3_INTSRC 0x0080
#define AARCH64_GPU_INTSRC 0x0100
#define AARCH64_PMU_INTSRC 0x0200
/* Mailbox write-set registers (write only)
* */
#define AARCH64_CORE0_MBOX0_SETREG *((uint32_t *) 0x40000080)
#define AARCH64_CORE0_MBOX1_SETREG *((uint32_t *) 0x40000084)
#define AARCH64_CORE0_MBOX2_SETREG *((uint32_t *) 0x40000088)
#define AARCH64_CORE0_MBOX3_SETREG *((uint32_t *) 0x4000008C)
#define AARCH64_CORE1_MBOX0_SETREG *((uint32_t *) 0x40000090)
#define AARCH64_CORE1_MBOX1_SETREG *((uint32_t *) 0x40000094)
#define AARCH64_CORE1_MBOX2_SETREG *((uint32_t *) 0x40000098)
#define AARCH64_CORE1_MBOX3_SETREG *((uint32_t *) 0x4000009C)
#define AARCH64_CORE2_MBOX0_SETREG *((uint32_t *) 0x400000A0)
#define AARCH64_CORE2_MBOX1_SETREG *((uint32_t *) 0x400000A4)
#define AARCH64_CORE2_MBOX2_SETREG *((uint32_t *) 0x400000A8)
#define AARCH64_CORE2_MBOX3_SETREG *((uint32_t *) 0x400000AC)
#define AARCH64_CORE3_MBOX0_SETREG *((uint32_t *) 0x400000B0)
#define AARCH64_CORE3_MBOX1_SETREG *((uint32_t *) 0x400000B4)
#define AARCH64_CORE3_MBOX2_SETREG *((uint32_t *) 0x400000B8)
#define AARCH64_CORE3_MBOX3_SETREG *((uint32_t *) 0x400000BC)
/* Mailbox write-clear registers (Read & Write)
* */
#define AARCH64_CORE0_MBOX0_RDCLREG *((uint32_t *) 0x400000C0)
#define AARCH64_CORE0_MBOX1_RDCLREG *((uint32_t *) 0x400000C4)
#define AARCH64_CORE0_MBOX2_RDCLREG *((uint32_t *) 0x400000C8)
#define AARCH64_CORE0_MBOX3_RDCLREG *((uint32_t *) 0x400000CC)
#define AARCH64_CORE1_MBOX0_RDCLREG *((uint32_t *) 0x400000D0)
#define AARCH64_CORE1_MBOX1_RDCLREG *((uint32_t *) 0x400000D4)
#define AARCH64_CORE1_MBOX2_RDCLREG *((uint32_t *) 0x400000D8)
#define AARCH64_CORE1_MBOX3_RDCLREG *((uint32_t *) 0x400000DC)
#define AARCH64_CORE2_MBOX0_RDCLREG *((uint32_t *) 0x400000E0)
#define AARCH64_CORE2_MBOX1_RDCLREG *((uint32_t *) 0x400000E4)
#define AARCH64_CORE2_MBOX2_RDCLREG *((uint32_t *) 0x400000E8)
#define AARCH64_CORE2_MBOX3_RDCLREG *((uint32_t *) 0x400000EC)
#define AARCH64_CORE3_MBOX0_RDCLREG *((uint32_t *) 0x400000F0)
#define AARCH64_CORE3_MBOX1_RDCLREG *((uint32_t *) 0x400000F4)
#define AARCH64_CORE3_MBOX2_RDCLREG *((uint32_t *) 0x400000F8)
#define AARCH64_CORE3_MBOX3_RDCLREG *((uint32_t *) 0x400000FC)
/* 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 */
+7
View File
@@ -0,0 +1,7 @@
# Target architecture (AARCH64)
CONFIG_ARCH = AARCH64
# Use ARM local timer (1/0)
CONFIG_ARM_TIMER = 0
-include config.dev.mk
+86
View File
@@ -0,0 +1,86 @@
/******************************************************************************
*
* 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
/* Reserve 4 MB for the Kernel and its stack */
#define MEMORY_LOW (4 * 1024 * 1024)
#define MEMORY_HIGH PERIPHERAL_BASE
#define MEMORY_SIZE (MEMORY_HIGH - MEMORY_LOW)
#define MEMORY_PAGE_SIZE (4 * 1024)
#define MEMORY_PAGE_COUNT (MEMORY_SIZE / MEMORY_PAGE_SIZE)
/* 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)
#define LOCAL_TIMER_IRQ 0
/* 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 */
+69
View File
@@ -0,0 +1,69 @@
/******************************************************************************
*
* 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 <drivers/soc/bcm2837/bcm2837.h>
#include <leos/log.h>
#include "timer.h"
#if CONFIG_ARM_TIMER == 1
const unsigned int m_interval = 500000000;
#else
const unsigned int m_interval = 200000;
#endif
unsigned int m_current = 0;
#define TIMER_ENABLE ((1 << 31) | (1 << 29) | (1 << 28))
#define TIMER_RELOAD 5000000
void
Timer_init(void)
{
#if CONFIG_ARM_TIMER == 1
/* Route local timer to a core0 */
AARCH64_LOCAL_INT_ROUTING &= ~0x03;
/* Set up timer status control register */
AARCH64_LOCAL_TIMER_STATCTL = TIMER_ENABLE | TIMER_RELOAD;
/* clear interrupt flag and reload timer */
AARCH64_LOCAL_TIMER_RECLR |= (1 << 31) | (1 << 30);
/* Set timer interrupt control register */
AARCH64_CORE0_TIMER_IRQCTL = (1 << 1); /* nCNTPNSIR1 - Non Secure*/
#else
m_current = AArch64_getReg32(TIMER_CLO);
m_current += m_interval;
AArch64_setReg32(TIMER_C1, m_current);
#endif
}
void
Timer_incFromISR(void)
{
m_current += m_interval;
#if CONFIG_ARM_TIMER == 1
/* clear interrupt flag and reload timer */
// AARCH64_LOCAL_TIMER_STATCTL |= TIMER_RELOAD;
AARCH64_LOCAL_TIMER_RECLR |= (1 << 31) | (1 << 30);
#else
AArch64_setReg32(TIMER_C1, m_current);
AArch64_setReg32(TIMER_CS, TIMER_CS_M1);
#endif
}
uint32_t
Timer_getTicks(void)
{
return m_current;
}
+9 -12
View File
@@ -6,28 +6,25 @@
******************************************************************************/
/**
* @file uart.h
* @file timer.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 TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F
#define TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F
#define UART_BASE 0x09000000
#include <leos/types.h>
void
uart_init(void);
Timer_init(void);
void
uart_putc(unsigned char c);
Timer_incFromISR(void);
uint32_t
Timer_getTicks(void);
void
uart_puts(const unsigned char *s);
#endif /* !UART_H */
#endif /* !TIMER_H */
+47
View File
@@ -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_MINI
#endif
#if UART_DEFAULT == UART_MINI
#define UART_init(...) UARTMini_init(__VA_ARGS__)
#define UART_get(...) UARTMini_get(__VA_ARGS__)
#define UART_put(...) UARTMini_put(__VA_ARGS__)
#elif UART_DEFAULT == UART_QEMU
#define UART_init(...)
#define UART_get(...)
#define UART_put(...) UARTQEMU_put(__VA_ARGS__)
#else
#warning "Unsupported UART"
#endif
#endif /* !UART_H */
+84
View File
@@ -0,0 +1,84 @@
/******************************************************************************
*
* Copyright (c) 2017-2019 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file UARTMini.c
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#include <aarch64/aarch64.h>
#include <drivers/soc/bcm2837/bcm2837.h>
#include "uart_mini.h"
int
UARTMini_init(void)
{
unsigned int sel;
/* Enable UART Mini and its registers*/
AArch64_setReg32(AUX_ENABLES, 1);
/* Disable TX and RX interrupts */
AArch64_setReg32(AUX_MU_IER_REG, 0);
/* Disable auto flow control, TX and RX */
AArch64_setReg32(AUX_MU_CNTL_REG, 0);
/* Set 8bit mode */
AArch64_setReg32(AUX_MU_LCR_REG, 3);
/* Set RTS line HIGH */
AArch64_setReg32(AUX_MU_MCR_REG, 0);
/* Set baud rate 115200 */
AArch64_setReg32(AUX_MU_IER_REG, 0);
AArch64_setReg32(AUX_MU_IIR_REG, 0xC6);
AArch64_setReg32(AUX_MU_BAUD_REG, 270);
sel = AArch64_getReg32(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_setReg32(GPFSEL1, sel);
AArch64_setReg32(GPPUD, 0);
AArch64_idle(150);
AArch64_setReg32(GPPUDCLK0, (1 << 14) | (1 << 15));
AArch64_idle(150);
AArch64_setReg32(GPPUDCLK0, 0);
/* Enable TX and RX */
AArch64_setReg32(AUX_MU_CNTL_REG, 3);
return 0;
}
int
UARTMini_put(char c)
{
while (1) {
if (AArch64_getReg32(AUX_MU_LSR_REG) & 0x20)
break;
}
AArch64_setReg32(AUX_MU_IO_REG, c);
return 0;
}
int
UARTMini_get(char *pc)
{
while (1) {
if (AArch64_getReg32(AUX_MU_LSR_REG) & 0x01)
break;
}
*pc = AArch64_getReg32(AUX_MU_IO_REG) & 0xFF;
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
/******************************************************************************
*
* Copyright (c) 2017-2019 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file UARTMini.h
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#ifndef UART_MINI_H_B0DFA3CF_5B4F_4EB0_B393_391C0069A04F
#define UART_MINI_H_B0DFA3CF_5B4F_4EB0_B393_391C0069A04F
int
UARTMini_init(void);
int
UARTMini_put(char c);
int
UARTMini_get(char *pc);
#endif /* !UART_MINI_H */
+6 -19
View File
@@ -13,29 +13,16 @@
* @see https://lowenware.com/
*/
#include "uart.h"
#include "uart_qemu.h"
volatile unsigned int *UART0 = (unsigned int *)UART_BASE;
#define UARTQEMU_BASE 0x09000000;
volatile unsigned int *UART0 = (unsigned int *)UARTQEMU_BASE;
void
uart_init(void)
{
}
void
uart_putc(unsigned char c)
int
UARTQEMU_put(unsigned char c)
{
*UART0 = (unsigned int) c;
return 0;
}
void
uart_puts(const unsigned char *s)
{
while(*s) {
*UART0 = (unsigned int) *(s++);
}
}
+6 -18
View File
@@ -6,29 +6,17 @@
******************************************************************************/
/**
* @file main.c
* @file uart_qemu.h
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#include "uart.h"
#ifndef UART_QEMU_H_EDB39A0E_9BED_4A47_91CD_E804A9B4E8ED
#define UART_QEMU_H_EDB39A0E_9BED_4A47_91CD_E804A9B4E8ED
int
UARTQEMU_put(unsigned char c);
void
k_main(void);
void
k_main(void)
{
uart_init();
uart_puts((unsigned char *) "Lowe OS\n");
for (;;) {
__asm__("WFE");
}
}
#endif /* !UART_QEMU_H */
+23
View File
@@ -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 Arch_init(...) AArch64_init(__VA_ARGS__)
#endif /* !ARCH_H */
+83
View File
@@ -0,0 +1,83 @@
/******************************************************************************
*
* 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 <drivers/soc/bcm2837/bcm2837.h>
#include <drivers/timer/timer.h>
#include "log.h"
#include "task.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"
};
static void
IRQ_onTimerInterrupt(void)
{
Timer_incFromISR();
Task_scheduleFromISR();
}
void
IRQ_init()
{
AArch64_setReg32(ENABLE_IRQS_1, SYSTEM_TIMER_IRQ_1);
}
void
IRQ_onInterrupt(void)
{
unsigned int irq = AArch64_getReg32(IRQ_PENDING_1);
switch(irq) {
#if CONFIG_ARM_TIMER == 1
case LOCAL_TIMER_IRQ:
#endif
case SYSTEM_TIMER_IRQ_1:
return IRQ_onTimerInterrupt();
default:
Log_putS("Unhandled irq: ");
Log_putU(irq, 16);
Log_putS("\n");
}
}
void
IRQ_fallback(int type, unsigned long esr, unsigned long address)
{
Log_putS(m_types[type]);
Log_putS(" -> ESR: ");
Log_putU(esr, 16);
Log_putS(", address: ");
Log_putU(address, 16);
Log_putS("\r\n");
}
+34
View File
@@ -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
IRQ_init(void);
void
IRQ_onInterrupt(void);
void
IRQ_fallback(int type, unsigned long esr, unsigned long address);
#define IRQ_enable(...) AArch64_enableIRQ(__VA_ARGS__)
#define IRQ_disable(...) AArch64_disableIRQ(__VA_ARGS__)
#endif /* !IRQ_H */
+77
View File
@@ -0,0 +1,77 @@
/******************************************************************************
*
* 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 <leos/irq.h>
#include <leos/leos.h>
#include <leos/log.h>
#include <leos/memory.h>
#include <leos/task.h>
#include <drivers/timer/timer.h>
void
Leos_demoTask1(void *arg);
void
Leos_demoTask2(void *arg);
void
Leos_run(void)
{
Log_init();
Log_putS("Starting LEOS (EL");
Log_putI(AArch64_getEL(), 10);
Log_putS(")\r\n");
AArch64_init();
IRQ_init();
Timer_init();
Memory_init();
Task_initSheduler();
IRQ_enable();
if (Task_create(Leos_demoTask1, "T1") == -1)
Log_putS("Task 1 was not created\r\n");
if (Task_create(Leos_demoTask2, "T2") == -1)
Log_putS("Task 2 was not created\r\n");
for (;;) {
Log_putS("I");
Task_yield();
}
}
void
Leos_demoTask2(void *arg)
{
for (;;) {
Log_putS("B");
Task_yield();
}
}
void
Leos_demoTask1(void *arg)
{
for (;;) {
Log_putS("A");
Task_yield();
}
}
+22
View File
@@ -0,0 +1,22 @@
/******************************************************************************
*
* Copyright (c) 2017-2020 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file leos.h
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#ifndef LEOS_H_7087F58B_BDEB_433B_A013_5B5F854922AF
#define LEOS_H_7087F58B_BDEB_433B_A013_5B5F854922AF
void
Leos_run(void);
#endif /* !LEOS_H */
+82
View File
@@ -0,0 +1,82 @@
/******************************************************************************
*
* 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 <drivers/uart/uart.h>
#include "log.h"
void
Log_init(void)
{
UART_init();
}
int
Log_putS(const char *string)
{
char c;
const char *p = string;
while((c = *p) != 0) {
if (UART_put(c))
return -1;
p++;
}
return (int)(p - string);
}
int
Log_putI(int64_t value, uint8_t base)
{
int result;
if (value < 0) {
if (UART_put('-'))
return -1;
value = -value;
result = 1;
} else {
result = 0;
}
result += Log_putU(value, base);
return (result) ? result : -1;
}
int
Log_putU(uint64_t value, uint8_t base)
{
int i = 0, result;
char buffer[64];
if (!value) {
return (UART_put('0')) ? -1 : 1;
}
do {
uint64_t r;
if (!(i < (sizeof(buffer) / sizeof(buffer[0]))))
return -1;
r = value % base;
buffer[i++] = (r < 0x0A) ? '0' + r : 'A' + r - 0x0A;
value /= base;
} while (value);
result = i;
while (i--) {
if (UART_put(buffer[i]))
return -1;
}
return result;
}
+33
View File
@@ -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 <leos/types.h>
void
Log_init(void);
int
Log_putS(const char *string);
int
Log_putI(int64_t value, uint8_t base);
int
Log_putU(uint64_t value, uint8_t base);
#endif /* !LOG_H */
+63
View File
@@ -0,0 +1,63 @@
/******************************************************************************
*
* Copyright (c) 2017-2020 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
unsigned
* @file memory.c
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#include <stdlib.h>
#include <aarch64/aarch64.h>
#include <drivers/soc/bcm2837/bcm2837.h>
#include "memory.h"
#include "log.h"
static unsigned long m_map[MEMORY_PAGE_COUNT / sizeof(unsigned long) / 8];
static int m_ix;
void
Memory_init(void)
{
m_ix = 0;
AArch64_memzero(m_map, sizeof(m_map));
}
void *
Memory_getPage(void)
{
int i, j;
unsigned long map;
for (i = m_ix; i < sizeof(m_map) / sizeof(m_map[0]); i++) {
map = m_map[i];
for (j = 0; j < 8 * sizeof(map); j++) {
if (!(map & (1 << j))) {
m_map[i] |= (1 << j);
return (void *) (MEMORY_LOW + (i * sizeof(map) * 8 + j) * MEMORY_PAGE_SIZE);
}
}
m_ix = i;
}
Log_putS("ENOMEM\r\n");
return NULL;
}
void
Memory_freePage(void *p_addr)
{
int i, j, c;
c = ((unsigned long) p_addr) / MEMORY_PAGE_SIZE;
i = c / sizeof(m_map[0]);
j = c % sizeof(m_map[0]);
m_map[i] &= ~(1 << j);
}
+30
View File
@@ -0,0 +1,30 @@
/******************************************************************************
*
* Copyright (c) 2017-2020 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file memory.h
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#ifndef MEMORY_H_C583E24E_55B0_49EF_99C9_5A36B04468AC
#define MEMORY_H_C583E24E_55B0_49EF_99C9_5A36B04468AC
void
Memory_init(void);
void *
Memory_getPage(void);
void
Memory_freePage(void *p_addr);
#endif /* !MEMORY_H */
+92
View File
@@ -0,0 +1,92 @@
/******************************************************************************
*
* Copyright (c) 2017-2020 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file scheduler.c
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#include "scheduler.h"
static struct KTask *m_first = NULL, *m_last, *m_current = NULL;
static KPid m_pid = 0;
static void
_disable_preempt(void)
{
m_current->preempt++;
}
static void
_enable_preempt(void)
{
m_current->preempt--;
}
static void
_switch(void)
{
struct KTask *i, *next;
long p = 0;
_disable_preempt();
for (;;) {
/* check urgent tasks */
for (i = m_first; i != NULL; i = i->next) {
if (!i->state && i->counter > p) {
p = i->counter;
next = i;
}
i = i->next;
}
if (p) {
break;
}
i = m_first;
for (i = m_first; i != NULL; i = i->next) {
i->counter = i->priority;
}
}
aarch64_switch(m_current, next);
_enable_preempt();
}
void
scheduler_init(void)
{
}
KPid
scheduler_add(struct KTask *task)
{
KPid result = ++m_pid;
task->pid = result;
task->prev = m_last;
m_last->next = task;
return result;
}
void
scheduler_switch(void)
{
}
void
scheduler_switch_from_isr(void)
{
}
+38
View File
@@ -0,0 +1,38 @@
/******************************************************************************
*
* Copyright (c) 2017-2019 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file scheduler.h
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#ifndef SCHEDULER_H_AE39DBC8_E643_4857_B319_9732123728A4
#define SCHEDULER_H_AE39DBC8_E643_4857_B319_9732123728A4
void
scheduler_init(void);
void
scheduler_run(void);
void
scheduler_switch(void);
KPid
scheduler_add(struct KTask *task);
KRetCode
scheduler_remove(struct KTask *task);
KRetCode
scheduler_remove_pid(KPid pid);
#endif /* !SCHEDULER_H */
+262
View File
@@ -0,0 +1,262 @@
/******************************************************************************
*
* Copyright (c) 2017-2020 by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file task.c
* @author Ilja Kartašov <ik@lowenware.com>
* @brief
*
* @see https://lowenware.com/
*/
#include <stdlib.h>
#include <aarch64/aarch64.h>
#include <drivers/soc/bcm2837/bcm2837.h>
#include <drivers/timer/timer.h>
#include "memory.h"
#include "log.h"
#include "task.h"
#define TASK_STATE_RUNNING 0
#define TASK_STATE_HALFCYCLE (1 << 8)
#ifndef CONFIG_IDLE_TASK_STACK_SIZE
#define CONFIG_IDLE_TASK_STACK_SIZE 0x4000
#endif
struct Task {
void *sp;
void *stackStart;
uint32_t pid;
uint32_t stackSize;
uint32_t lock;
uint32_t counter;
uint32_t cycles;
int32_t priority;
uint32_t state;
char name[CONFIG_TASK_MAX_NAME_LEN + 1];
struct Task *next;
};
struct __attribute__((packed)) TaskContext {
uint64_t x[31];
uint64_t elr_el1;
uint64_t spsr_el1;
};
static struct Task *m_currentTask, *m_lastTask, m_idleTask;
static uint32_t m_pid = 1;
static struct Task *
scheduleNext(void)
{
struct Task *i, *next = NULL;
int32_t priority = -1;
if (m_currentTask->counter)
m_currentTask->counter--;
for (;;) {
/* check urgent tasks */
for (i = &m_idleTask; i != NULL; i = i->next) {
if (i->state != TASK_STATE_RUNNING)
continue;
if (i->priority > priority && i->counter) {
priority = i->priority;
next = i;
}
}
if (next) {
break;
}
for (i = &m_idleTask; i != NULL; i = i->next) {
i->counter = i->cycles;
}
}
return next;
}
void
Task_initSheduler(void)
{
struct Task *idleTask = &m_idleTask;
m_pid = 1;
m_idleTask.sp = NULL;
m_idleTask.stackStart = NULL;
m_idleTask.stackSize = CONFIG_IDLE_TASK_STACK_SIZE;
m_idleTask.pid = 1;
m_idleTask.lock = 1;
m_idleTask.counter = 1;
m_idleTask.cycles = 1;
m_idleTask.priority = 0;
m_idleTask.state = TASK_STATE_RUNNING;
m_idleTask.name[0] = 'I';
m_idleTask.name[1] = 'D';
m_idleTask.name[2] = 'L';
m_idleTask.name[3] = 'E';
m_idleTask.name[4] = 0;
m_idleTask.next = NULL;
m_currentTask = idleTask;
m_lastTask = idleTask;
Task_unlockScheduler();
}
PID
Task_create(TaskCallback callback, void *arg)
{
struct TaskContext *ctx;
struct Task *task = Memory_getPage();
if (!task)
return -1;
Log_putS("Task @0x");
Log_putU((uint64_t) task, 16);
Log_putS(" - ");
Log_putU(((uint64_t) task) + MEMORY_PAGE_SIZE, 16);
Log_putS("\r\n");
task->sp = (void *)task + MEMORY_PAGE_SIZE - 272;
task->stackStart = task->sp;
task->stackSize = MEMORY_PAGE_SIZE - sizeof(*task);
task->lock = 1;
task->counter = 1;
task->cycles = 1;
task->pid = ++m_pid;
task->priority = 0;
task->state = TASK_STATE_RUNNING;
task->name[0] = 'N';
task->name[1] = 'O';
task->name[2] = 'N';
task->name[3] = 'E';
task->name[4] = 0;
task->next = 0;
ctx = (struct TaskContext *) task->sp;
ctx->x[20] = (uint64_t) arg;
ctx->x[21] = (uint64_t) callback;
ctx->x[30] = (uint64_t) AArch64_startTask;
ctx->elr_el1 = (uint64_t) AArch64_startTask;
ctx->spsr_el1 = AArch64_getPState();
Task_lockScheduler();
m_lastTask->next = task;
m_lastTask = task;
Task_unlockScheduler();
return task->pid;
}
void
Task_yield(void)
{
#if 1
uint64_t ticks = Timer_getTicks();
Task_lockScheduler();
Log_putS("^");
m_currentTask->counter = 0;
Task_unlockScheduler();
__asm__("WFE");
while (ticks == Timer_getTicks());
#else
/* Task yield should be solved differently */
struct Task *next, *prev;
Task_lockScheduler();
Log_putS("^");
prev = m_currentTask;
prev->counter = 0;
next = scheduleNext();
if (next != prev) {
next->state |= TASK_STATE_HALFCYCLE;
m_currentTask = next;
Task_unlockScheduler();
AArch64_switchContext(prev, next);
/* `next` tasks never exits here, but in AArch64_startTask,
* that is why there is an own Task_unlockScheduler() call
* */
} else {
// __asm__("WFE");
}
Task_unlockScheduler();
#endif
}
void
Task_lockScheduler(void)
{
m_currentTask->lock++;
}
void
Task_unlockScheduler(void)
{
if (m_currentTask->lock)
m_currentTask->lock--;
}
void
Task_scheduleFromISR(void)
{
if (!m_currentTask->lock) {
struct Task *next;
if (m_currentTask->state & TASK_STATE_HALFCYCLE) {
m_currentTask->state &= ~TASK_STATE_HALFCYCLE;
return;
}
Log_putS("!");
Task_lockScheduler();
next = scheduleNext();
if (next != m_currentTask) {
m_currentTask = next;
}
/* unlock call could be moved to aarch64.S interrupt handler in case of
* issue
* */
Task_unlockScheduler();
}
}
void *
Task_getStackPointer(void)
{
/*
Log_putS("gSP:");
Log_putU((uint64_t)m_currentTask->sp, 16);
Log_putS("\r\n");
*/
return m_currentTask->sp;
}
void
Task_setStackPointer(void *sp)
{
/*
Log_putS("sSP:");
Log_putU((uint64_t)sp, 16);
Log_putS("\r\n");
*/
m_currentTask->sp = sp;
}
+51
View File
@@ -0,0 +1,51 @@
/******************************************************************************
*
* 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 <leos/types.h>
#ifndef CONFIG_TASK_MAX_NAME_LEN
#define CONFIG_TASK_MAX_NAME_LEN 16
#endif
typedef void (*TaskCallback)(void *p_ctx);
void
Task_initSheduler(void);
PID
Task_create(TaskCallback callback, void *arg);
void
Task_yield(void);
void
Task_lockScheduler(void);
void
Task_unlockScheduler(void);
void
Task_scheduleFromISR(void);
void *
Task_getStackPointer(void);
void
Task_setStackPointer(void *sp);
#endif /* !TASK_H */
+25
View File
@@ -0,0 +1,25 @@
/******************************************************************************
*
* 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
#include <stdbool.h>
#include <stdint.h>
typedef int RetCode;
typedef unsigned int PID;
#endif /* !TYPES_H */
-38
View File
@@ -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
View File
@@ -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
// -----------------------------------------------------------------------------