diff --git a/include/scheduler.hpp b/include/scheduler.hpp index 4cf0a6e7..20720f47 100644 --- a/include/scheduler.hpp +++ b/include/scheduler.hpp @@ -1,6 +1,6 @@ #pragma once - #include "config.hpp" +#include "util.hpp" #include @@ -15,24 +15,6 @@ void PendSV_Handler(); void SVC_Handler(); } -struct stack_registers { - unsigned R0{}; - unsigned R1{}; - unsigned R2{}; - unsigned R3{}; - unsigned R12{}; - unsigned LR{}; - unsigned RETURN_ADDR{}; - unsigned CTRL{0x01000000}; - unsigned FP_REGS[16]{}; - unsigned FPSCR{}; - - // diagram: https://shorturl.at/85lyY - unsigned RESERVED_FOR_STACK_ALIGNMENT[2]; - - stack_registers(unsigned return_addr) : RETURN_ADDR(return_addr) {} -}; - class Scheduler { unsigned current_task_index = 0; uint8_t slices_remaining = 1; @@ -43,7 +25,7 @@ class Scheduler { // ===== DO NOT REARRANGE THESE ===== etl::array stack{}; - stack_registers first_stack_frame; + exception_stack_registers first_stack_frame; // ================================== public: @@ -53,7 +35,10 @@ class Scheduler { // This is useful if we want to adjust the ratio of driver to process runtime uint8_t consecutive_quantums_to_run; - Task(const stack_registers& initial_stack_frame, uint8_t initial_priority) : + Task( + const exception_stack_registers& initial_stack_frame, + uint8_t initial_priority + ) : first_stack_frame(initial_stack_frame), consecutive_quantums_to_run(initial_priority) {} @@ -67,6 +52,7 @@ class Scheduler { void add_task(void (*function)(void), uint8_t priority = 1); void start_scheduler(); + void change_current_task_priority(uint8_t new_priority); void yield_current_task(); diff --git a/include/util.hpp b/include/util.hpp index 83e44e92..caff8f0e 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -7,4 +7,22 @@ using ProcessCallbackPtr = void (*)(int, int); using ProcessName = etl::string<20>; enum class FaultType { Usage, Bus, Memory }; +struct exception_stack_registers { + unsigned R0{}; + unsigned R1{}; + unsigned R2{}; + unsigned R3{}; + unsigned R12{}; + unsigned LR{}; + unsigned RETURN_ADDR{}; + unsigned CTRL{0x01000000}; + unsigned FP_REGS[16]{}; + unsigned FPSCR{}; + + // diagram: https://shorturl.at/85lyY + unsigned RESERVED_FOR_STACK_ALIGNMENT[2]{}; + + exception_stack_registers(unsigned return_addr) : RETURN_ADDR(return_addr) {} +}; + } // namespace edge diff --git a/src/main.cpp b/src/main.cpp index b99d0dc7..6df07f21 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,7 @@ #include #include -void task1(void) +void exception_task(void) { auto trigger_faults = []() { // Usage @@ -19,8 +19,6 @@ void task1(void) }; using namespace edge::userlib; - using namespace edge::drivers; - static void (*fault_handler)(edge::FaultType) = [](edge::FaultType type) { switch (type) { case edge::FaultType::Usage: @@ -35,6 +33,22 @@ void task1(void) } }; + set_fault_handler(fault_handler); + + trigger_faults(); + + set_led(2, 2, true); + + while (1) { + yield(); + } +} + +void task1(void) +{ + using namespace edge::userlib; + using namespace edge::drivers; + static void (*on_button_press)(ButtonType, ButtonState) = [](ButtonType type, ButtonState state) { if (state == ButtonState::DOWN) { @@ -48,10 +62,6 @@ void task1(void) get_button_pressed(ButtonType::A, on_button_press); get_button_pressed(ButtonType::B, on_button_press); - set_fault_handler(fault_handler); - - trigger_faults(); - while (1) { yield(); } @@ -86,6 +96,7 @@ int main(void) edge::FaultHandler::get(); + edge::scheduler.add_task(exception_task); edge::scheduler.add_task(task0); edge::scheduler.add_task(task1); diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 35dbe94a..5e633d12 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -27,7 +27,7 @@ void Scheduler::start_scheduler() void Scheduler::add_task(void (*function)(void), uint8_t priority) { task_stack.emplace_back( - stack_registers{reinterpret_cast(function)}, priority + exception_stack_registers{reinterpret_cast(function)}, priority ); } @@ -144,12 +144,13 @@ void Scheduler::yield_current_task() // This stack frame, originally created by the exception handler, will be popped // by restore() t.stack_ptr_loc = (unsigned*)__get_PSP(); - auto stored_registers = reinterpret_cast(t.stack_ptr_loc); + auto stored_registers = + reinterpret_cast(t.stack_ptr_loc); // "Push" registers, create a fake stack frame // This will be popped by the exception handler - t.stack_ptr_loc -= (sizeof(stack_registers) / sizeof(unsigned)); - auto new_registers = reinterpret_cast(t.stack_ptr_loc); + t.stack_ptr_loc -= (sizeof(exception_stack_registers) / sizeof(unsigned)); + auto new_registers = reinterpret_cast(t.stack_ptr_loc); new_registers->R0 = static_cast(arg1); new_registers->R1 = static_cast(arg2); diff --git a/src/svc.cpp b/src/svc.cpp index 072ff2b4..26176547 100644 --- a/src/svc.cpp +++ b/src/svc.cpp @@ -11,54 +11,54 @@ namespace edge { -// TODO: replace uint32_t* stack_ptr with an actual structure - void handle_yield() { scheduler.yield_current_task(); } -void handle_change_priority(uint32_t* stack_ptr) +void handle_change_priority(exception_stack_registers* stack_regs) { - scheduler.change_current_task_priority(stack_ptr[0]); + scheduler.change_current_task_priority(stack_regs->R0); } -etl::optional handle_driver_command(uint32_t* stack_ptr) +etl::optional handle_driver_command(exception_stack_registers* stack_regs) { - auto type = static_cast(stack_ptr[0]); - return drivers::handle_command(type, stack_ptr[1], stack_ptr[2], stack_ptr[3]); + auto type = static_cast(stack_regs->R0); + return drivers::handle_command( + type, stack_regs->R1, stack_regs->R2, stack_regs->R3 + ); } -void handle_driver_subscribe(uint32_t* stack_ptr) +void handle_driver_subscribe(exception_stack_registers* stack_regs) { - auto type = static_cast(stack_ptr[0]); - auto callback = reinterpret_cast(stack_ptr[1]); - int arg1 = stack_ptr[2]; - int arg2 = stack_ptr[3]; + auto type = static_cast(stack_regs->R0); + auto callback = reinterpret_cast(stack_regs->R1); + int arg1 = stack_regs->R2; + int arg2 = stack_regs->R3; return drivers::handle_subscribe( type, callback, arg1, arg2, scheduler.get_current_task() ); } -void handle_set_fault_handler(uint32_t* stack_ptr) +void handle_set_fault_handler(exception_stack_registers* stack_regs) { uint32_t current_task_id = scheduler.get_current_task(); - auto callback = reinterpret_cast(stack_ptr[0]); + auto callback = reinterpret_cast(stack_regs->R0); FaultHandler::get().set_fault_callback(current_task_id, callback); } -void handle_ipc(uint32_t* stack_ptr) +void handle_ipc(exception_stack_registers* stack_regs) { - auto type = static_cast(stack_ptr[0]); - auto name = reinterpret_cast(stack_ptr[1]); + auto type = static_cast(stack_regs->R0); + auto name = reinterpret_cast(stack_regs->R1); etl::string<20> name_str{name}; if (type == IPCCommandType::SEND) [[likely]] { - auto message = static_cast(stack_ptr[2]); + auto message = static_cast(stack_regs->R2); IPCManager::get().send_message(name_str, message); } else if (type == IPCCommandType::REGISTER) { - auto callback = reinterpret_cast(stack_ptr[2]); + auto callback = reinterpret_cast(stack_regs->R2); IPCManager::get().register_callback( scheduler.get_current_task(), name_str, callback ); @@ -68,26 +68,27 @@ void handle_ipc(uint32_t* stack_ptr) } } -etl::optional handle_call(uint32_t* stack_ptr) +etl::optional handle_call(exception_stack_registers* stack_regs) { - auto call_type = static_cast(((char*)stack_ptr[6])[-2]); + auto call_type = + static_cast(((char*)(stack_regs->RETURN_ADDR))[-2]); switch (call_type) { case SystemCallType::CHANGE_PRIORITY: - handle_change_priority(stack_ptr); + handle_change_priority(stack_regs); break; case SystemCallType::YIELD: handle_yield(); break; case SystemCallType::COMMAND: - return handle_driver_command(stack_ptr); + return handle_driver_command(stack_regs); case SystemCallType::SUBSCRIBE: - handle_driver_subscribe(stack_ptr); + handle_driver_subscribe(stack_regs); break; case edge::SystemCallType::IPC: - handle_ipc(stack_ptr); + handle_ipc(stack_regs); break; case edge::SystemCallType::SET_FAULT_HANDLER: - handle_set_fault_handler(stack_ptr); + handle_set_fault_handler(stack_regs); break; } return etl::nullopt; @@ -102,11 +103,11 @@ __attribute__((used)) void SVC_Handler(void) has_hit = true; return; } - uint32_t* SP_reg; - asm("MRS %0,PSP" : "=r"(SP_reg)); - auto ret_opt = handle_call(SP_reg); + exception_stack_registers* stack_regs; + asm("MRS %0,PSP" : "=r"(stack_regs)); + auto ret_opt = handle_call(stack_regs); if (ret_opt) { - SP_reg[0] = *ret_opt; + stack_regs->R0 = *ret_opt; } } }