-
Notifications
You must be signed in to change notification settings - Fork 18
Implement clock controller #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
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 67f6d62
Test commit signing
moojek 371509f
Merge branch 'Operacja-System:main' into zegar
moojek 827960d
Add HAL timer abstraction
moojek f4b4886
Switch clock handling to one-shot timer behavior
moojek 67a4421
Refactor stdbigos clock API to return error_t
moojek 758875e
Run project formatter
moojek 3ac6a4e
Implement periodic clock and next-switch tick API
moojek ac94235
Clean up code
moojek 95b19c6
Enable only timer sie bit and remove unused CSR_SIE_STIE
moojek 26f9eaa
Use rdtime pseudoinstruction in hal_timer_now
moojek 68caca4
Rename for consistency
moojek 9bc7369
Move sbi_error_t to error_t mapping function to common util file
moojek 747c607
Adjust returns in timer
moojek ce4eafd
Add option to disable timer interrupts
moojek 37ce359
Remove redundant include
moojek a0d61d5
Fix formatting
moojek abed4ac
Add option to disable timer interrupts
moojek 62295a9
Remove redundant include
moojek 1becde7
Fix formatting
moojek 799398e
Merge branch 'zegar' of github.com:moojek/BigOS into zegar
moojek 3ff6e4c
Enhance documentation for clock API in clock.h
moojek 5769ac9
Add clock API documentation and update group annotations in header
moojek 5b5bdf2
Fix formatting of the clock.h header guard
moojek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| ===== | ||
| Clock | ||
| ===== | ||
|
|
||
| .. doxygengroup:: clock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,3 +10,4 @@ Stdbigos | |
| types | ||
| string | ||
| bitutils | ||
| clock | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
|
|
||
| /** | ||
| * @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 | ||
|
moojek marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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_ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) { | ||
|
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); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.