Added part13-interrupts, albeit without a README.md for now

This commit is contained in:
Adam Greenwood-Byrne 2021-10-12 17:19:47 +01:00
parent 1393191895
commit ecce209c5e
18 changed files with 1453 additions and 0 deletions

View file

@ -0,0 +1,20 @@
CFILES = $(wildcard *.c lib/*.c kernel/*.c)
SFILES = $(wildcard boot/*.S lib/*.S kernel/*.S)
OFILES = $(CFILES:.c=.o) $(SFILES:.S=.o)
LLVMPATH = /opt/homebrew/opt/llvm/bin
CLANGFLAGS = -Wall -O2 -ffreestanding -nostdlib -mcpu=cortex-a72+nosimd
all: clean kernel8.img
%.o: %.c
$(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@
%.o: %.S
$(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@
kernel8.img: $(OFILES)
$(LLVMPATH)/ld.lld -m aarch64elf -nostdlib $(OFILES) -T boot/link.ld -o kernel8.elf
$(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img
clean:
/bin/rm kernel8.elf */*.o *.img > /dev/null 2> /dev/null || true

View file

@ -0,0 +1,114 @@
#include "sysregs.h"
#define LOCAL_CONTROL 0xff800000
#define LOCAL_PRESCALER 0xff800008
#define OSC_FREQ 54000000
#define MAIN_STACK 0x400000
.section ".text.boot" // Make sure the linker puts this at the start of the kernel image
.global _start // Execution starts here
_start:
ldr x0, =LOCAL_CONTROL // Sort out the timer
str wzr, [x0]
mov w1, 0x80000000
str w1, [x0, #(LOCAL_PRESCALER - LOCAL_CONTROL)]
ldr x0, =OSC_FREQ
msr cntfrq_el0, x0
msr cntvoff_el2, xzr
// Check processor ID is zero (executing on main core), else hang
mrs x1, mpidr_el1
and x1, x1, #3
cbz x1, 2f
// We're not on the main core, so hang in an infinite wait loop
adr x5, spin_cpu0
1: wfe
ldr x4, [x5, x1, lsl #3]
cbz x4, 1b
ldr x2, =__stack_start // Get ourselves a fresh stack - location depends on CPU core asking
lsl x1, x1, #9 // Multiply core_number by 512
add x3, x2, x1 // Add to the address
mov sp, x3
mov x0, #0
mov x1, #0
mov x2, #0
mov x3, #0
br x4
b 1b
2: // We're on the main core!
// First enable the FPU
mov x0, #0x33ff
msr cptr_el3, x0 // Disable coprocessor traps to EL3
mov x0, #3 << 20
msr cpacr_el1, x0 // Enable FP/SIMD at EL1
// Now get ready to switch from EL3 down to EL1
ldr x0, =SCTLR_VALUE_MMU_DISABLED
msr sctlr_el1, x0
ldr x0, =HCR_VALUE
msr hcr_el2, x0
ldr x0, =SCR_VALUE
msr scr_el3, x0
ldr x0, =SPSR_VALUE
msr spsr_el3, x0
adr x0, el1_entry
msr elr_el3, x0
eret
el1_entry:
// We're in EL1
// Clean the BSS section
ldr x1, =__bss_start // Start address
ldr w2, =__bss_size // Size of the section
3: cbz w2, 4f // Quit loop if zero
str xzr, [x1], #8
sub w2, w2, #1
cbnz w2, 3b // Loop if non-zero
// Set stack to start somewhere safe
mov sp, #MAIN_STACK
// Jump to our main() routine in C (make sure it doesn't return)
4: bl main
// In case it does return, halt the master core too
b 1b
.ltorg
.org 0x100
.globl spin_cpu0
spin_cpu0:
.quad 0
.org 0x108
.globl spin_cpu1
spin_cpu1:
.quad 0
.org 0x110
.globl spin_cpu2
spin_cpu2:
.quad 0
.org 0x118
.globl spin_cpu3
spin_cpu3:
.quad 0
.globl get_el
get_el:
mrs x0, CurrentEL
lsr x0, x0, #2
ret

View file

@ -0,0 +1,35 @@
SECTIONS
{
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
__bss_size = (__bss_end - __bss_start)>>3;
}
.cpu1Stack :
{
. = ALIGN(16);
__stack_start = .;
. = . + 512;
__cpu1_stack = .;
}
.cpu2Stack :
{
. = . + 512;
__cpu2_stack = .;
}
.cpu3Stack :
{
. = . + 512;
__cpu3_stack = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}

View file

@ -0,0 +1,44 @@
#ifndef _SYSREGS_H
#define _SYSREGS_H
// ***************************************
// SCTLR_EL1, System Control Register (EL1), 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_I_CACHE_ENABLED (1 << 12)
#define SCTLR_D_CACHE_ENABLED (1 << 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_ENABLED | SCTLR_D_CACHE_ENABLED | SCTLR_MMU_DISABLED)
// ***************************************
// HCR_EL2, Hypervisor Configuration Register (EL2), Page 2487 of AArch64-Reference-Manual.
// ***************************************
#define HCR_RW (1 << 31)
#define HCR_VALUE HCR_RW
// ***************************************
// SCR_EL3, Secure Configuration Register (EL3), 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)
// ***************************************
// SPSR_EL3, Saved Program Status Register (EL3) 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)
#endif

View file

@ -0,0 +1,13 @@
void fb_init();
void drawPixel(int x, int y, unsigned char attr);
void drawChar(unsigned char ch, int x, int y, unsigned char attr, int zoom);
void drawString(int x, int y, char *s, unsigned char attr, int zoom);
void drawRect(int x1, int y1, int x2, int y2, unsigned char attr, int fill);
void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill);
void drawLine(int x1, int y1, int x2, int y2, unsigned char attr);
void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr);
void wait_msec(unsigned int n);
void debugstr(char *str);
void debugcrlf(void);
void debugch(unsigned char b);
void debughex(unsigned int d);

View file

@ -0,0 +1,17 @@
#define PERIPHERAL_BASE 0xFE000000
#define LEGACY_BASE 0x7E000000
#define SAFE_ADDRESS 0x00400000 // Somewhere safe to store a lot of data
void uart_init();
void uart_writeText(char *buffer);
void uart_loadOutputFifo();
unsigned char uart_readByte();
unsigned int uart_isReadByteReady();
void uart_writeByteBlockingActual(unsigned char ch);
void uart_update();
void mmio_write(long reg, unsigned int val);
unsigned int mmio_read(long reg);
void gpio_useAsAlt0(unsigned int pin_number);
void gpio_useAsAlt3(unsigned int pin_number);
void uart_hex(unsigned int d);
void uart_byte(unsigned char b);

View file

@ -0,0 +1,34 @@
extern volatile unsigned int mbox[36];
enum {
MBOX_REQUEST = 0
};
enum {
MBOX_CH_POWER = 0,
MBOX_CH_FB = 1,
MBOX_CH_VUART = 2,
MBOX_CH_VCHIQ = 3,
MBOX_CH_LEDS = 4,
MBOX_CH_BTNS = 5,
MBOX_CH_TOUCH = 6,
MBOX_CH_COUNT = 7,
MBOX_CH_PROP = 8 // Request from ARM for response by VideoCore
};
enum {
MBOX_TAG_SETPOWER = 0x28001,
MBOX_TAG_SETCLKRATE = 0x38002,
MBOX_TAG_SETPHYWH = 0x48003,
MBOX_TAG_SETVIRTWH = 0x48004,
MBOX_TAG_SETVIRTOFF = 0x48009,
MBOX_TAG_SETDEPTH = 0x48005,
MBOX_TAG_SETPXLORDR = 0x48006,
MBOX_TAG_GETFB = 0x40001,
MBOX_TAG_GETPITCH = 0x40008,
MBOX_TAG_LAST = 0
};
unsigned int mbox_call(unsigned char ch);

View file

@ -0,0 +1,11 @@
extern unsigned int spin_cpu0;
extern unsigned int spin_cpu1;
extern unsigned int spin_cpu2;
extern unsigned int spin_cpu3;
void start_core1(void (*func)(void));
void start_core2(void (*func)(void));
void start_core3(void (*func)(void));
void clear_core1(void);
void clear_core2(void);
void clear_core3(void);

View file

@ -0,0 +1,253 @@
unsigned int vgapal[] = {
0x000000,
0x0000AA,
0x00AA00,
0x00AAAA,
0xAA0000,
0xAA00AA,
0xAA5500,
0xAAAAAA,
0x555555,
0x5555FF,
0x55FF55,
0x55FFFF,
0xFF5555,
0xFF55FF,
0xFFFF55,
0xFFFFFF
};
enum {
FONT_WIDTH = 8,
FONT_HEIGHT = 8,
FONT_BPG = 8, // Bytes per glyph
FONT_BPL = 1, // Bytes per line
FONT_NUMGLYPHS = 224
};
unsigned char font[FONT_NUMGLYPHS][FONT_BPG] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
{ 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
{ 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
{ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
{ 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
{ 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
{ 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
{ 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
{ 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
{ 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
{ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
{ 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
{ 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
{ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
{ 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
{ 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
{ 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
{ 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
{ 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
{ 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
{ 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
{ 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
{ 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
{ 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
{ 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
{ 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
{ 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
{ 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
{ 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
{ 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
{ 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
{ 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
{ 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
{ 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
{ 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
{ 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
{ 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
{ 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
{ 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
{ 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
{ 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
{ 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
{ 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
{ 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
{ 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
{ 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
{ 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
{ 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
{ 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
{ 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
{ 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
{ 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
{ 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
{ 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
{ 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
{ 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
{ 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
{ 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
{ 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
{ 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
{ 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
{ 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
{ 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
{ 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
{ 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
{ 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
{ 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
{ 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
{ 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
{ 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
{ 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
{ 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
{ 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
{ 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
{ 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
{ 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
{ 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
{ 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
{ 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
{ 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007F
{ 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E}, // U+00C7 (C cedille)
{ 0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FC (u umlaut)
{ 0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E9 (e aigu)
{ 0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00}, // U+00E2 (a circumflex)
{ 0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E4 (a umlaut)
{ 0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E0 (a grave)
{ 0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E5 (a ring)
{ 0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+00E7 (c cedille)
{ 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00}, // U+00EA (e circumflex)
{ 0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00EB (e umlaut)
{ 0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E8 (e grave)
{ 0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EF (i umlaut)
{ 0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EE (i circumflex)
{ 0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EC (i grave)
{ 0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00}, // U+00C4 (A umlaut)
{ 0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00}, // U+00C5 (A ring)
{ 0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C8 (E grave)
{ 0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00}, // U+00E6 (ae)
{ 0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00}, // U+00C6 (AE)
{ 0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F4 (o circumflex)
{ 0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F6 (o umlaut)
{ 0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F2 (o grave)
{ 0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FB (u circumflex)
{ 0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00F9 (u grave)
{ 0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+00FF (y umlaut)
{ 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+00D6 (O umlaut)
{ 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+00DC (U umlaut)
{ 0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18}, // U+00A2 (dollarcents)
{ 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00}, // U+00A3 (pound sterling)
{ 0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C}, // U+00A5 (yen)
{ 0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E}, // U+00A7 (paragraph)
{ 0x70, 0xD8, 0x18, 0x3C, 0x18, 0x18, 0x1B, 0x0E}, // U+0192 (dutch florijn)
{ 0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E1 (a aigu)
{ 0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00ED (i augu)
{ 0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F3 (o aigu)
{ 0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FA (u aigu)
{ 0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00}, // U+00F1 (n ~)
{ 0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00}, // U+00D1 (N ~)
{ 0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00}, // U+00AA (superscript a)
{ 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00BA (superscript 0)
{ 0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00}, // U+00BF (inverted ?)
{ 0x00, 0x00, 0x00, 0x3F, 0x03, 0x03, 0x00, 0x00}, // U+2310 (gun pointing right)
{ 0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00}, // U+00AC (gun pointing left)
{ 0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0}, // U+00BD (1/2)
{ 0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03}, // U+00BC (1/4)
{ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 (inverted !)
{ 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00AB (<<)
{ 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00BB (>>)
{ 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00}, // U+2591 (25% solid)
{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}, // U+2592 (50% solid)
{ 0xFF, 0xAA, 0xFF, 0x55, 0xFF, 0xAA, 0xFF, 0x55}, // U+2593 (75% solid)
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // U+2502 (thin vertical)
{ 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08}, // U+2524 (down L, left L, up L)
{ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2561 (up L, down L, left D)
{ 0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14}, // U+2562 (up D, down D, left L)
{ 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14}, // U+2556 (down D, left L)
{ 0x00, 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2555 (down L, left D)
{ 0x14, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14}, // U+2563 (up D, down D, left D)
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, // U+2551 (double vertical)
{ 0x00, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14}, // U+2557 (down D, left D)
{ 0x14, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00}, // U+255D (up D, left D)
{ 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00}, // U+255C (up D, left L)
{ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00}, // U+255B (up L, left D)
{ 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08}, // U+2510 (down L, left L)
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00}, // U+2514 (up L, right L)
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00}, // U+2534 (up L, right L, left L)
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08}, // U+252C (down L, right L, left L)
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08}, // U+251C (down L, right L, up L)
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, // U+2500 (thin horizontal)
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08}, // U+253C (up L, right L, left L, down L)
{ 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+255E (up L, down L, right D)
{ 0x14, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x14, 0x14}, // U+255F (up D, down D, right L)
{ 0x14, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00}, // U+255A (up D, right D)
{ 0x00, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14}, // U+2554 (down D, right D)
{ 0x14, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00}, // U+2569 (left D, right D, up D)
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14}, // U+2566 (left D, right D, down D)
{ 0x14, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14}, // U+2560 (up D, down D, right D)
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2550 (double horizontal)
{ 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14}, // U+256C (left D, right D, down D, up D)
{ 0x08, 0x08, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2567 (left D, right D, up L)
{ 0x14, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x00, 0x00}, // U+2568 (left L, right L, up D)
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x08, 0x08}, // U+2564 (left D, right D, down L)
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x14, 0x14}, // U+2565 (left L, right L, down D)
{ 0x14, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x00, 0x00}, // U+2559 (up D, right L)
{ 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x00, 0x00}, // U+2558 (up L, right D)
{ 0x00, 0x00, 0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+2552 (down L, right D)
{ 0x00, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x14, 0x14}, // U+2553 (down D, right L)
{ 0x14, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x14, 0x14}, // U+256B (left L, right L, down D, up D)
{ 0x08, 0x08, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0x08}, // U+256A (left D, right D, down L, up L)
{ 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00}, // U+2518 (up L, left L)
{ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08}, // U+250C (down L, right L)
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2588 (solid)
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2584 (bottom half)
{ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, // U+258C (left half)
{ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, // U+2590 (right half)
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, // U+2580 (top half)
};

View file

@ -0,0 +1,45 @@
#include "kernel.h"
const char entry_error_messages[16][32] = {
"SYNC_INVALID_EL1t",
"IRQ_INVALID_EL1t",
"FIQ_INVALID_EL1t",
"ERROR_INVALID_EL1T",
"SYNC_INVALID_EL1h",
"IRQ_INVALID_EL1h",
"FIQ_INVALID_EL1h",
"ERROR_INVALID_EL1h",
"SYNC_INVALID_EL0_64",
"IRQ_INVALID_EL0_64",
"FIQ_INVALID_EL0_64",
"ERROR_INVALID_EL0_64",
"SYNC_INVALID_EL0_32",
"IRQ_INVALID_EL0_32",
"FIQ_INVALID_EL0_32",
"ERROR_INVALID_EL0_32"
};
void enable_interrupt_controller() {
REGS_IRQ->irq0_enable_0 = AUX_IRQ | SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3;
}
void handle_irq() {
unsigned int irq = REGS_IRQ->irq0_pending_0;
while(irq) {
if (irq & SYS_TIMER_IRQ_1) {
irq &= ~SYS_TIMER_IRQ_1;
handle_timer_1();
}
if (irq & SYS_TIMER_IRQ_3) {
irq &= ~SYS_TIMER_IRQ_3;
handle_timer_3();
}
}
}

View file

@ -0,0 +1,154 @@
#define SYNC_INVALID_EL1t 0
#define IRQ_INVALID_EL1t 1
#define FIQ_INVALID_EL1t 2
#define ERROR_INVALID_EL1t 3
#define SYNC_INVALID_EL1h 4
#define IRQ_INVALID_EL1h 5
#define FIQ_INVALID_EL1h 6
#define ERROR_INVALID_EL1h 7
#define SYNC_INVALID_EL0_64 8
#define IRQ_INVALID_EL0_64 9
#define FIQ_INVALID_EL0_64 10
#define ERROR_INVALID_EL0_64 11
#define SYNC_INVALID_EL0_32 12
#define IRQ_INVALID_EL0_32 13
#define FIQ_INVALID_EL0_32 14
#define ERROR_INVALID_EL0_32 15
//stack frame size
#define S_FRAME_SIZE 256
.macro kernel_entry
sub sp, sp, #S_FRAME_SIZE
stp x0, x1, [sp, #16 * 0]
stp x2, x3, [sp, #16 * 1]
stp x4, x5, [sp, #16 * 2]
stp x6, x7, [sp, #16 * 3]
stp x8, x9, [sp, #16 * 4]
stp x10, x11, [sp, #16 * 5]
stp x12, x13, [sp, #16 * 6]
stp x14, x15, [sp, #16 * 7]
stp x16, x17, [sp, #16 * 8]
stp x18, x19, [sp, #16 * 9]
stp x20, x21, [sp, #16 * 10]
stp x22, x23, [sp, #16 * 11]
stp x24, x25, [sp, #16 * 12]
stp x26, x27, [sp, #16 * 13]
stp x28, x29, [sp, #16 * 14]
str x30, [sp, #16 * 15]
.endm
.macro kernel_exit
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
ldp x6, x7, [sp, #16 * 3]
ldp x8, x9, [sp, #16 * 4]
ldp x10, x11, [sp, #16 * 5]
ldp x12, x13, [sp, #16 * 6]
ldp x14, x15, [sp, #16 * 7]
ldp x16, x17, [sp, #16 * 8]
ldp x18, x19, [sp, #16 * 9]
ldp x20, x21, [sp, #16 * 10]
ldp x22, x23, [sp, #16 * 11]
ldp x24, x25, [sp, #16 * 12]
ldp x26, x27, [sp, #16 * 13]
ldp x28, x29, [sp, #16 * 14]
ldr x30, [sp, #16 * 15]
add sp, sp, #S_FRAME_SIZE
eret
.endm
.macro handle_invalid_entry type
kernel_entry
mov x0, #\type
mrs x1, esr_el1
mrs x2, elr_el1
b err_hang
.endm
.macro ventry label
.align 7
b \label
.endm
//Exception vectors table
.align 11
.globl vectors
vectors:
ventry sync_invalid_el1t // Synchronous EL1t
ventry irq_invalid_el1t // IRQ EL1t
ventry fiq_invalid_el1t // FIQ EL1t
ventry error_invalid_el1t // Error EL1t
ventry sync_invalid_el1h // Synchronous EL1h
ventry handle_el1_irq // IRQ EL1h
ventry fiq_invalid_el1h // FIQ EL1h
ventry error_invalid_el1h // Error EL1h
ventry sync_invalid_el0_64 // Synchronous 64-bit EL0
ventry irq_invalid_el0_64 // IRQ 64-bit EL0
ventry fiq_invalid_el0_64 // FIQ 64-bit EL0
ventry error_invalid_el0_64 // Error 64-bit EL0
ventry sync_invalid_el0_32 // Synchronous 32-bit EL0
ventry irq_invalid_el0_32 // IRQ 32-bit EL0
ventry fiq_invalid_el0_32 // FIQ 32-bit EL0
ventry error_invalid_el0_32 // Error 32-bit EL0
sync_invalid_el1t:
handle_invalid_entry SYNC_INVALID_EL1t
irq_invalid_el1t:
handle_invalid_entry IRQ_INVALID_EL1t
fiq_invalid_el1t:
handle_invalid_entry FIQ_INVALID_EL1t
error_invalid_el1t:
handle_invalid_entry ERROR_INVALID_EL1t
sync_invalid_el1h:
handle_invalid_entry SYNC_INVALID_EL1h
fiq_invalid_el1h:
handle_invalid_entry FIQ_INVALID_EL1h
error_invalid_el1h:
handle_invalid_entry ERROR_INVALID_EL1h
sync_invalid_el0_64:
handle_invalid_entry SYNC_INVALID_EL0_64
irq_invalid_el0_64:
handle_invalid_entry IRQ_INVALID_EL0_64
fiq_invalid_el0_64:
handle_invalid_entry FIQ_INVALID_EL0_64
error_invalid_el0_64:
handle_invalid_entry ERROR_INVALID_EL0_64
sync_invalid_el0_32:
handle_invalid_entry SYNC_INVALID_EL0_32
irq_invalid_el0_32:
handle_invalid_entry IRQ_INVALID_EL0_32
fiq_invalid_el0_32:
handle_invalid_entry FIQ_INVALID_EL0_32
error_invalid_el0_32:
handle_invalid_entry ERROR_INVALID_EL0_32
handle_el1_irq:
kernel_entry
bl handle_irq
kernel_exit
.globl err_hang
err_hang: b err_hang

View file

@ -0,0 +1,111 @@
#include "../include/fb.h"
#include "../include/io.h"
#include "../include/multicore.h"
#include "kernel.h"
void initProgress(void)
{
drawRect(0, 0, 301, 50, 0x0f, 0);
drawString(309, 21, "Core 0", 0x0f, 1);
drawRect(0, 60, 301, 110, 0x0f, 0);
drawString(309, 81, "Core 1", 0x0f, 1);
drawRect(0, 120, 301, 170, 0x0f, 0);
drawString(309, 141, "Timer 1", 0x0f, 1);
drawRect(0, 180, 301, 230, 0x0f, 0);
drawString(309, 201, "Timer 3", 0x0f, 1);
}
void drawProgress(unsigned int core, unsigned int val) {
unsigned char col = (core + 1) + ((core + 1) << 4);
// val should be 0-100
if (val == 0) drawRect(1, (60 * core) + 1, 300, (60 * core) + 49, 0x00, 1);
if (val > 0) drawRect(1, (60 * core) + 1, (val * 3), (60 * core) + 49, col, 1);
}
void core0_main(void)
{
unsigned int core0_val = 0;
while (1) {
wait_msec(0x100000);
drawProgress(0, core0_val);
if (core0_val < 100) core0_val++;
}
}
void core1_main(void)
{
unsigned int core1_val = 0;
clear_core1(); // Only run once
while (1) {
wait_msec(0x3FFFF);
drawProgress(1, core1_val);
if (core1_val < 100) core1_val++;
}
}
// TIMER FUNCTIONS
const unsigned int timer1_int = CLOCKHZ;
const unsigned int timer3_int = CLOCKHZ / 4;
unsigned int timer1_val = 0;
unsigned int timer3_val = 0;
void timer_init() {
timer1_val = REGS_TIMER->counter_lo;
timer1_val += timer1_int;
REGS_TIMER->compare[1] = timer1_val;
timer3_val = REGS_TIMER->counter_lo;
timer3_val += timer3_int;
REGS_TIMER->compare[3] = timer3_val;
}
void handle_timer_1() {
timer1_val += timer1_int;
REGS_TIMER->compare[1] = timer1_val;
REGS_TIMER->control_status |= SYS_TIMER_IRQ_1;
unsigned int progval = timer1_val / timer1_int;
if (progval <= 100) drawProgress(2, progval);
}
void handle_timer_3() {
timer3_val += timer3_int;
REGS_TIMER->compare[3] = timer3_val;
REGS_TIMER->control_status |= SYS_TIMER_IRQ_3;
unsigned int progval = timer3_val / timer3_int;
if (progval <= 100) drawProgress(3, progval);
}
void main(void)
{
fb_init();
unsigned int i=0;
while (i++<30) debugcrlf();
initProgress();
// Kick it off on core 1
start_core1(core1_main);
// Kick off the timers
irq_init_vectors();
enable_interrupt_controller();
irq_enable();
timer_init();
// Loop endlessly
core0_main();
}

View file

@ -0,0 +1,45 @@
#define PERIPHERAL_BASE 0xFE000000
#define CLOCKHZ 1000000
struct timer_regs {
volatile unsigned int control_status;
volatile unsigned int counter_lo;
volatile unsigned int counter_hi;
volatile unsigned int compare[4];
};
#define REGS_TIMER ((struct timer_regs *)(PERIPHERAL_BASE + 0x00003000))
struct arm_irq_regs_2711 {
volatile unsigned int irq0_pending_0;
volatile unsigned int irq0_pending_1;
volatile unsigned int irq0_pending_2;
volatile unsigned int res0;
volatile unsigned int irq0_enable_0;
volatile unsigned int irq0_enable_1;
volatile unsigned int irq0_enable_2;
volatile unsigned int res1;
volatile unsigned int irq0_disable_0;
volatile unsigned int irq0_disable_1;
volatile unsigned int irq0_disable_2;
};
typedef struct arm_irq_regs_2711 arm_irq_regs;
#define REGS_IRQ ((arm_irq_regs *)(PERIPHERAL_BASE + 0x0000B200))
enum vc_irqs {
SYS_TIMER_IRQ_0 = 1,
SYS_TIMER_IRQ_1 = 2,
SYS_TIMER_IRQ_2 = 4,
SYS_TIMER_IRQ_3 = 8,
AUX_IRQ = (1 << 29)
};
void irq_init_vectors();
void irq_enable();
void irq_disable();
void enable_interrupt_controller();
void handle_timer_1();
void handle_timer_3();

260
part13-interrupts/lib/fb.c Normal file
View file

@ -0,0 +1,260 @@
#include "../include/io.h"
#include "../include/mb.h"
#include "../include/terminal.h"
unsigned int width, height, pitch, isrgb;
unsigned char *fb;
int curx = 0;
int cury = 0;
void fb_init()
{
mbox[0] = 35*4; // Length of message in bytes
mbox[1] = MBOX_REQUEST;
mbox[2] = MBOX_TAG_SETPHYWH; // Tag identifier
mbox[3] = 8; // Value size in bytes
mbox[4] = 8; // Value size in bytes (again!)
mbox[5] = 1920; // Value(width)
mbox[6] = 1080; // Value(height)
mbox[7] = MBOX_TAG_SETVIRTWH;
mbox[8] = 8;
mbox[9] = 8;
mbox[10] = 1920;
mbox[11] = 1080;
mbox[12] = MBOX_TAG_SETVIRTOFF;
mbox[13] = 8;
mbox[14] = 8;
mbox[15] = 0; // Value(x)
mbox[16] = 0; // Value(y)
mbox[17] = MBOX_TAG_SETDEPTH;
mbox[18] = 4;
mbox[19] = 4;
mbox[20] = 32; // Bits per pixel
mbox[21] = MBOX_TAG_SETPXLORDR;
mbox[22] = 4;
mbox[23] = 4;
mbox[24] = 1; // RGB
mbox[25] = MBOX_TAG_GETFB;
mbox[26] = 8;
mbox[27] = 8;
mbox[28] = 4096; // FrameBufferInfo.pointer
mbox[29] = 0; // FrameBufferInfo.size
mbox[30] = MBOX_TAG_GETPITCH;
mbox[31] = 4;
mbox[32] = 4;
mbox[33] = 0; // Bytes per line
mbox[34] = MBOX_TAG_LAST;
// Check call is successful and we have a pointer with depth 32
if (mbox_call(MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) {
mbox[28] &= 0x3FFFFFFF; // Convert GPU address to ARM address
width = mbox[10]; // Actual physical width
height = mbox[11]; // Actual physical height
pitch = mbox[33]; // Number of bytes per line
isrgb = mbox[24]; // Pixel order
fb = (unsigned char *)((long)mbox[28]);
}
}
void drawPixel(int x, int y, unsigned char attr)
{
int offs = (y * pitch) + (x * 4);
*((unsigned int*)(fb + offs)) = vgapal[attr & 0x0f];
}
void drawRect(int x1, int y1, int x2, int y2, unsigned char attr, int fill)
{
int y=y1;
while (y <= y2) {
int x=x1;
while (x <= x2) {
if ((x == x1 || x == x2) || (y == y1 || y == y2)) drawPixel(x, y, attr);
else if (fill) drawPixel(x, y, (attr & 0xf0) >> 4);
x++;
}
y++;
}
}
void drawLine(int x1, int y1, int x2, int y2, unsigned char attr)
{
int dx, dy, p, x, y;
dx = x2-x1;
dy = y2-y1;
x = x1;
y = y1;
p = 2*dy-dx;
while (x<x2) {
if (p >= 0) {
drawPixel(x,y,attr);
y++;
p = p+2*dy-2*dx;
} else {
drawPixel(x,y,attr);
p = p+2*dy;
}
x++;
}
}
void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill)
{
int x = radius;
int y = 0;
int err = 0;
while (x >= y) {
if (fill) {
drawLine(x0 - y, y0 + x, x0 + y, y0 + x, (attr & 0xf0) >> 4);
drawLine(x0 - x, y0 + y, x0 + x, y0 + y, (attr & 0xf0) >> 4);
drawLine(x0 - x, y0 - y, x0 + x, y0 - y, (attr & 0xf0) >> 4);
drawLine(x0 - y, y0 - x, x0 + y, y0 - x, (attr & 0xf0) >> 4);
}
drawPixel(x0 - y, y0 + x, attr);
drawPixel(x0 + y, y0 + x, attr);
drawPixel(x0 - x, y0 + y, attr);
drawPixel(x0 + x, y0 + y, attr);
drawPixel(x0 - x, y0 - y, attr);
drawPixel(x0 + x, y0 - y, attr);
drawPixel(x0 - y, y0 - x, attr);
drawPixel(x0 + y, y0 - x, attr);
if (err <= 0) {
y += 1;
err += 2*y + 1;
}
if (err > 0) {
x -= 1;
err -= 2*x + 1;
}
}
}
void drawChar(unsigned char ch, int x, int y, unsigned char attr, int zoom)
{
unsigned char *glyph = (unsigned char *)&font + (ch < FONT_NUMGLYPHS ? ch : 0) * FONT_BPG;
for (int i=1;i<=(FONT_HEIGHT*zoom);i++) {
for (int j=0;j<(FONT_WIDTH*zoom);j++) {
unsigned char mask = 1 << (j/zoom);
unsigned char col = (*glyph & mask) ? attr & 0x0f : (attr & 0xf0) >> 4;
drawPixel(x+j, y+i, col);
}
glyph += (i%zoom) ? 0 : FONT_BPL;
}
}
void drawString(int x, int y, char *s, unsigned char attr, int zoom)
{
while (*s) {
if (*s == '\r') {
x = 0;
} else if(*s == '\n') {
x = 0; y += (FONT_HEIGHT*zoom);
} else {
drawChar(*s, x, y, attr, zoom);
x += (FONT_WIDTH*zoom);
}
s++;
}
}
void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr)
{
unsigned int newx = oldx + shiftx, newy = oldy + shifty;
unsigned int xcount = 0, ycount = 0;
unsigned int bitmap[width][height]; // This is very unsafe if it's too big for the stack...
unsigned int offs;
// Save the bitmap
while (xcount < width) {
while (ycount < height) {
offs = ((oldy + ycount) * pitch) + ((oldx + xcount) * 4);
bitmap[xcount][ycount] = *((unsigned int*)(fb + offs));
ycount++;
}
ycount=0;
xcount++;
}
// Wipe it out with background colour
drawRect(oldx, oldy, oldx + width, oldy + width, attr, 1);
// Draw it again
for (int i=newx;i<newx + width;i++) {
for (int j=newy;j<newy + height;j++) {
offs = (j * pitch) + (i * 4);
*((unsigned int*)(fb + offs)) = bitmap[i-newx][j-newy];
}
}
}
void wait_msec(unsigned int n)
{
register unsigned long f, t, r;
// Get the current counter frequency
asm volatile ("mrs %0, cntfrq_el0" : "=r"(f));
// Read the current counter
asm volatile ("mrs %0, cntpct_el0" : "=r"(t));
// Calculate expire value for counter
t+=((f/1000)*n)/1000;
do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r<t);
}
int strlen(const char *str) {
const char *s;
for (s = str; *s; ++s);
return (s - str);
}
void debugstr(char *str) {
if (curx + (strlen(str) * 8) >= 1920) {
curx = 0; cury += 8;
}
if (cury + 8 >= 1080) {
cury = 0;
}
drawString(curx, cury, str, 0x0f, 1);
curx += (strlen(str) * 8);
}
void debugcrlf(void) {
curx = 0; cury += 8;
}
void debugch(unsigned char b) {
unsigned int n;
int c;
for(c=4;c>=0;c-=4) {
n=(b>>c)&0xF;
n+=n>9?0x37:0x30;
debugstr((char *)&n);
}
debugstr(" ");
}
void debughex(unsigned int d) {
unsigned int n;
int c;
for(c=28;c>=0;c-=4) {
n=(d>>c)&0xF;
n+=n>9?0x37:0x30;
debugstr((char *)&n);
}
debugstr(" ");
}

199
part13-interrupts/lib/io.c Normal file
View file

@ -0,0 +1,199 @@
#include "../include/io.h"
// GPIO
enum {
GPFSEL0 = PERIPHERAL_BASE + 0x200000,
GPSET0 = PERIPHERAL_BASE + 0x20001C,
GPCLR0 = PERIPHERAL_BASE + 0x200028,
GPPUPPDN0 = PERIPHERAL_BASE + 0x2000E4
};
enum {
GPIO_MAX_PIN = 53,
GPIO_FUNCTION_OUT = 1,
GPIO_FUNCTION_ALT5 = 2,
GPIO_FUNCTION_ALT3 = 7,
GPIO_FUNCTION_ALT0 = 4
};
enum {
Pull_None = 0,
Pull_Down = 1, // Are down and up the right way around?
Pull_Up = 2
};
void mmio_write(long reg, unsigned int val) { *(volatile unsigned int *)reg = val; }
unsigned int mmio_read(long reg) { return *(volatile unsigned int *)reg; }
unsigned int gpio_call(unsigned int pin_number, unsigned int value, unsigned int base, unsigned int field_size, unsigned int field_max) {
unsigned int field_mask = (1 << field_size) - 1;
if (pin_number > field_max) return 0;
if (value > field_mask) return 0;
unsigned int num_fields = 32 / field_size;
unsigned int reg = base + ((pin_number / num_fields) * 4);
unsigned int shift = (pin_number % num_fields) * field_size;
unsigned int curval = mmio_read(reg);
curval &= ~(field_mask << shift);
curval |= value << shift;
mmio_write(reg, curval);
return 1;
}
unsigned int gpio_set (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPSET0, 1, GPIO_MAX_PIN); }
unsigned int gpio_clear (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPCLR0, 1, GPIO_MAX_PIN); }
unsigned int gpio_pull (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPPUPPDN0, 2, GPIO_MAX_PIN); }
unsigned int gpio_function(unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPFSEL0, 3, GPIO_MAX_PIN); }
void gpio_useAsAlt0(unsigned int pin_number) {
gpio_pull(pin_number, Pull_None);
gpio_function(pin_number, GPIO_FUNCTION_ALT0);
}
void gpio_useAsAlt3(unsigned int pin_number) {
gpio_pull(pin_number, Pull_None);
gpio_function(pin_number, GPIO_FUNCTION_ALT3);
}
void gpio_useAsAlt5(unsigned int pin_number) {
gpio_pull(pin_number, Pull_None);
gpio_function(pin_number, GPIO_FUNCTION_ALT5);
}
void gpio_initOutputPinWithPullNone(unsigned int pin_number) {
gpio_pull(pin_number, Pull_None);
gpio_function(pin_number, GPIO_FUNCTION_OUT);
}
void gpio_setPinOutputBool(unsigned int pin_number, unsigned int onOrOff) {
if (onOrOff) {
gpio_set(pin_number, 1);
} else {
gpio_clear(pin_number, 1);
}
}
// UART
enum {
AUX_BASE = PERIPHERAL_BASE + 0x215000,
AUX_IRQ = AUX_BASE,
AUX_ENABLES = AUX_BASE + 4,
AUX_MU_IO_REG = AUX_BASE + 64,
AUX_MU_IER_REG = AUX_BASE + 68,
AUX_MU_IIR_REG = AUX_BASE + 72,
AUX_MU_LCR_REG = AUX_BASE + 76,
AUX_MU_MCR_REG = AUX_BASE + 80,
AUX_MU_LSR_REG = AUX_BASE + 84,
AUX_MU_MSR_REG = AUX_BASE + 88,
AUX_MU_SCRATCH = AUX_BASE + 92,
AUX_MU_CNTL_REG = AUX_BASE + 96,
AUX_MU_STAT_REG = AUX_BASE + 100,
AUX_MU_BAUD_REG = AUX_BASE + 104,
AUX_UART_CLOCK = 500000000,
UART_MAX_QUEUE = 16 * 1024
};
#define AUX_MU_BAUD(baud) ((AUX_UART_CLOCK/(baud*8))-1)
unsigned char uart_output_queue[UART_MAX_QUEUE];
unsigned int uart_output_queue_write = 0;
unsigned int uart_output_queue_read = 0;
void uart_init() {
mmio_write(AUX_ENABLES, 1); //enable UART1
mmio_write(AUX_MU_IER_REG, 0);
mmio_write(AUX_MU_CNTL_REG, 0);
mmio_write(AUX_MU_LCR_REG, 3); //8 bits
mmio_write(AUX_MU_MCR_REG, 0);
mmio_write(AUX_MU_IER_REG, 0);
mmio_write(AUX_MU_IIR_REG, 0xC6); //disable interrupts
mmio_write(AUX_MU_BAUD_REG, AUX_MU_BAUD(115200));
gpio_useAsAlt5(14);
gpio_useAsAlt5(15);
mmio_write(AUX_MU_CNTL_REG, 3); //enable RX/TX
}
unsigned int uart_isOutputQueueEmpty() {
return uart_output_queue_read == uart_output_queue_write;
}
unsigned int uart_isReadByteReady() { return mmio_read(AUX_MU_LSR_REG) & 0x01; }
unsigned int uart_isWriteByteReady() { return mmio_read(AUX_MU_LSR_REG) & 0x20; }
unsigned char uart_readByte() {
while (!uart_isReadByteReady());
return (unsigned char)mmio_read(AUX_MU_IO_REG);
}
void uart_writeByteBlockingActual(unsigned char ch) {
while (!uart_isWriteByteReady());
mmio_write(AUX_MU_IO_REG, (unsigned int)ch);
}
void uart_loadOutputFifo() {
while (!uart_isOutputQueueEmpty() && uart_isWriteByteReady()) {
uart_writeByteBlockingActual(uart_output_queue[uart_output_queue_read]);
uart_output_queue_read = (uart_output_queue_read + 1) & (UART_MAX_QUEUE - 1); // Don't overrun
}
}
void uart_writeByteBlocking(unsigned char ch) {
unsigned int next = (uart_output_queue_write + 1) & (UART_MAX_QUEUE - 1); // Don't overrun
while (next == uart_output_queue_read) uart_loadOutputFifo();
uart_output_queue[uart_output_queue_write] = ch;
uart_output_queue_write = next;
}
void uart_writeText(char *buffer) {
while (*buffer) {
if (*buffer == '\n') uart_writeByteBlockingActual('\r');
uart_writeByteBlockingActual(*buffer++);
}
}
void uart_drainOutputQueue() {
while (!uart_isOutputQueueEmpty()) uart_loadOutputFifo();
}
void uart_update() {
uart_loadOutputFifo();
if (uart_isReadByteReady()) {
unsigned char ch = uart_readByte();
if (ch == '\r') uart_writeText("\n"); else uart_writeByteBlocking(ch);
}
}
void uart_hex(unsigned int d) {
unsigned int n;
int c;
for(c=28;c>=0;c-=4) {
// get highest tetrad
n=(d>>c)&0xF;
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
n+=n>9?0x37:0x30;
uart_writeByteBlockingActual(n);
}
}
void uart_byte(unsigned char b) {
unsigned int n;
int c;
for(c=4;c>=0;c-=4) {
// get highest tetrad
n=(b>>c)&0xF;
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
n+=n>9?0x37:0x30;
uart_writeByteBlockingActual(n);
}
uart_writeByteBlockingActual(' ');
}

View file

@ -0,0 +1,39 @@
#include "../include/io.h"
// The buffer must be 16-byte aligned as only the upper 28 bits of the address can be passed via the mailbox
volatile unsigned int __attribute__((aligned(16))) mbox[36];
enum {
VIDEOCORE_MBOX = (PERIPHERAL_BASE + 0x0000B880),
MBOX_READ = (VIDEOCORE_MBOX + 0x0),
MBOX_POLL = (VIDEOCORE_MBOX + 0x10),
MBOX_SENDER = (VIDEOCORE_MBOX + 0x14),
MBOX_STATUS = (VIDEOCORE_MBOX + 0x18),
MBOX_CONFIG = (VIDEOCORE_MBOX + 0x1C),
MBOX_WRITE = (VIDEOCORE_MBOX + 0x20),
MBOX_RESPONSE = 0x80000000,
MBOX_FULL = 0x80000000,
MBOX_EMPTY = 0x40000000
};
unsigned int mbox_call(unsigned char ch)
{
// 28-bit address (MSB) and 4-bit value (LSB)
unsigned int r = ((unsigned int)((long) &mbox) &~ 0xF) | (ch & 0xF);
// Wait until we can write
while (mmio_read(MBOX_STATUS) & MBOX_FULL);
// Write the address of our buffer to the mailbox with the channel appended
mmio_write(MBOX_WRITE, r);
while (1) {
// Is there a reply?
while (mmio_read(MBOX_STATUS) & MBOX_EMPTY);
// Is it a reply to our message?
if (r == mmio_read(MBOX_READ)) return mbox[1]==MBOX_RESPONSE; // Is it successful?
}
return 0;
}

View file

@ -0,0 +1,44 @@
#include "../include/multicore.h"
void store32(unsigned long address, unsigned long value)
{
*(unsigned long *) address = value;
}
unsigned long load32(unsigned long address)
{
return *(unsigned long *) address;
}
void start_core1(void (*func)(void))
{
store32((unsigned long)&spin_cpu1, (unsigned long)func);
asm volatile ("sev");
}
void start_core2(void (*func)(void))
{
store32((unsigned long)&spin_cpu2, (unsigned long)func);
asm volatile ("sev");
}
void start_core3(void (*func)(void))
{
store32((unsigned long)&spin_cpu3, (unsigned long)func);
asm volatile ("sev");
}
void clear_core1(void)
{
store32((unsigned long)&spin_cpu1, 0);
}
void clear_core2(void)
{
store32((unsigned long)&spin_cpu2, 0);
}
void clear_core3(void)
{
store32((unsigned long)&spin_cpu3, 0);
}

View file

@ -0,0 +1,15 @@
.globl irq_init_vectors
irq_init_vectors:
adr x0, vectors
msr vbar_el1, x0
ret
.globl irq_enable
irq_enable:
msr daifclr, #2
ret
.globl irq_disable
irq_disable:
msr daifset, #2
ret