Skip to content

Commit a7177f4

Browse files
authored
Merge pull request #50 from stevenewald/fix-reg-restore
Fix register restoration
2 parents 26acd41 + fe41e03 commit a7177f4

File tree

9 files changed

+34
-23
lines changed

9 files changed

+34
-23
lines changed

edge_os.ld

+8-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ SECTIONS
3232
{
3333
PROVIDE(__start_user_programs_data = .);
3434
_build/user_*.o(.data*)
35-
_build/user_*.o(.bss*)
35+
/* _build/user_*.o(.bss*)
36+
* bss needs to be within __bss_start__ and __bss_end__ to be zeroed by the c lib on startup
37+
* however, that makes it really really hard to isolate
38+
* I don't think this current isolation technique will work for bss, so I've enabled user read/write of all bss code
39+
* If we made a real OS, we would have a different binary for each program, but because this is a mini os, we didn't bother.
40+
*
41+
* Because of this reason (and discovering it during finals week), I have disabled the MPU
42+
* */
3643
PROVIDE(__end_user_programs_data = .);
3744
ASSERT((__end_user_programs_data - __start_user_programs_data) <= 16384, "Error: .user_programs_data section exceeds 16 KB");
3845
} > RAM

include/drivers/gpio_pin_event.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ class GPIOPinEvent {
1111
GPIOPinEvent(
1212
uint8_t pin, GPIOConfiguration resistance,
1313
aidan::GPIOEventController::GPIOEventCallback callback
14-
) : pin(pin)
14+
) :
15+
pin(pin)
1516
{
1617
// TODO: add resistance
1718
aidan::GPIOEventController::get().set_gpio_callback(

include/scheduler/scheduler.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22
#include "config.hpp"
3-
#include "util.hpp"
43
#include "task.hpp"
4+
#include "util.hpp"
55

66
#include <stdio.h>
77

@@ -31,6 +31,7 @@ class Scheduler {
3131
void change_current_task_priority(uint8_t new_priority);
3232

3333
void yield_current_task();
34+
void restore_current_task_regs(exception_stack_registers* regs);
3435

3536
private:
3637
void handle_first_svc_hit();

include/scheduler/task.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "config.hpp"
4+
#include "util.hpp"
45

56
namespace edge {
67

include/userlib/system_call_type.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ enum class SystemCallType : uint8_t {
99
COMMAND = 2,
1010
SUBSCRIBE = 3,
1111
IPC = 4,
12-
SET_FAULT_HANDLER = 5
12+
SET_FAULT_HANDLER = 5,
13+
RESTORE_REGS = 6
1314
};
1415
}

src/entrypoint.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ int main(void)
1616

1717
edge::FaultHandler::get();
1818

19-
edge::scheduler.add_task(exception_task);
19+
// edge::scheduler.add_task(exception_task);
2020

2121
edge::scheduler.add_task(ipc_part1);
2222
edge::scheduler.add_task(ipc_part2);

src/scheduler/mpu.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ MpuController& MpuController::get()
1919

2020
void MpuController::initialize_mpu() const
2121
{
22+
// MPU disabled. Read comment in linker script to see why
23+
return;
2224
auto user_code_start = reinterpret_cast<unsigned>(&__start_user_programs_code);
2325
MPU->RNR = 0;
2426
MPU->RBAR = (user_code_start & MPU_RBAR_ADDR_Msk);

src/scheduler/scheduler.cpp

+8-18
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
#include "drivers/driver_commands.hpp"
44
#include "nrf52833.h"
5-
#include "scheduler/pending_process_callbacks.hpp"
65
#include "scheduler/mpu.hpp"
6+
#include "scheduler/pending_process_callbacks.hpp"
7+
#include "userlib/system_call_type.hpp"
78
#include "util.hpp"
89

910
namespace edge {
@@ -22,6 +23,7 @@ void Scheduler::start_scheduler()
2223

2324
NVIC_SetPriority(PendSV_IRQn, 0x3);
2425
NVIC_SetPriority(SysTick_IRQn, 0x1);
26+
2527
MpuController::get().initialize_mpu();
2628
asm volatile("CPSIE I");
2729
asm volatile("SVC #0");
@@ -115,24 +117,12 @@ __attribute__((used)) void SysTick_Handler()
115117
// I don't think there's any way to make this cleaner lol
116118
__attribute__((used, naked)) USER_CODE void restore_regs()
117119
{
118-
// Load fpscr first so we can avoid dirtying r0 after its popped
119-
asm volatile("ldr r0, [sp, #96]\n"
120-
"vmsr fpscr, r0\n");
121-
122-
// Pop regs as usual
123-
asm volatile("pop {r0, r1, r2, r3, r12, lr}");
124-
125-
// Skip SP and RETPSR. SP will be loaded last
126-
// RETPSR should be ignored because we already popped when returning from exception
127-
asm volatile("add sp, #8");
128-
129-
// Pop caller saved FP registers
130-
asm volatile("vpop {s0-s15}");
131-
132-
// Skip FPSCR and 2 reserved regs
133-
asm volatile("add sp, #12");
120+
asm volatile("svc %0" ::"I"(SystemCallType::RESTORE_REGS));
121+
}
134122

135-
asm volatile("ldr pc, [sp, #-84]");
123+
void Scheduler::restore_current_task_regs(exception_stack_registers* regs)
124+
{
125+
__set_PSP(reinterpret_cast<unsigned>(&regs[1]) + 4);
136126
}
137127

138128
void Scheduler::yield_current_task()

src/svc/svc.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ void handle_ipc(exception_stack_registers* stack_regs)
6868
}
6969
}
7070

71+
void restore_regs(exception_stack_registers* stack_regs)
72+
{
73+
scheduler.restore_current_task_regs(stack_regs);
74+
}
75+
7176
etl::optional<int> handle_call(exception_stack_registers* stack_regs)
7277
{
7378
auto call_type =
@@ -89,6 +94,9 @@ etl::optional<int> handle_call(exception_stack_registers* stack_regs)
8994
case edge::SystemCallType::SET_FAULT_HANDLER:
9095
handle_set_fault_handler(stack_regs);
9196
break;
97+
case edge::SystemCallType::RESTORE_REGS:
98+
restore_regs(stack_regs);
99+
break;
92100
}
93101
return etl::nullopt;
94102
}

0 commit comments

Comments
 (0)