Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions jocktos/inc/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@
typedef struct {
volatile bool pending;
volatile uint32_t tick_count;
volatile TaskControlBlock* running; ///< Currently running task
volatile TaskControlBlock* ready; ///< Singly linked list of tasks ready to run, in decending order of priority
volatile TaskControlBlock* suspended; ///< Singly linked list of suspended tasks, in decending order of priority
volatile TaskControlBlock* terminated; ///< Currently running task
volatile TaskControlBlock* running; ///< Currently running task
volatile TaskControlBlock* ready; ///< Singly linked list of tasks ready to run, in decending order of priority
volatile TaskControlBlock* suspended; ///< Singly linked list of suspended tasks, in decending order of priority
} Scheduler;

/**
Expand Down
3 changes: 2 additions & 1 deletion jocktos/inc/tcb.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ typedef enum {
RUNNING = 0, ///< The task is currently executing on the CPU with priority over others.
READY = 1, ///< The task is ready and waiting for execution by the scheduler.
BLOCKED = 2, ///< The task is waiting for a resource (e.g., semaphore, mutex) to become available.
SUSPENDED = 3 ///< The task is temporarily inactive and can be reactivated by an event.
SUSPENDED = 3, ///< The task is temporarily inactive and can be reactivated by an event.
TERMINATED = 4 ///< The task has been terminated and is no longer executing.
} TaskState;

/**
Expand Down
40 changes: 32 additions & 8 deletions jocktos/src/os.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@

/* -- Defines ------------------------------------------------------------- */

#define FILL 0xBABEFACE // for task allocation debugging
#define CANARY 0xDEADBEEF
#define CANARY_SIZE 16
#define TRIGGER_PendSV *(uintptr_t volatile *)0xE000ED04 = (1U << 28)

/* -- Types --------------------------------------------------------------- */

/* -- Private Function Declarations --------------------------------------- */
/**
* \details Safely catches an unexpected return from a task.
* Any task that returns is marked as 'terminated' and moved accordingly.
*
*/
void task_exit_guard(void);

/**
* \brief Updates the task control blocks stack_usage
Expand Down Expand Up @@ -182,8 +191,7 @@ void initializeStack(TaskControlBlock* tcb) {
// - non-critical registers are initialized to their index
*(--stack_ptr) = (1U << 24); ///< Set thumb state bit in EPSR
*(--stack_ptr) = (uintptr_t)tcb->task_handle; ///< Set PC to task function handle
*(--stack_ptr) = 0xFFFFFFF9U; ///< Set LR register for MSP thread mode
// *(--stack_ptr) = 0xFFFFFFFDU; ///< Set LR register for PSP thread mode
*(--stack_ptr) = (uintptr_t)task_exit_guard; // LR: Return trap
*(--stack_ptr) = 0x0000000CU; ///< Set R12 register deafult to its index
*(--stack_ptr) = 0x00000003U; ///< Set R3 register deafult to its index
*(--stack_ptr) = 0x00000002U; ///< Set R2 register deafult to its index
Expand All @@ -201,11 +209,11 @@ void initializeStack(TaskControlBlock* tcb) {
*(--stack_ptr) = 0x00000004U; ///< Set R4 register deafult to its index
tcb->stack_pointer = stack_ptr;
// Fill unused process stack with known value
while (stack_ptr > tcb->stack_overflow + 8) {
*(--stack_ptr) = 0xBABEFACEU;
while (stack_ptr > tcb->stack_overflow + CANARY_SIZE) {
*(--stack_ptr) = FILL;
}
while (stack_ptr > tcb->stack_overflow) {
*(--stack_ptr) = 0xDEADBEEFU; ///< set top 8 bytes to something else
*(--stack_ptr) = CANARY; ///< set top 8 bytes to something else
}
}

Expand All @@ -224,7 +232,17 @@ void SysTick_Handler(void) {
uint32_t primask;
primask = jock_os_enter_critical_section();
JOCKTOSScheduler.tick_count++;
jock_os_switch_running_task(&JOCKTOSScheduler.ready);
TaskControlBlock** dest = &JOCKTOSScheduler.ready;
TaskControlBlock* tcb = JOCKTOSScheduler.running;
uint32_t* ptr = (uint32_t*)tcb->stack_overflow + CANARY_SIZE;
for (int i = 0; i < CANARY_SIZE; i++) {
if (*(--ptr) != CANARY) {
if (tcb == &usr_main_tcb) break; // ignore stack canary for main [TODO]
dest = &JOCKTOSScheduler.terminated;
break;
}
}
jock_os_switch_running_task(dest);
jock_os_leave_critical_section(primask);

}
Expand Down Expand Up @@ -294,7 +312,7 @@ void monitorJOCKTOS(void* arg) {
}


void idleJOCKTOS(void* arg) {
void idleJOCKTOS(void* arg __attribute__((unused))) {
/* Disable interrupts to make sure that the busy flag does not get
modified between the check in the while condition and the system
sleep */
Expand Down Expand Up @@ -351,4 +369,10 @@ void idleJOCKTOS(void* arg) {
// TODO: Figure out how to low power
}


__attribute__((noreturn))
void task_exit_guard(void) {
uint32_t primask = jock_os_enter_critical_section();
JOCKTOSScheduler.running->state = TERMINATED;
jock_os_switch_running_task(&JOCKTOSScheduler.terminated);
jock_os_leave_critical_section(primask);
}