xtr.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include "all-headers.h"
  2. #define ENABLE_XTR_ASSERTIONS
  3. #ifdef ENABLE_XTR_ASSERTIONS
  4. #define XTR_ASSERT_NON_NULL_POINTER(ptr) assertNonNullPointer (ptr, __FILE__, __LINE__) ;
  5. #else
  6. #define XTR_ASSERT_NON_NULL_POINTER(ptr)
  7. #endif
  8. #ifdef ENABLE_XTR_ASSERTIONS
  9. #define XTR_ASSERT(condition,value) assertion (condition, value, __FILE__, __LINE__) ;
  10. #else
  11. #define XTR_ASSERT(condition,value)
  12. #endif
  13. // CORTEX-M4 EXCEPTION FRAME (WITHOUT FLOATING-POINT STORAGE) *
  14. // *
  15. // PSP+32 -> | | *
  16. // |----------------------------| \ *
  17. // PSP+28 -> | xPSR | | *
  18. // |----------------------------| | *
  19. // PSP+24 -> | PC (after SVC instruction) | | *
  20. // |----------------------------| | *
  21. // PSP+20 -> | LR | | *
  22. // |----------------------------| | *
  23. // PSP+16 -> | R12 | | Saved by interrupt response *
  24. // |----------------------------| | *
  25. // PSP+12 -> | R3 | | *
  26. // |----------------------------| | *
  27. // PSP+8 -> | R2 | | *
  28. // |----------------------------| | *
  29. // PSP+4 -> | R1 | | *
  30. // |----------------------------| | *
  31. // /---- PSP ----> | R0 | | *
  32. // | |----------------------------| / *
  33. // | *
  34. // | *---------------------*
  35. // | | LR return code | +36 [ 9]
  36. // | *---------------------*
  37. // \-----------------------------------------------| R13 (PSP) | +32 [ 8]
  38. // *---------------------*
  39. // | R11 | +28 [ 7]
  40. // *---------------------*
  41. // | R10 | +24 [ 6]
  42. // *---------------------*
  43. // | R9 | +20 [ 5]
  44. // *---------------------*
  45. // | R8 | +16 [ 4]
  46. // *---------------------*
  47. // | R7 | +12 [ 3]
  48. // *---------------------*
  49. // | R6 | + 8 [ 2]
  50. // *---------------------*
  51. // | R5 | + 4 [ 1]
  52. // *---------------------------------------* *---------------------*
  53. // | var.running.task.control.block.ptr +------> | R4 | + 0 [ 0]
  54. // *---------------------------------------* *---------------------*
  55. //
  56. //----------------------------------------------------------------------------------------------------------------------
  57. typedef struct {
  58. uint32_t mR0 ;
  59. uint32_t mR1 ;
  60. uint32_t mR2 ;
  61. uint32_t mR3 ;
  62. uint32_t mR12 ;
  63. uint32_t mLR ;
  64. uint32_t mPC ;
  65. uint32_t mXPSR ;
  66. } ExceptionFrame_without_floatingPointStorage ;
  67. typedef struct {
  68. uint32_t mR4 ;
  69. uint32_t mR5 ;
  70. uint32_t mR6 ;
  71. uint32_t mR7 ;
  72. uint32_t mR8 ;
  73. uint32_t mR9 ;
  74. uint32_t mR10 ;
  75. uint32_t mR11 ;
  76. ExceptionFrame_without_floatingPointStorage * mPSP ; // R13
  77. uint32_t mLR_RETURN_CODE ;
  78. } TaskContext ;
  79. static void kernel_set_task_context (INIT_MODE_
  80. TaskContext & ioTaskContext,
  81. const uint32_t inStackBufferAddress,
  82. const uint32_t inStackBufferSize,
  83. RoutineTaskType inTaskRoutine) {
  84. // Initialize LR
  85. ioTaskContext.mLR_RETURN_CODE = 0xFFFFFFFD ;
  86. // Stack Pointer initial value
  87. uint32_t initialTopOfStack = inStackBufferAddress + inStackBufferSize ;
  88. initialTopOfStack -= sizeof (ExceptionFrame_without_floatingPointStorage) ;
  89. // Initialize SP
  90. auto ptr = (ExceptionFrame_without_floatingPointStorage *) initialTopOfStack ;
  91. ioTaskContext.mPSP = ptr ;
  92. // Initialize PC
  93. ptr->mPC = (uint32_t) inTaskRoutine ;
  94. // Initialize CPSR
  95. ptr->mXPSR = 1 << 24 ; // Thumb bit
  96. // Self termination
  97. ptr->mLR = (uint32_t) taskSelfTerminates;
  98. }
  99. // T A S K C O N T R O L B L O C K *
  100. typedef struct TaskControlBlock {
  101. // Context buffer
  102. TaskContext mTaskContext ; // SHOULD BE THE FIRST FIELD
  103. // Store reactivation deadline
  104. uint32_t mDeadline ;
  105. // Task index
  106. uint8_t mTaskIndex ;
  107. } TaskControlBlock ;
  108. static TaskControlBlock gTaskDescriptorArray [TASK_COUNT] ;
  109. TaskControlBlock * descriptorPointerForTaskIndex (const uint8_t inTaskIndex) {
  110. XTR_ASSERT (inTaskIndex < TASK_COUNT, inTaskIndex) ;
  111. return & gTaskDescriptorArray [inTaskIndex] ;
  112. }
  113. uint8_t indexForDescriptorTask (const TaskControlBlock * inTaskPtr) { // should be not nullptr
  114. XTR_ASSERT_NON_NULL_POINTER (inTaskPtr) ;
  115. return inTaskPtr->mTaskIndex ;
  116. }
  117. // RUNNING TASK DESCRIPTOR POINTER
  118. TaskControlBlock * gRunningTaskControlBlockPtr asm ("var.running.task.control.block.ptr") ; // Shared with assembly code
  119. // SCHEDULER
  120. static TaskList gReadyTaskList ;
  121. static TaskList gDeadlineWaitingTaskList ;
  122. void kernel_makeTaskReady (IRQ_MODE_ TaskControlBlock * inTaskPtr) {
  123. XTR_ASSERT_NON_NULL_POINTER (inTaskPtr) ;
  124. gReadyTaskList.enterTask (MODE_ inTaskPtr) ;
  125. }
  126. void kernelSelectTaskToRun (IRQ_MODE) asm ("kernel.select.task.to.run") ; // Invoked from assembly
  127. void kernelSelectTaskToRun (IRQ_MODE) {
  128. if (gRunningTaskControlBlockPtr != nullptr) {
  129. gReadyTaskList.enterTask (MODE_ gRunningTaskControlBlockPtr) ;
  130. }
  131. gRunningTaskControlBlockPtr = gReadyTaskList.removeFirstTask (MODE) ;
  132. }
  133. // kernel_createTask
  134. static uint8_t gTaskIndex ;
  135. void kernel_createTask (INIT_MODE_
  136. uint64_t * inStackBufferAddress,
  137. uint32_t inStackBufferSize,
  138. RoutineTaskType inTaskRoutine) {
  139. XTR_ASSERT (gTaskIndex < TASK_COUNT, gTaskIndex) ;
  140. TaskControlBlock * taskControlBlockPtr = & gTaskDescriptorArray [gTaskIndex] ;
  141. taskControlBlockPtr->mTaskIndex = gTaskIndex ;
  142. // Initialize properties
  143. // As gTaskDescriptorArray is in bss, all properties are by default initialized to binary 0
  144. // taskControlBlockPtr->mDeadline = 0 ; // statically initialized to 0
  145. // taskControlBlockPtr->mUserResult = false ; // statically initialized to false
  146. // taskControlBlockPtr->mGuardState = GUARD_EVALUATING_OR_OUTSIDE ; // statically initialized to GUARD_EVALUATING_OR_OUTSIDE
  147. // taskControlBlockPtr->mGuardDescriptor.mCount = 0 ; // statically initialized to 0
  148. // Initialize Context
  149. kernel_set_task_context (MODE_
  150. taskControlBlockPtr->mTaskContext,
  151. (uint32_t) inStackBufferAddress,
  152. inStackBufferSize,
  153. inTaskRoutine) ;
  154. // Make task ready
  155. kernel_makeTaskReady (MODE_ taskControlBlockPtr) ;
  156. gTaskIndex += 1 ;
  157. }
  158. static void kernel_makeNoTaskRunning(KERNEL_MODE) {
  159. gRunningTaskControlBlockPtr = nullptr; // No running task
  160. }
  161. void kernel_blockOnDeadline (KERNEL_MODE_ const uint32_t inDeadline) {
  162. XTR_ASSERT_NON_NULL_POINTER (gRunningTaskControlBlockPtr) ;
  163. gRunningTaskControlBlockPtr->mDeadline = inDeadline ;
  164. gDeadlineWaitingTaskList.enterTask (MODE_ gRunningTaskControlBlockPtr) ;
  165. kernel_makeNoTaskRunning (MODE) ;
  166. }
  167. // Task termination
  168. void service_taskSelfTerminates(KERNEL_MODE) {
  169. kernel_makeNoTaskRunning(MODE);
  170. }
  171. static void irq_makeTasksReadyFromCurrentDate (IRQ_MODE_ const uint32_t inCurrentDate) {
  172. TaskList::Iterator iterator (MODE_ gDeadlineWaitingTaskList) ;
  173. TaskControlBlock * task ;
  174. while ((task = iterator.nextTask (MODE))) {
  175. if (inCurrentDate >= task->mDeadline) {
  176. gDeadlineWaitingTaskList.removeTask (MODE_ task) ;
  177. kernel_makeTaskReady (MODE_ task) ;
  178. }
  179. }
  180. }
  181. MACRO_REAL_TIME_ISR (irq_makeTasksReadyFromCurrentDate) ;
  182. // Synchronisation
  183. void kernel_blockRunningTaskInList (KERNEL_MODE_ TaskList & ioWaitingList) {
  184. XTR_ASSERT_NON_NULL_POINTER (gRunningTaskControlBlockPtr) ;
  185. ioWaitingList.enterTask (MODE_ gRunningTaskControlBlockPtr) ;
  186. kernel_makeNoTaskRunning (MODE) ;
  187. }
  188. bool irq_makeTaskReadyFromList (IRQ_MODE_ TaskList & ioWaitingList) {
  189. TaskControlBlock * taskPtr = ioWaitingList.removeFirstTask (MODE) ;
  190. const bool found = taskPtr != nullptr ;
  191. if (found) {
  192. kernel_makeTaskReady (MODE_ taskPtr) ;
  193. }
  194. return found ;
  195. }