Compare commits
9
Commits
c95e490a21
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21a25ec4e8 | ||
|
|
85b0df56bb | ||
|
|
26f05b04d7 | ||
|
|
a93f257f2e | ||
|
|
a0c215e954 | ||
|
|
6c4dba0929 | ||
|
|
417106b967 | ||
|
|
08ffb6ee94 | ||
|
|
8718f035a5 |
@@ -1 +1 @@
|
|||||||
Elias Löwe <elias@lowenware.com>
|
Ilja Kartaschoff <ik@lowenware.com>
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Lion's Share License -> LSL
|
|
||||||
# Löwenware Software Distribution -> LSD
|
|
||||||
+39
@@ -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.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
ROOT = ./
|
||||||
|
|
||||||
|
include ${ROOT}Makevars.mk
|
||||||
|
|
||||||
|
# Rules
|
||||||
|
#
|
||||||
|
all: kernel
|
||||||
|
|
||||||
|
$(BUILD_DIR)kernel:
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
.PHONY: clean run debug kernel
|
||||||
|
|
||||||
|
kernel: $(BUILD_DIR)kernel
|
||||||
|
cd kernel && BUILD_DIR=../$(BUILD_DIR)kernel/ make
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -Rf ./$(BUILD_DIR)*
|
||||||
|
|
||||||
|
run: kernel
|
||||||
|
$(AARCH64_QEMU)
|
||||||
|
|
||||||
|
debug: kernel
|
||||||
|
$(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
@@ -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
|
||||||
@@ -1,3 +1,88 @@
|
|||||||
# Löwe OS
|
# LeOS
|
||||||
Operating System for ARMv8 (aarch64) architecture.
|
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
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
arm_control=0x200
|
||||||
|
kernel_old=1
|
||||||
|
disable_commandline_tags=1
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
```
|
||||||
@@ -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
|
||||||
@@ -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 $@
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -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 */
|
||||||
@@ -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 = . ;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -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,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 */
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
ASM=clang
|
|
||||||
TARGET=aarch64-none-elf
|
|
||||||
CPU=cortex-a57
|
|
||||||
LD=ld.lld
|
|
||||||
OBJCOPY=objcopy --target elf64-littleaarch64
|
|
||||||
|
|
||||||
all: build/core.bin build/core.elf
|
|
||||||
|
|
||||||
# compilation -----------------------------------------------------------------
|
|
||||||
|
|
||||||
build/core.o: core/core.s
|
|
||||||
$(ASM) -c -triple --target=$(TARGET) -mcpu=$(CPU) -O0 -g $< -o $@
|
|
||||||
|
|
||||||
build/uart.o: core/uart.s
|
|
||||||
$(ASM) -c --target=$(TARGET) -mcpu=$(CPU) -O0 -g $< -o $@
|
|
||||||
|
|
||||||
# ELF -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
build/core.elf: build/core.o build/uart.o
|
|
||||||
$(LD) -Tcore/core.ld $^ -o $@
|
|
||||||
|
|
||||||
# BIN -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
build/core.bin: build/core.elf
|
|
||||||
$(OBJCOPY) -O binary $< $@
|
|
||||||
|
|
||||||
build/core.sym: build/core.elf
|
|
||||||
$(OBJCOPY) --only-keep-debug $< $@
|
|
||||||
$(OBJCOPY) --strip-debug build/core.elf
|
|
||||||
|
|
||||||
# Clean -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f build/*
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
ENTRY(_core_init)
|
|
||||||
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x40000000;
|
|
||||||
.text : { *(.text) }
|
|
||||||
.data : { *(.text) }
|
|
||||||
.bss : { *(.bss COMMON) }
|
|
||||||
. = ALIGN(10);
|
|
||||||
. = . + 0x1000;
|
|
||||||
stack_ptr = . ;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Target architecture (AARCH64)
|
||||||
|
CONFIG_ARCH = AARCH64
|
||||||
|
|
||||||
|
# Use ARM local timer (1/0)
|
||||||
|
CONFIG_ARM_TIMER = 0
|
||||||
|
|
||||||
|
-include config.dev.mk
|
||||||
@@ -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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2019 by Löwenware Ltd
|
||||||
|
* Please, refer LICENSE file for legal information
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file timer.h
|
||||||
|
* @author Ilja Kartašov <ik@lowenware.com>
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @see https://lowenware.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F
|
||||||
|
#define TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F
|
||||||
|
|
||||||
|
#include <leos/types.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
Timer_init(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
Timer_incFromISR(void);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
Timer_getTicks(void);
|
||||||
|
|
||||||
|
#endif /* !TIMER_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_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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2019 by Löwenware Ltd
|
||||||
|
* Please, refer LICENSE file for legal information
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file uart.c
|
||||||
|
* @author Ilja Kartašov <ik@lowenware.com>
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @see https://lowenware.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uart_qemu.h"
|
||||||
|
|
||||||
|
#define UARTQEMU_BASE 0x09000000;
|
||||||
|
|
||||||
|
volatile unsigned int *UART0 = (unsigned int *)UARTQEMU_BASE;
|
||||||
|
|
||||||
|
int
|
||||||
|
UARTQEMU_put(unsigned char c)
|
||||||
|
{
|
||||||
|
*UART0 = (unsigned int) c;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
|
UARTQEMU_put(unsigned char c);
|
||||||
|
|
||||||
|
#endif /* !UART_QEMU_H */
|
||||||
@@ -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 */
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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 */
|
||||||
Reference in New Issue
Block a user