Skip to content

Commit

Permalink
Merge pull request #27 from stevenewald/mpu
Browse files Browse the repository at this point in the history
Add MPU Support
  • Loading branch information
stevenewald authored Nov 15, 2024
2 parents eee1d5b + 226a5ba commit 88fb3b4
Show file tree
Hide file tree
Showing 20 changed files with 363 additions and 187 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ ETL_INCLUDES += ./external/etl/include/etl/unordered_map.h
# Source and header files
APP_HEADER_PATHS += ./include
APP_SOURCE_PATHS += ./src
APP_SOURCES = $(notdir $(wildcard src/*.cpp))
APP_SOURCE_PATHS += ./src/user
APP_SOURCES = $(notdir $(wildcard src/*.cpp src/user/*.cpp))

# Path to base of nRF52x-base repo
NRF_BASE_DIR = external/nrf52x-base/

# Include board Makefile (if any)
include external/microbit_v2/Board.mk

LINKER_SCRIPT = edge_os.ld

# Include main Makefile
include $(NRF_BASE_DIR)/make/AppMakefile.mk

Expand Down
70 changes: 70 additions & 0 deletions edge_os.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* Linker script to configure memory regions. */
/* Only for gcc nrf52833 with 128kb ram and 512kb flash */

SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)

MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x20000
}

FLASH_PAGE_SIZE = 4096;
FLASH_DATA_PAGES_USED = 4;

SECTIONS
{
. = ALIGN(4);
.svc_data :
{
PROVIDE(__start_svc_data = .);
KEEP(*(.svc_data))
PROVIDE(__stop_svc_data = .);
} > RAM
.log_dynamic_data :
{
PROVIDE(__start_log_dynamic_data = .);
KEEP(*(SORT(.log_dynamic_data*)))
PROVIDE(__stop_log_dynamic_data = .);
} > RAM
.user_programs_data ALIGN(16384) :
{
PROVIDE(__start_user_programs_data = .);
_build/user_*.o(.data*)
_build/user_*.o(.bss*)
PROVIDE(__end_user_programs_data = .);
ASSERT((__end_user_programs_data - __start_user_programs_data) <= 16384, "Error: .user_programs_data section exceeds 16 KB");
} > RAM
} INSERT AFTER .data;

SECTIONS
{
.log_const_data :
{
PROVIDE(__start_log_const_data = .);
KEEP(*(SORT(.log_const_data*)))
PROVIDE(__stop_log_const_data = .);
} > FLASH
/* TODO: make sure this doesnt cause duplication? */
.user_programs_code ALIGN(16384) :
{
PROVIDE(__start_user_programs_code = .);
_build/user_*.o(.text*)
_build/user_*.o(.rodata*)
KEEP(*(.user_code))
PROVIDE(__end_user_programs_code = .);
ASSERT((__end_user_programs_code - __start_user_programs_code) <= 16384, "Error: .user_programs_code section exceeds 16 KB");
} > FLASH
} INSERT AFTER .text

SECTIONS
{
__stop_ot_flash_data = (ORIGIN(FLASH) + LENGTH(FLASH) - FLASH_PAGE_SIZE);
__start_ot_flash_data = (__stop_ot_flash_data - (FLASH_PAGE_SIZE * FLASH_DATA_PAGES_USED));

/* Assure that code does not overlap flash data area.*/
ASSERT((__start_ot_flash_data >= __etext + SIZEOF(.data)), "Error: Code overlaps flash data area.")
}

INCLUDE "nrf_common.ld"
3 changes: 2 additions & 1 deletion include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

