Skip to content
Draft
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
22 changes: 22 additions & 0 deletions include/stdbigos/clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef STDBIGOS_CLOCK
#define STDBIGOS_CLOCK

#include "sbi.h"
#include "types.h"

/// @ingroup stdbigos
/// @{
/// @ingroup clock
/// @{

u64 clock_now(void);
u64 clock_ticks(void);

struct sbiret clock_init(u64 tick_quantum);
struct sbiret clock_rearm(void);
struct sbiret clock_on_timer_interrupt(void);

/// @}
/// @}

#endif // !STDBIGOS_CLOCK
44 changes: 43 additions & 1 deletion src/example_sbi/entry.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,52 @@
#include <stdbigos/clock.h>
#include <stdbigos/csr.h>
#include <stdbigos/sbi.h>
#include <stdbigos/trap.h>
#include <stdbigos/types.h>
#include <stdbool.h>

static void sbi_puts(const char* str) {
while (*str) sbi_debug_console_write_byte(*str++);
}

[[gnu::interrupt("supervisor")]]
static void int_handler() {
reg_t cause = CSR_READ(scause);
if (!is_interrupt(cause)) {
return;
}

reg_t int_no = get_interrupt_code(cause);
if (int_no != IntSTimer) {
return;
}

(void)clock_on_timer_interrupt();
}

void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) {
sbi_puts("Hello world\n");
CSR_WRITE(stvec, int_handler);

struct sbiret ret = clock_init(50000llu);
if (ret.error != SBI_SUCCESS) {
sbi_puts("clock init failed\n");
return;
}

CSR_SET(sie, 1lu << IntSTimer);
CSR_SET(sstatus, 1lu << 1);

sbi_puts("clock started\n");

u64 last_tick = 0;
while (true) {
wfi();

u64 ticks = clock_ticks();
if (ticks != last_tick && (ticks % 100) == 0) {
sbi_puts("tick x100\n");
}

last_tick = ticks;
}
}
51 changes: 51 additions & 0 deletions src/lib/stdbigos/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <stdbigos/clock.h>
#include <stdbigos/csr.h>

static u64 g_tick_quantum;
static u64 g_next_deadline;
static u64 g_ticks;

static struct sbiret clock_program_timer(u64 deadline) {
struct sbiret ret = sbi_set_timer(deadline);
if (ret.error == SBI_ERR_NOT_SUPPORTED) {
return sbi_legacy_set_timer(deadline);
}

return ret;
}

static struct sbiret make_error(sbi_error_t error) {
return (struct sbiret){.error = error, .value = 0};
}

u64 clock_now(void) {
return CSR_READ(time);
}

u64 clock_ticks(void) {
return g_ticks;
}

struct sbiret clock_rearm(void) {
if (g_tick_quantum == 0) {
return make_error(SBI_ERR_INVALID_STATE);
}

g_next_deadline = clock_now() + g_tick_quantum;
return clock_program_timer(g_next_deadline);
}

struct sbiret clock_init(u64 tick_quantum) {
if (tick_quantum == 0) {
return make_error(SBI_ERR_INVALID_PARAM);
}

g_ticks = 0;
g_tick_quantum = tick_quantum;
return clock_rearm();
}

struct sbiret clock_on_timer_interrupt(void) {
++g_ticks;
return clock_rearm();
}