Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions build_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,32 @@ class ConfigInfo:
"hello": Path("example/imx8mq_evk/hello")
}
),
BoardInfo(
name="odroidc2",
gcc_cpu="cortex-a53",
loader_link_address=0x20000000,
kernel_options={
"KernelPlatform": "odroidc2",
"KernelIsMCS": True,
"KernelArmExportPCNTUser": True,
},
examples={
"hello": Path("example/odroidc2/hello")
}
),
BoardInfo(
name="odroidc4",
gcc_cpu="cortex-a55",
loader_link_address=0x20000000,
kernel_options={
"KernelPlatform": "odroidc4",
"KernelIsMCS": True,
"KernelArmExportPCNTUser": True,
},
examples={
"timer": Path("example/odroidc4/timer")
}
),
)

SUPPORTED_CONFIGS = (
Expand Down
18 changes: 18 additions & 0 deletions docs/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,24 @@ Microkit produces a raw binary file, so when using U-Boot you must execute the i

=> go 0x40480000

## Odroid-C2

The HardKernel Odroid-C2 is an ARM SBC based on the Amlogic Meson S905 system-on-chip. It
should be noted that the Odroid-C2 is no longer available for purchase but its successor,
the Odroid-C4, is readily available at the time of writing.

Microkit produces a raw binary file, so when using U-Boot you must execute the image using:

=> go 0x20000000

## Odroid-C4

The HardKernel Odroid-C4 is an ARM SBC based on the Amlogic Meson S905X3 system-on-chip.

Microkit produces a raw binary file, so when using U-Boot you must execute the image using:

=> go 0x20000000

## TQMa8XQP 1GB

The TQMa8XQP is a system-on-module designed by TQ-Systems GmbH.
Expand Down
55 changes: 55 additions & 0 deletions example/odroidc2/hello/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# Copyright 2021, Breakaway Consulting Pty. Ltd.
#
# SPDX-License-Identifier: BSD-2-Clause
#
ifeq ($(strip $(BUILD_DIR)),)
$(error BUILD_DIR must be specified)
endif

ifeq ($(strip $(MICROKIT_SDK)),)
$(error MICROKIT_SDK must be specified)
endif

ifeq ($(strip $(MICROKIT_BOARD)),)
$(error MICROKIT_BOARD must be specified)
endif

ifeq ($(strip $(MICROKIT_CONFIG)),)
$(error MICROKIT_CONFIG must be specified)
endif

TOOLCHAIN := aarch64-none-elf

CPU := cortex-a55

CC := $(TOOLCHAIN)-gcc
LD := $(TOOLCHAIN)-ld
AS := $(TOOLCHAIN)-as
MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit

HELLO_OBJS := hello.o

BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG)

IMAGES := hello.elf
CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include
LDFLAGS := -L$(BOARD_DIR)/lib
LIBS := -lmicrokit -Tmicrokit.ld

IMAGE_FILE = $(BUILD_DIR)/loader.img
REPORT_FILE = $(BUILD_DIR)/report.txt

all: $(IMAGE_FILE)

$(BUILD_DIR)/%.o: %.c Makefile
$(CC) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile
$(AS) -g -mcpu=$(CPU) $< -o $@

$(BUILD_DIR)/hello.elf: $(addprefix $(BUILD_DIR)/, $(HELLO_OBJS))
$(LD) $(LDFLAGS) $^ $(LIBS) -o $@

$(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) hello.system
$(MICROKIT_TOOL) hello.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE)
16 changes: 16 additions & 0 deletions example/odroidc2/hello/hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2021, Breakaway Consulting Pty. Ltd.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <stdint.h>
#include <microkit.h>

void init(void)
{
microkit_dbg_puts("hello, world\n");
}

void notified(microkit_channel ch)
{
}
11 changes: 11 additions & 0 deletions example/odroidc2/hello/hello.system
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2021, Breakaway Consulting Pty. Ltd.

SPDX-License-Identifier: BSD-2-Clause
-->
<system>
<protection_domain name="hello" priority="254">
<program_image path="hello.elf" />
</protection_domain>
</system>
55 changes: 55 additions & 0 deletions example/odroidc4/timer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# Copyright 2021, Breakaway Consulting Pty. Ltd.
#
# SPDX-License-Identifier: BSD-2-Clause
#
ifeq ($(strip $(BUILD_DIR)),)
$(error BUILD_DIR must be specified)
endif

ifeq ($(strip $(MICROKIT_SDK)),)
$(error MICROKIT_SDK must be specified)
endif

ifeq ($(strip $(MICROKIT_BOARD)),)
$(error MICROKIT_BOARD must be specified)
endif

ifeq ($(strip $(MICROKIT_CONFIG)),)
$(error MICROKIT_CONFIG must be specified)
endif

TOOLCHAIN := aarch64-none-elf

CPU := cortex-a55

CC := $(TOOLCHAIN)-gcc
LD := $(TOOLCHAIN)-ld
AS := $(TOOLCHAIN)-as
MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit

TIMER_OBJS := timer.o

BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG)

IMAGES := timer.elf
CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include
LDFLAGS := -L$(BOARD_DIR)/lib
LIBS := -lmicrokit -Tmicrokit.ld

IMAGE_FILE = $(BUILD_DIR)/loader.img
REPORT_FILE = $(BUILD_DIR)/report.txt

all: $(IMAGE_FILE)

$(BUILD_DIR)/%.o: %.c Makefile
$(CC) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile
$(AS) -g -mcpu=$(CPU) $< -o $@

$(BUILD_DIR)/timer.elf: $(addprefix $(BUILD_DIR)/, $(TIMER_OBJS))
$(LD) $(LDFLAGS) $^ $(LIBS) -o $@

