Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4254710
Add rough skeleton for clock controller
moojek Mar 23, 2026
67f6d62
Test commit signing
moojek Mar 23, 2026
371509f
Merge branch 'Operacja-System:main' into zegar
moojek Apr 19, 2026
827960d
Add HAL timer abstraction
moojek Apr 19, 2026
f4b4886
Switch clock handling to one-shot timer behavior
moojek Apr 19, 2026
67a4421
Refactor stdbigos clock API to return error_t
moojek Apr 19, 2026
758875e
Run project formatter
moojek Apr 19, 2026
3ac6a4e
Implement periodic clock and next-switch tick API
moojek Apr 19, 2026
ac94235
Clean up code
moojek Apr 19, 2026
95b19c6
Enable only timer sie bit and remove unused CSR_SIE_STIE
moojek Apr 20, 2026
26f9eaa
Use rdtime pseudoinstruction in hal_timer_now
moojek Apr 20, 2026
68caca4
Rename for consistency
moojek Apr 24, 2026
9bc7369
Move sbi_error_t to error_t mapping function to common util file
moojek Apr 24, 2026
747c607
Adjust returns in timer
moojek Apr 24, 2026
ce4eafd
Add option to disable timer interrupts
moojek Apr 24, 2026
37ce359
Remove redundant include
moojek Apr 24, 2026
a0d61d5
Fix formatting
moojek Apr 26, 2026
abed4ac
Add option to disable timer interrupts
moojek Apr 24, 2026
62295a9
Remove redundant include
moojek Apr 24, 2026
1becde7
Fix formatting
moojek Apr 26, 2026
799398e
Merge branch 'zegar' of github.com:moojek/BigOS into zegar
moojek May 2, 2026
3ff6e4c
Enhance documentation for clock API in clock.h
moojek May 2, 2026
5769ac9
Add clock API documentation and update group annotations in header
moojek May 2, 2026
5b5bdf2
Fix formatting of the clock.h header guard
moojek May 2, 2026
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
5 changes: 5 additions & 0 deletions docs/source/pages/api/libs/stdbigos/clock.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
=====
Clock
=====

.. doxygengroup:: clock
1 change: 1 addition & 0 deletions docs/source/pages/api/libs/stdbigos/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ Stdbigos
types
string
bitutils
clock
52 changes: 52 additions & 0 deletions include/hal/timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef HAL_TIMER_H
#define HAL_TIMER_H

#include <stdbigos/error.h>
#include <stdbigos/types.h>

/**
* @addtogroup hal
* @{
*/

/**
* @brief Read current monotonic hardware timer value.
* @return Current hardware timer tick value.
*/
u64 hal_timer_now(void);
Comment thread
moojek marked this conversation as resolved.

/**
* @brief Program the next timer interrupt deadline.
*
* @param deadline Absolute timer value when the interrupt should fire.
* @retval ERR_NONE Success
* @retval ERR_BAD_ARG Invalid deadline argument
* @retval ERR_NOT_IMPLEMENTED Timer SBI extension unsupported
* @retval ERR_NOT_VALID Other platform/firmware failure
*/
error_t hal_timer_arm_absolute(u64 deadline);

/**
* @brief Program next timer interrupt relative to current time.
*
* @param delta Timer ticks from now
* @retval ERR_NONE Success
* @retval ERR_BAD_ARG Invalid delta argument
* @retval ERR_NOT_IMPLEMENTED Timer SBI extension unsupported
* @retval ERR_NOT_VALID Other platform/firmware failure
*/
error_t hal_timer_arm_relative(u64 delta);

/**
* @brief Enable supervisor timer interrupts.
*/
void hal_timer_enable_interrupts(void);

/**
* @brief Disable supervisor timer interrupts.
*/
void hal_timer_disable_interrupts(void);

/// @}

#endif // !HAL_TIMER_H
91 changes: 91 additions & 0 deletions include/stdbigos/clock.h
Comment thread
moojek marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#ifndef STDBIGOS_CLOCK
#define STDBIGOS_CLOCK