namespace edge {
constexpr uint8_t MAX_PROCESSES = 10;
}
constexpr size_t STACK_SIZE_BYTES = 2048;
} // namespace edge
2 changes: 1 addition & 1 deletion include/ipc/ipc_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace edge {
class IPCManager {
etl::unordered_map<etl::string<20>, uint8_t, MAX_PROCESSES> name_to_id;
etl::unordered_map<ProcessName, uint8_t, MAX_PROCESSES> name_to_id;
etl::array<ProcessCallbackPtr, MAX_PROCESSES> ipc_communicators{nullptr};

IPCManager() = default;
Expand Down
69 changes: 0 additions & 69 deletions include/scheduler.hpp

This file was deleted.

25 changes: 25 additions & 0 deletions include/scheduler/mpu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "config.hpp"

namespace edge {
class MpuController {
MpuController() { }

~MpuController() { disable_mpu(); };

void disable_mpu() const;

public:
void initialize_mpu() const;

MpuController(const MpuController&) = delete;
MpuController(MpuController&&) = delete;
MpuController& operator=(const MpuController&) = delete;
MpuController& operator=(MpuController&&) = delete;

static MpuController& get();

void set_program_stack_start(const unsigned* stack_ptr) const;
};
} // namespace edge
44 changes: 44 additions & 0 deletions include/scheduler/scheduler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once
#include "config.hpp"
#include "util.hpp"
#include "task.hpp"

#include <stdio.h>

#include <cstdint>

static constexpr size_t QUANTUM_MILLIS = 5;

namespace edge {
extern "C" {
void PendSV_Handler();
void SVC_Handler();
}

class Scheduler {
unsigned current_task_index = 0;
uint8_t slices_remaining = 1;

etl::vector<Task, MAX_PROCESSES> task_stack{};

public:
unsigned get_current_task() const { return current_task_index; }

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();

private:
void handle_first_svc_hit();

friend void PendSV_Handler(void);
friend void SVC_Handler(void);
};

extern Scheduler scheduler;

} // namespace edge
34 changes: 34 additions & 0 deletions include/scheduler/task.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "config.hpp"

namespace edge {

class Task {
static constexpr size_t STACK_SIZE_IN_UNSIGNED =
(STACK_SIZE_BYTES / sizeof(unsigned)) - sizeof(exception_stack_registers)
- sizeof(unsigned*) - sizeof(uint8_t);

public:
// ===== DO NOT REARRANGE THESE =====
// Align for MPU purposes
alignas(STACK_SIZE_BYTES) etl::array<unsigned, STACK_SIZE_IN_UNSIGNED> stack{};
exception_stack_registers first_stack_frame;
// ==================================

// needs to point to first_stack_frame
unsigned* stack_ptr_loc{&first_stack_frame.R0};

// This is useful if we want to adjust the ratio of driver to process runtime
uint8_t consecutive_quantums_to_run;

Task(
const exception_stack_registers& initial_stack_frame, uint8_t initial_priority
) :
first_stack_frame(initial_stack_frame),
consecutive_quantums_to_run(initial_priority)
{}
};

static_assert(sizeof(Task) <= STACK_SIZE_BYTES);
} // namespace edge
13 changes: 2 additions & 11 deletions include/userlib/syscalls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,14 @@ void get_button_pressed(
void (*callback)(drivers::ButtonType, drivers::ButtonState)
);

void send_ipc(const ProcessName& name, uint32_t message);
void send_ipc(const char* name, uint32_t message);

void subscribe_ipc(const ProcessName& name, void (*callback)(int message));
void subscribe_ipc(const char* name, void (*callback)(int message));

void set_fault_handler(void (*callback)(FaultType));

// We need a syscall for this because SVC will not be preempted by SysTick
// Technically this is insecure - it's mostly for debugging
void debug_print(const char* string);

// yeah i know
template <size_t Length>
inline void debug_println(const etl::string<Length>& str)
{
etl::string<Length + 1> str2 = str;
str2 += "\n";
debug_print(str2.data());
}

} // namespace edge::userlib
2 changes: 2 additions & 0 deletions include/util.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#define USER_CODE __attribute__((section(".user_code")))

namespace edge {
[[noreturn]] void panic(const char* reason);

Expand Down
2 changes: 1 addition & 1 deletion src/fault_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "nrf52.h"
#include "pending_process_callbacks.hpp"
#include "scheduler.hpp"
#include "scheduler/scheduler.hpp"

#include <stdio.h>

Expand Down
Loading

0 comments on commit 88fb3b4

Please sign in to comment.