$(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) timer.system
$(MICROKIT_TOOL) timer.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE)
145 changes: 145 additions & 0 deletions example/odroidc4/timer/timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright 2024, UNSW
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <stdint.h>
#include <stdbool.h>
#include <microkit.h>

/*
* This is a very simple timer driver with the intention of showing
* how to do MMIO and handle interrupts in Microkit.
*/

uintptr_t timer_regs;

#define TIMER_IRQ_CH 0

#define TIMER_REG_START 0x140

#define TIMER_A_INPUT_CLK 0
#define TIMER_E_INPUT_CLK 8
#define TIMER_A_EN (1 << 16)
#define TIMER_A_MODE (1 << 12)

#define TIMESTAMP_TIMEBASE_SYSTEM 0b000
#define TIMESTAMP_TIMEBASE_1_US 0b001
#define TIMESTAMP_TIMEBASE_10_US 0b010
#define TIMESTAMP_TIMEBASE_100_US 0b011
#define TIMESTAMP_TIMEBASE_1_MS 0b100

#define TIMEOUT_TIMEBASE_1_US 0b00
#define TIMEOUT_TIMEBASE_10_US 0b01
#define TIMEOUT_TIMEBASE_100_US 0b10
#define TIMEOUT_TIMEBASE_1_MS 0b11

#define NS_IN_US 1000ULL
#define NS_IN_MS 1000000ULL

typedef struct {
uint32_t mux;
uint32_t timer_a;
uint32_t timer_b;
uint32_t timer_c;
uint32_t timer_d;
uint32_t unused[13];
uint32_t timer_e;
uint32_t timer_e_hi;
uint32_t mux1;
uint32_t timer_f;
uint32_t timer_g;
uint32_t timer_h;
uint32_t timer_i;
} meson_timer_reg_t;

typedef struct {
volatile meson_timer_reg_t *regs;
bool disable;
} meson_timer_t;

meson_timer_t timer;

static char hexchar(unsigned int v)
{
return v < 10 ? '0' + v : ('a' - 10) + v;
}

static void puthex64(uint64_t val)
{
char buffer[16 + 3];
buffer[0] = '0';
buffer[1] = 'x';
buffer[16 + 3 - 1] = 0;
for (unsigned i = 16 + 1; i > 1; i--) {
buffer[i] = hexchar(val & 0xf);
val >>= 4;
}
microkit_dbg_puts(buffer);
}

uint64_t meson_get_time()
{
uint64_t initial_high = timer.regs->timer_e_hi;
uint64_t low = timer.regs->timer_e;
uint64_t high = timer.regs->timer_e_hi;
if (high != initial_high) {
low = timer.regs->timer_e;
}

uint64_t ticks = (high << 32) | low;
uint64_t time = ticks * NS_IN_US;
return time;
}

void meson_set_timeout(uint16_t timeout, bool periodic)
{
if (periodic) {
timer.regs->mux |= TIMER_A_MODE;
} else {
timer.regs->mux &= ~TIMER_A_MODE;
}

timer.regs->timer_a = timeout;

if (timer.disable) {
timer.regs->mux |= TIMER_A_EN;
timer.disable = false;
}
}

void meson_stop_timer()
{
timer.regs->mux &= ~TIMER_A_EN;
timer.disable = true;
}

void init()
{
timer.regs = (void *)(timer_regs + TIMER_REG_START);

timer.regs->mux = TIMER_A_EN | (TIMESTAMP_TIMEBASE_1_US << TIMER_E_INPUT_CLK) |
(TIMEOUT_TIMEBASE_1_MS << TIMER_A_INPUT_CLK);

timer.regs->timer_e = 0;

// Have a timeout of 1 second, and have it be periodic so that it will keep recurring.
microkit_dbg_puts("Setting a timeout of 1 second.\n");
meson_set_timeout(1000, true);
}

void notified(microkit_channel ch)
{
switch (ch) {
case TIMER_IRQ_CH:
microkit_dbg_puts("Got timer interrupt!\n");
microkit_irq_ack(ch);
microkit_dbg_puts("Current time is: ");
puthex64(meson_get_time());
microkit_dbg_puts("\n");
break;
default:
microkit_dbg_puts("TIMER|ERROR: unexpected channel!\n");
}
}
15 changes: 15 additions & 0 deletions example/odroidc4/timer/timer.system
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2024, UNSW

SPDX-License-Identifier: BSD-2-Clause
-->
<system>
<memory_region name="timer" size="0x10_000" phys_addr="0xffd0f000" />

<protection_domain name="timer">
<program_image path="timer.elf" />
<map mr="timer" vaddr="0x2_000_000" perms="rw" cached="false" setvar_vaddr="timer_regs" />
<irq irq="42" id="0" trigger="edge" />
</protection_domain>
</system>
22 changes: 22 additions & 0 deletions loader/src/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,28 @@ static void putc(uint8_t ch)
while (!(*UART_REG(STAT) & STAT_TDRE)) { }
*UART_REG(TRANSMIT) = ch;
}
#elif defined(BOARD_odroidc2)
#define UART_BASE 0xc81004c0
#define UART_WFIFO 0x0
#define UART_STATUS 0xC
#define UART_TX_FULL (1 << 21)

static void putc(uint8_t ch)
{
while ((*UART_REG(UART_STATUS) & UART_TX_FULL));
*UART_REG(UART_WFIFO) = ch;
}
#elif defined(BOARD_odroidc4)
#define UART_BASE 0xff803000
#define UART_WFIFO 0x0
#define UART_STATUS 0xC
#define UART_TX_FULL (1 << 21)

static void putc(uint8_t ch)
{
while ((*UART_REG(UART_STATUS) & UART_TX_FULL));
*UART_REG(UART_WFIFO) = ch;
}
#else
#error Board not defined
#endif
Expand Down