#include "error.h"
#include "types.h"

/**
* @file include/stdbigos/clock.h
* @brief Public periodic clock API used by the scheduler and examples.
*
* The periodic clock provides a monotonic time source measured in
* architecture-specific ticks and supports scheduling a "next switch"
* tick for the scheduler to observe.
*
* @addtogroup stdbigos
* @{
* @addtogroup clock
* @{
*/

/**
* @brief Initialize the periodic clock subsystem.
*
* Initialize internal state and program the first timer deadline using
* the provided tick quantum.
*
* @param tick_quantum Number of hardware timer ticks per software tick.
* @return error_t E_OK on success, otherwise an error code.
*/
error_t clock_init(u64 tick_quantum);

/**
* @brief Return the current time in hardware timer ticks.
*
* This returns a monotonic timestamp suitable for computing deadlines.
*
* @return Current time in hardware ticks.
*/
u64 clock_now(void);

/**
* @brief Return the number of software ticks since boot.
*
* Software ticks are incremented by the timer IRQ handler and advance
* at a rate of one per `tick_quantum` hardware ticks.
*
* @return Number of elapsed software ticks.
*/
u64 clock_ticks_now(void);

/**
* @brief Request the scheduler be woken in a number of software ticks.
*
* Programs the next switch tick to be `ticks_from_now` software ticks
* in the future. This does not block; use `clock_next_switch_tick`
* or `clock_ticks_to_next_switch` to query the scheduled value.
*
* @param ticks_from_now Number of software ticks from now to schedule.
* @return error_t E_OK on success, otherwise an error code.
*/
error_t clock_set_next_switch_in(u64 ticks_from_now);

/**
* @brief Obtain the currently scheduled next-switch absolute tick.
*
* Writes the absolute software tick value at which the scheduler has
* requested a switch into `out_tick`.
*
* @param out_tick Pointer to u64 to receive the absolute tick value.
* @return error_t E_OK on success, EINVAL if `out_tick` is NULL, or
* other error codes on failure.
*/
error_t clock_next_switch_tick(u64* out_tick);

/**
* @brief Obtain the number of software ticks until the next switch.
*
* Writes into `out_ticks` the number of ticks remaining until the
* scheduled next-switch tick. If a next-switch is not scheduled,
* behavior is implementation-defined.
*
* @param out_ticks Pointer to u64 to receive remaining ticks.
* @return error_t E_OK on success, EINVAL if `out_ticks` is NULL, or
* other error codes on failure.
*/
error_t clock_ticks_to_next_switch(u64* out_ticks);

/** @} */ /* end group clock */
/** @} */ /* end group stdbigos */

#endif // !STDBIGOS_CLOCK
16 changes: 16 additions & 0 deletions include/stdbigos/sbi_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef _STDBIGOS_SBI_UTILS_H_
#define _STDBIGOS_SBI_UTILS_H_

#include "error.h"
#include "sbi.h"

static inline error_t sbi_map_error(sbi_error_t err) {
switch (err) {
case SBI_SUCCESS: return ERR_NONE;
case SBI_ERR_INVALID_PARAM: return ERR_BAD_ARG;
case SBI_ERR_NOT_SUPPORTED: return ERR_NOT_IMPLEMENTED;
default: return ERR_NOT_VALID;
}
}

#endif // !_STDBIGOS_SBI_UTILS_H_
2 changes: 1 addition & 1 deletion src/example_sbi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SETUP_EXECUTABLE(example_sbi)

target_link_libraries(example_sbi PRIVATE startup stdbigos)
target_link_libraries(example_sbi PRIVATE startup stdbigos hal)

ADD_QEMU_TARGET(example_sbi)
31 changes: 30 additions & 1 deletion src/example_sbi/entry.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <hal/timer.h>
#include <hal/trap.h>
#include <stdbigos/clock.h>
#include <stdbigos/sbi.h>
#include <stdbigos/types.h>

Expand All @@ -6,5 +9,31 @@ static void sbi_puts(const char* str) {
}

