Skip to content

Commit

Permalink
Timer test
Browse files Browse the repository at this point in the history
  • Loading branch information
robotman2412 committed Aug 28, 2024
1 parent 387ae7e commit dbbc32e
Show file tree
Hide file tree
Showing 32 changed files with 746 additions and 458 deletions.
2 changes: 1 addition & 1 deletion common/badgelib
Submodule badgelib updated 1 files
+2 −2 include/arrays.h
1 change: 0 additions & 1 deletion kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ add_executable(${target}
${CMAKE_CURRENT_LIST_DIR}/src/process/syscall_util.c

${CMAKE_CURRENT_LIST_DIR}/src/scheduler/scheduler.c
${CMAKE_CURRENT_LIST_DIR}/src/scheduler/syscall_impl.c

${CMAKE_CURRENT_LIST_DIR}/src/housekeeping.c
${CMAKE_CURRENT_LIST_DIR}/src/main.c
Expand Down
1 change: 1 addition & 0 deletions kernel/cpu/riscv/include/cpu/riscv_pmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// This file expects RISCV_PMP_REGION_COUNT to be defined by "port/hardware.h".

#include "assertions.h"
#include "attributes.h"
#include "meta.h"
#include "port/hardware.h"
#include "port/hardware_allocation.h"
Expand Down
4 changes: 2 additions & 2 deletions kernel/cpu/riscv/src/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void sched_raise_from_isr(sched_thread_t *thread, bool syscall, void *entry_poin
// Requests the scheduler to prepare a switch from kernel to userland for a user thread.
// Resumes the userland thread where it left off.
void sched_lower_from_isr() {
sched_thread_t *thread = sched_current_thread_unsafe();
sched_thread_t *thread = sched_current_thread();
process_t *process = thread->process;
assert_dev_drop(!(thread->flags & THREAD_KERNEL) && (thread->flags & THREAD_PRIVILEGED));
atomic_fetch_and(&thread->flags, ~THREAD_PRIVILEGED);
Expand Down Expand Up @@ -144,7 +144,7 @@ bool sched_signal_enter(size_t handler_vaddr, size_t return_vaddr, int signum) {
// Exits a signal handler in the current thread.
// Returns false if the process cannot be resumed.
bool sched_signal_exit() {
sched_thread_t *thread = sched_current_thread_unsafe();
sched_thread_t *thread = sched_current_thread();
if (!(atomic_fetch_and(&thread->flags, ~THREAD_SIGHANDLER) & THREAD_SIGHANDLER)) {
return false;
}
Expand Down
49 changes: 49 additions & 0 deletions kernel/include/badgelib/hwtimer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

// SPDX-License-Identifier: MIT

#pragma once

#include "attributes.h"

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

#define FREQUENCY_HZ_MIN INT32_MIN
#define FREQUENCY_HZ_MAX INT32_MAX
#define TIMER_VALUE_MIN INT64_MIN
#define TIMER_VALUE_MAX INT64_MAX

typedef int32_t frequency_hz_t;
typedef int64_t timer_value_t;

// Initialise timer and watchdog subsystem.
void timer_init();
// Get the number of hardware timers.
int timer_count() CONST;
// Get the IRQ number for a timer.
int timer_get_irq(int timerno);
// Set the counting frequency of a hardware timer.
void timer_set_freq(int timerno, frequency_hz_t frequency);

// Configure and enable timer alarm.
void timer_alarm_config(int timerno, timer_value_t threshold, bool reset_on_alarm);
// Disable timer alarm.
void timer_alarm_disable(int timerno);
// Get the current value of timer.
timer_value_t timer_value_get(int timerno);
// Set the current value of timer.
void timer_value_set(int timerno, timer_value_t value);
// Enable the timer counting.
void timer_start(int timerno);
// Disable the timer counting.
void timer_stop(int timerno);

// Check whether timer has interrupts enabled.
bool timer_int_enabled(int timerno);
// Enable / disable timer interrupts.
void timer_int_enable(int timerno, bool enable);
// Check whether timer interrupt had fired.
bool timer_int_pending(int timerno);
// Clear timer interrupt.
void timer_int_clear(int timerno);
49 changes: 8 additions & 41 deletions kernel/include/badgelib/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,24 @@

#pragma once

#include "attributes.h"
#include "port/hardware_allocation.h"

#include <stdatomic.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#define FREQUENCY_HZ_MIN INT32_MIN
#define FREQUENCY_HZ_MAX INT32_MAX
#define TIMESTAMP_US_MIN INT64_MIN
#define TIMESTAMP_US_MAX INT64_MAX
#define TIMER_VALUE_MIN INT64_MIN
#define TIMER_VALUE_MAX INT64_MAX

typedef int32_t frequency_hz_t;
typedef int64_t timestamp_us_t;
typedef int64_t timer_value_t;

typedef void (*timer_fn_t)(void *cookie);

// Initialise timer and watchdog subsystem.
void time_init();
void time_init();
// Sets the alarm time when the next task switch should occur.
void time_set_next_task_switch(timestamp_us_t timestamp);

// Get the number of hardware timers.
#define timer_count() (2)
// Set the counting frequency of a hardware timer.
void timer_set_freq(int timerno, frequency_hz_t frequency);


// Configure and enable timer alarm.
void timer_alarm_config(int timerno, timer_value_t threshold, bool reset_on_alarm);
// Disable timer alarm.
void timer_alarm_disable(int timerno);
// Get the current value of timer.
timer_value_t timer_value_get(int timerno);
// Set the current value of timer.
void timer_value_set(int timerno, timer_value_t value);
// Enable the timer counting.
void timer_start(int timerno);
// Disable the timer counting.
void timer_stop(int timerno);

// Check whether timer has interrupts enabled.
bool timer_int_enabled(int timerno);
// Enable / disable timer interrupts.
void timer_int_enable(int timerno, bool enable);
// Check whether timer interrupt had fired.
bool timer_int_pending(int timerno);
// Clear timer interrupt.
void timer_int_clear(int timerno);

void time_set_next_task_switch(timestamp_us_t timestamp);
// Attach a task to a timer interrupt.
int64_t time_add_async_task(timestamp_us_t timestamp, timer_fn_t task, void *cookie);
// Cancel a task created with `time_add_async_task`.
bool time_cancel_async_task(int64_t taskno);
// Get current time in microseconds.
timestamp_us_t time_us();
9 changes: 0 additions & 9 deletions kernel/include/scheduler/isr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,5 @@

#pragma once

#include "attributes.h"
#include "badge_err.h"

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



// Requests the scheduler to prepare a switch from inside an interrupt routine.
void sched_request_switch_from_isr();
34 changes: 22 additions & 12 deletions kernel/include/scheduler/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ void sched_exec() NORETURN;
// Exit the scheduler and subsequenty shut down the CPU.
void sched_exit(int cpu);


// Returns the current thread ID.
tid_t sched_current_tid();
// Returns the current thread struct.
sched_thread_t *sched_current_thread();
// Returns the associated thread struct.
sched_thread_t *sched_get_thread(tid_t thread);

// Create a new suspended userland thread.
// If `kernel_stack_bottom` is NULL, the scheduler will allocate a stack.
tid_t thread_new_user(
Expand All @@ -65,26 +73,28 @@ tid_t thread_new_kernel(badge_err_t *ec, char const *name, sched_entry_t entry_p
// Do not wait for thread to be joined; clean up immediately.
void thread_detach(badge_err_t *ec, tid_t thread);

// Pauses execution of a user thread.
void thread_suspend(badge_err_t *ec, tid_t thread);
// Explicitly yield to the scheduler; the scheduler may run other threads without waiting for preemption.
// Use this function to reduce the CPU time used by a thread.
void thread_yield(void);
// Sleep for an amount of microseconds.
void thread_sleep(timestamp_us_t delay);

// Pauses execution of a thread.
// If `suspend_kernel` is false, the thread won't be suspended until it enters user mode.
void thread_suspend(badge_err_t *ec, tid_t thread, bool suspend_kernel);
// Resumes a previously suspended thread or starts it.
void thread_resume(badge_err_t *ec, tid_t thread);
// Resumes a previously suspended thread or starts it.
// Immediately schedules the thread instead of putting it in the queue first.
void thread_resume_now(badge_err_t *ec, tid_t thread);
// Resumes a previously suspended thread or starts it from an ISR.
void thread_resume_from_isr(badge_err_t *ec, tid_t thread);
// Resumes a previously suspended thread or starts it from an ISR.
// Immediately schedules the thread instead of putting it in the queue first.
void thread_resume_now_from_isr(badge_err_t *ec, tid_t thread);
// Returns whether a thread is running; it is neither suspended nor has it exited.
bool thread_is_running(badge_err_t *ec, tid_t thread);

// Returns the current thread ID.
tid_t sched_current_tid();
// Returns the current thread struct.
sched_thread_t *sched_current_thread();
// Returns the associated thread struct.
sched_thread_t *sched_get_thread(tid_t thread);

// Explicitly yield to the scheduler; the scheduler may run other threads without waiting for preemption.
// Use this function to reduce the CPU time used by a thread.
void sched_yield(void);
// Exits the current thread.
// If the thread is detached, resources will be cleaned up.
void thread_exit(int code) NORETURN;
Expand Down
7 changes: 3 additions & 4 deletions kernel/include/scheduler/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@
#define THREAD_STARTNOW (1 << 6)
// The thread should be suspended.
#define THREAD_SUSPENDING (1 << 7)
// The thread should be suspended even if it is a kernel thread.
#define THREAD_KSUSPEND (1 << 8)
// The thread has exited and is awaiting join.
#define THREAD_EXITED (1 << 8)
#define THREAD_EXITED (1 << 9)

// The scheduler is starting on this CPU.
#define SCHED_STARTING (1 << 0)
Expand Down Expand Up @@ -107,6 +109,3 @@ struct sched_cpulocal_t {
// Idle thread.
sched_thread_t idle_thread;
};

// Returns the current thread without using a critical section.
sched_thread_t *sched_current_thread_unsafe();
2 changes: 2 additions & 0 deletions kernel/include/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ bool smp_poweroff();
bool smp_pause();
// Resume another CPU, if supported.
bool smp_resume(int cpu);
// Whether a CPU can be powered off at runtime.
bool smp_can_poweroff(int cpu);
20 changes: 0 additions & 20 deletions kernel/port/esp32c6/include/port/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,6 @@
#define RISCV_VT_TCAUSE_MASK 31


/* ==== SOC INFO ==== */

// Number of timer groups.
#define ESP_TIMG_COUNT 2
// Number of timers per timer group.
#define ESP_TIMG_TIMER_COUNT 1
// Speed of RC_FAST_CLK in hertz.
#define ESP_FREQ_RC_FAST_CLK 20000000
// Speed of XTAL_CLK in hertz.
#define ESP_FREQ_XTAL_CLK 40000000
// Speed of RC32K_CLK in hertz.
#define ESP_FREQ_RC32K_CLK 32000
// Speed of XTAL32K_CLK in hertz.
#define ESP_FREQ_XTAL32K_CLK 32000
// Speed of RC_SLOW_CLK in hertz.
#define ESP_FREQ_RC_SLOW_CLK 150000
// Speed of OSC_SLOW_CLK in hertz.
#define ESP_FREQ_OSC_SLOW_CLK 32000


/* ==== PERIPHERAL MAP ==== */

// Base address of peripherals.
Expand Down
4 changes: 2 additions & 2 deletions kernel/port/esp32c6/include/port/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@

#define EXT_IRQ_COUNT ETS_MAX_INTR_SOURCE

// Set the external interrupt signal for CPU0 timer IRQs.
void set_cpu0_timer_irq(int timer_irq);
// Set the external interrupt signal for CPU timer IRQs.
void set_cpu_timer_irq(int cpu, int timer_irq);
27 changes: 15 additions & 12 deletions kernel/port/esp32c6/src/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,20 @@ void riscv_interrupt_handler() {
return;
}

// Check pending interrupts.
for (int i = 0; i < ETS_MAX_INTR_SOURCE / 32; i++) {
uint32_t pending = INTMTX.status[i];
int lsb_pos = __builtin_clz(pending);
int irq = i * 32 + lsb_pos;
if (irq_ch_is_enabled(irq)) {
// Jump to ISR.
if (isr_table[mcause]) {
isr_table[mcause](irq);
} else {
logkf_from_isr(LOG_FATAL, "Unhandled interrupt %{d}", mcause);
panic_abort();
while (pending) {
int lsb_pos = __builtin_ctz(pending);
pending ^= 1 << lsb_pos;
int irq = i * 32 + lsb_pos;
if (irq && irq_ch_is_enabled(irq)) {
// Jump to ISR.
if (isr_table[irq]) {
isr_table[irq](irq);
} else {
logkf_from_isr(LOG_FATAL, "Unhandled interrupt %{d}", irq);
panic_abort();
}
}
}
}
Expand All @@ -104,7 +106,8 @@ void riscv_interrupt_handler() {


// Set the external interrupt signal for CPU0 timer IRQs.
void set_cpu0_timer_irq(int timer_irq) {
void set_cpu_timer_irq(int cpu, int timer_irq) {
(void)cpu;
INTMTX.route[timer_irq] = TIMER_IRQ_CH;
}

Expand All @@ -123,7 +126,7 @@ void irq_ch_disable(int irq) {
// Query whether the IRQ is enabled.
bool irq_ch_is_enabled(int irq) {
assert_dev_drop(irq > 0 && irq < ETS_MAX_INTR_SOURCE);
return INTMTX.route[irq] != 0;
return INTMTX.route[irq] == EXT_IRQ_CH;
}

// Set the interrupt service routine for an interrupt on this CPU.
Expand Down
6 changes: 6 additions & 0 deletions kernel/port/esp32c6/src/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,9 @@ bool smp_resume(int cpu) {
(void)cpu;
return false;
}

// Whether a CPU can be powered off at runtime.
bool smp_can_poweroff(int cpu) {
(void)cpu;
return false;
}
8 changes: 0 additions & 8 deletions kernel/port/esp32p4/include/port/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,3 @@
#define RISCV_VT_ICAUSE_MASK 63
// Bitmask for trap cause.
#define RISCV_VT_TCAUSE_MASK 31


/* ==== SOC INFO ==== */

// Number of timer groups.
#define ESP_TIMG_COUNT 2
// Number of timers per timer group.
#define ESP_TIMG_TIMER_COUNT 1
6 changes: 2 additions & 4 deletions kernel/port/esp32p4/include/port/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@

#define EXT_IRQ_COUNT ETS_MAX_INTR_SOURCE

// Set the external interrupt signal for CPU0 timer IRQs.
void set_cpu0_timer_irq(int timer_irq);
// Set the external interrupt signal for CPU1 timer IRQs.
void set_cpu1_timer_irq(int timer_irq);
// Set the external interrupt signal for CPU timer IRQs.
void set_cpu_timer_irq(int cpu, int timer_irq);
Loading

0 comments on commit dbbc32e

Please sign in to comment.