|
@@ -0,0 +1,196 @@
|
|
|
+#include "all-headers.h"
|
|
|
+
|
|
|
+
|
|
|
+#define ENABLE_XTR_ASSERTIONS
|
|
|
+
|
|
|
+
|
|
|
+#ifdef ENABLE_XTR_ASSERTIONS
|
|
|
+ #define XTR_ASSERT_NON_NULL_POINTER(ptr) assertNonNullPointer (ptr, __FILE__, __LINE__) ;
|
|
|
+#else
|
|
|
+ #define XTR_ASSERT_NON_NULL_POINTER(ptr)
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+#ifdef ENABLE_XTR_ASSERTIONS
|
|
|
+ #define XTR_ASSERT(condition,value) assertion (condition, value, __FILE__, __LINE__) ;
|
|
|
+#else
|
|
|
+ #define XTR_ASSERT(condition,value)
|
|
|
+#endif
|
|
|
+
|
|
|
+// CORTEX-M4 EXCEPTION FRAME (WITHOUT FLOATING-POINT STORAGE) *
|
|
|
+// *
|
|
|
+// PSP+32 -> | | *
|
|
|
+// |----------------------------| \ *
|
|
|
+// PSP+28 -> | xPSR | | *
|
|
|
+// |----------------------------| | *
|
|
|
+// PSP+24 -> | PC (after SVC instruction) | | *
|
|
|
+// |----------------------------| | *
|
|
|
+// PSP+20 -> | LR | | *
|
|
|
+// |----------------------------| | *
|
|
|
+// PSP+16 -> | R12 | | Saved by interrupt response *
|
|
|
+// |----------------------------| | *
|
|
|
+// PSP+12 -> | R3 | | *
|
|
|
+// |----------------------------| | *
|
|
|
+// PSP+8 -> | R2 | | *
|
|
|
+// |----------------------------| | *
|
|
|
+// PSP+4 -> | R1 | | *
|
|
|
+// |----------------------------| | *
|
|
|
+// /---- PSP ----> | R0 | | *
|
|
|
+// | |----------------------------| / *
|
|
|
+// | *
|
|
|
+// | *---------------------*
|
|
|
+// | | LR return code | +36 [ 9]
|
|
|
+// | *---------------------*
|
|
|
+// \-----------------------------------------------| R13 (PSP) | +32 [ 8]
|
|
|
+// *---------------------*
|
|
|
+// | R11 | +28 [ 7]
|
|
|
+// *---------------------*
|
|
|
+// | R10 | +24 [ 6]
|
|
|
+// *---------------------*
|
|
|
+// | R9 | +20 [ 5]
|
|
|
+// *---------------------*
|
|
|
+// | R8 | +16 [ 4]
|
|
|
+// *---------------------*
|
|
|
+// | R7 | +12 [ 3]
|
|
|
+// *---------------------*
|
|
|
+// | R6 | + 8 [ 2]
|
|
|
+// *---------------------*
|
|
|
+// | R5 | + 4 [ 1]
|
|
|
+// *---------------------------------------* *---------------------*
|
|
|
+// | var.running.task.control.block.ptr +------> | R4 | + 0 [ 0]
|
|
|
+// *---------------------------------------* *---------------------*
|
|
|
+//
|
|
|
+//----------------------------------------------------------------------------------------------------------------------
|
|
|
+
|
|
|
+typedef struct {
|
|
|
+ uint32_t mR0 ;
|
|
|
+ uint32_t mR1 ;
|
|
|
+ uint32_t mR2 ;
|
|
|
+ uint32_t mR3 ;
|
|
|
+ uint32_t mR12 ;
|
|
|
+ uint32_t mLR ;
|
|
|
+ uint32_t mPC ;
|
|
|
+ uint32_t mXPSR ;
|
|
|
+} ExceptionFrame_without_floatingPointStorage ;
|
|
|
+
|
|
|
+typedef struct {
|
|
|
+ uint32_t mR4 ;
|
|
|
+ uint32_t mR5 ;
|
|
|
+ uint32_t mR6 ;
|
|
|
+ uint32_t mR7 ;
|
|
|
+ uint32_t mR8 ;
|
|
|
+ uint32_t mR9 ;
|
|
|
+ uint32_t mR10 ;
|
|
|
+ uint32_t mR11 ;
|
|
|
+ ExceptionFrame_without_floatingPointStorage * mPSP ; // R13
|
|
|
+ uint32_t mLR_RETURN_CODE ;
|
|
|
+} TaskContext ;
|
|
|
+
|
|
|
+
|
|
|
+static void kernel_set_task_context (INIT_MODE_
|
|
|
+ TaskContext & ioTaskContext,
|
|
|
+ const uint32_t inStackBufferAddress,
|
|
|
+ const uint32_t inStackBufferSize,
|
|
|
+ RoutineTaskType inTaskRoutine) {
|
|
|
+
|
|
|
+ // Initialize LR
|
|
|
+ ioTaskContext.mLR_RETURN_CODE = 0xFFFFFFFD ;
|
|
|
+
|
|
|
+ // Stack Pointer initial value
|
|
|
+ uint32_t initialTopOfStack = inStackBufferAddress + inStackBufferSize ;
|
|
|
+ initialTopOfStack -= sizeof (ExceptionFrame_without_floatingPointStorage) ;
|
|
|
+
|
|
|
+ // Initialize SP
|
|
|
+ auto ptr = (ExceptionFrame_without_floatingPointStorage *) initialTopOfStack ;
|
|
|
+ ioTaskContext.mPSP = ptr ;
|
|
|
+
|
|
|
+ // Initialize PC
|
|
|
+ ptr->mPC = (uint32_t) inTaskRoutine ;
|
|
|
+
|
|
|
+ // Initialize CPSR
|
|
|
+ ptr->mXPSR = 1 << 24 ; // Thumb bit
|
|
|
+}
|
|
|
+
|
|
|
+// T A S K C O N T R O L B L O C K *
|
|
|
+
|
|
|
+typedef struct TaskControlBlock {
|
|
|
+
|
|
|
+ // Context buffer
|
|
|
+ TaskContext mTaskContext ; // SHOULD BE THE FIRST FIELD
|
|
|
+
|
|
|
+ // Task index
|
|
|
+ uint8_t mTaskIndex ;
|
|
|
+} TaskControlBlock ;
|
|
|
+
|
|
|
+
|
|
|
+static TaskControlBlock gTaskDescriptorArray [TASK_COUNT] ;
|
|
|
+
|
|
|
+
|
|
|
+TaskControlBlock * descriptorPointerForTaskIndex (const uint8_t inTaskIndex) {
|
|
|
+ XTR_ASSERT (inTaskIndex < TASK_COUNT, inTaskIndex) ;
|
|
|
+ return & gTaskDescriptorArray [inTaskIndex] ;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+uint8_t indexForDescriptorTask (const TaskControlBlock * inTaskPtr) { // should be not nullptr
|
|
|
+ XTR_ASSERT_NON_NULL_POINTER (inTaskPtr) ;
|
|
|
+ return inTaskPtr->mTaskIndex ;
|
|
|
+}
|
|
|
+
|
|
|
+// RUNNING TASK DESCRIPTOR POINTER
|
|
|
+
|
|
|
+TaskControlBlock * gRunningTaskControlBlockPtr asm ("var.running.task.control.block.ptr") ; // Shared with assembly code
|
|
|
+
|
|
|
+// SCHEDULER
|
|
|
+
|
|
|
+static TaskList gReadyTaskList ;
|
|
|
+
|
|
|
+
|
|
|
+static void kernel_makeTaskReady (IRQ_MODE_ TaskControlBlock * inTaskPtr) {
|
|
|
+ XTR_ASSERT_NON_NULL_POINTER (inTaskPtr) ;
|
|
|
+ gReadyTaskList.enterTask (MODE_ inTaskPtr) ;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void kernelSelectTaskToRun (IRQ_MODE) asm ("kernel.select.task.to.run") ; // Invoked from assembly
|
|
|
+
|
|
|
+void kernelSelectTaskToRun (IRQ_MODE) {
|
|
|
+ if (gRunningTaskControlBlockPtr != nullptr) {
|
|
|
+ gReadyTaskList.enterTask (MODE_ gRunningTaskControlBlockPtr) ;
|
|
|
+ }
|
|
|
+ gRunningTaskControlBlockPtr = gReadyTaskList.removeFirstTask (MODE) ;
|
|
|
+}
|
|
|
+
|
|
|
+// kernel_createTask
|
|
|
+
|
|
|
+static uint8_t gTaskIndex ;
|
|
|
+
|
|
|
+
|
|
|
+void kernel_createTask (INIT_MODE_
|
|
|
+ uint64_t * inStackBufferAddress,
|
|
|
+ uint32_t inStackBufferSize,
|
|
|
+ RoutineTaskType inTaskRoutine) {
|
|
|
+ XTR_ASSERT (gTaskIndex < TASK_COUNT, gTaskIndex) ;
|
|
|
+ TaskControlBlock * taskControlBlockPtr = & gTaskDescriptorArray [gTaskIndex] ;
|
|
|
+ taskControlBlockPtr->mTaskIndex = gTaskIndex ;
|
|
|
+
|
|
|
+ // Initialize properties
|
|
|
+ // As gTaskDescriptorArray is in bss, all properties are by default initialized to binary 0
|
|
|
+ // taskControlBlockPtr->mDeadline = 0 ; // statically initialized to 0
|
|
|
+ // taskControlBlockPtr->mUserResult = false ; // statically initialized to false
|
|
|
+ // taskControlBlockPtr->mGuardState = GUARD_EVALUATING_OR_OUTSIDE ; // statically initialized to GUARD_EVALUATING_OR_OUTSIDE
|
|
|
+ // taskControlBlockPtr->mGuardDescriptor.mCount = 0 ; // statically initialized to 0
|
|
|
+
|
|
|
+ // Initialize Context
|
|
|
+ kernel_set_task_context (MODE_
|
|
|
+ taskControlBlockPtr->mTaskContext,
|
|
|
+ (uint32_t) inStackBufferAddress,
|
|
|
+ inStackBufferSize,
|
|
|
+ inTaskRoutine) ;
|
|
|
+
|
|
|
+ // Make task ready
|
|
|
+ kernel_makeTaskReady (MODE_ taskControlBlockPtr) ;
|
|
|
+ gTaskIndex += 1 ;
|
|
|
+}
|
|
|
+
|
|
|
+
|