void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) {
sbi_puts("Hello world\n");
if (hal_trap_init() != ERR_NONE) {
sbi_puts("trap init failed\n");
return;
}

error_t err = clock_init(50000llu);
if (err != ERR_NONE) {
sbi_puts("clock init failed\n");
return;
}

hal_timer_enable_interrupts();

sbi_puts("clock started\n");

u64 last_tick = clock_ticks_now();
while (true) {
hal_wait_for_interrupt();

u64 now_tick = clock_ticks_now();
if (now_tick != last_tick) {
if ((now_tick % 100) == 0) {
sbi_puts("tick periodic\n");
}
last_tick = now_tick;
}
}
}
41 changes: 41 additions & 0 deletions src/lib/hal/arch/riscv/timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <hal/timer.h>
#include <stdbigos/sbi.h>
#include <stdbigos/sbi_utils.h>

#include "csr.h"
#include "trap.h"

u64 hal_timer_now(void) {
u64 now;
__asm__ volatile("rdtime %0" : "=r"(now)::"memory");
return now;
}

error_t hal_timer_arm_absolute(u64 deadline) {
if (deadline == 0) {
return ERR_BAD_ARG;
}

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

return sbi_map_error(ret.error);
}

error_t hal_timer_arm_relative(u64 delta) {
Comment thread
moojek marked this conversation as resolved.
if (delta == 0) {
return ERR_BAD_ARG;
}

return hal_timer_arm_absolute(hal_timer_now() + delta);
}

void hal_timer_enable_interrupts(void) {
CSR_SET(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER);
}

void hal_timer_disable_interrupts(void) {
CSR_CLEAR(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER);
}
107 changes: 107 additions & 0 deletions src/lib/stdbigos/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <hal/timer.h>
#include <hal/trap.h>
#include <stdbigos/clock.h>

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

static error_t clock_program_timer(u64 deadline) {
error_t err = hal_timer_arm_absolute(deadline);
if (err != ERR_NONE) {
return err;
}

return ERR_NONE;
}

static error_t clock_schedule_next_deadline(void) {
if (g_tick_quantum == 0) {
return ERR_NOT_INITIALIZED;
}

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

static void clock_timer_irq_handler(void) {
++g_ticks;
(void)clock_schedule_next_deadline();
}

u64 clock_now(void) {
return hal_timer_now();
}

u64 clock_ticks_now(void) {
return g_ticks;
}

error_t clock_init(u64 tick_quantum) {
if (tick_quantum == 0) {
return ERR_BAD_ARG;
}

error_t err = hal_trap_register_timer_handler(clock_timer_irq_handler);
if (err != ERR_NONE) {
return err;
}

g_ticks = 0;
g_tick_quantum = tick_quantum;
g_next_switch_tick = 0;
return clock_schedule_next_deadline();
}

error_t clock_set_next_switch_in(u64 ticks_from_now) {
if (g_tick_quantum == 0) {
return ERR_NOT_INITIALIZED;
}

if (ticks_from_now == 0) {
return ERR_BAD_ARG;
}

g_next_switch_tick = g_ticks + ticks_from_now;
return ERR_NONE;
}

error_t clock_next_switch_tick(u64* out_tick) {
if (out_tick == NULL) {
return ERR_BAD_ARG;
}

if (g_tick_quantum == 0) {
return ERR_NOT_INITIALIZED;
}

if (g_next_switch_tick == 0) {
return ERR_NOT_FOUND;
}

*out_tick = g_next_switch_tick;
return ERR_NONE;
}

error_t clock_ticks_to_next_switch(u64* out_ticks) {
if (out_ticks == NULL) {
return ERR_BAD_ARG;
}

if (g_tick_quantum == 0) {
return ERR_NOT_INITIALIZED;
}

if (g_next_switch_tick == 0) {
return ERR_NOT_FOUND;
}

if (g_ticks >= g_next_switch_tick) {
*out_ticks = 0;
return ERR_NONE;
}

*out_ticks = g_next_switch_tick - g_ticks;
return ERR_NONE;
}
Loading