rtos.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "main.h"
  2. /**
  3. * @brief Task Structure
  4. */
  5. typedef struct task {
  6. void (*pFunc) (void); /**< @brief function pointer */
  7. uint32_t delay; /**< @brief delay before the first start of the task */
  8. uint32_t period; /**< @brief task start period */
  9. int run; /**< @brief task ready flag */
  10. } task_t;
  11. /*
  12. * Local variables
  13. */
  14. static volatile task_t TaskArray[MAX_TASKS];/**< @brief task queue */
  15. static volatile int arrayTail; /**< @brief "tail" of the queue */
  16. static volatile uint32_t TDelay; /**< @brief delay counter */
  17. /**
  18. * @brief Initialization of RTOS and t_delay, tick time - 1 ms
  19. */
  20. inline void RTOS_Init(void) {
  21. // setting up the main timer
  22. SysTick->LOAD = (uint32_t)(SystemCoreClock/1000 - 1UL); /* set reload register */
  23. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  24. SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
  25. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  26. SysTick_CTRL_TICKINT_Msk |
  27. SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
  28. // shrink "tail"
  29. arrayTail = 0;
  30. }
  31. /**
  32. * @brief Adding a task to the list
  33. *
  34. * @param taskFunc function pointer
  35. * @param taskDelay delay before the first start of the task
  36. * @param taskPeriod task start period
  37. */
  38. void RTOS_SetTask (void (*taskFunc)(void), uint32_t taskDelay, uint32_t taskPeriod) {
  39. int i;
  40. if (!taskFunc) {
  41. return;
  42. }
  43. // search for a task in the current list
  44. for(i = 0; i < arrayTail; i++) {
  45. // if found, then update the variables
  46. if (TaskArray[i].pFunc == taskFunc) {
  47. __disable_irq();
  48. TaskArray[i].delay = taskDelay;
  49. TaskArray[i].period = taskPeriod;
  50. TaskArray[i].run = 0;
  51. __enable_irq();
  52. // update, exit
  53. return;
  54. }
  55. }
  56. // if there is no such task in the list
  57. if (arrayTail < MAX_TASKS) {
  58. // and there is a place, then we add
  59. __disable_irq();
  60. TaskArray[arrayTail].pFunc = taskFunc;
  61. TaskArray[arrayTail].delay = taskDelay;
  62. TaskArray[arrayTail].period = taskPeriod;
  63. TaskArray[arrayTail].run = 0;
  64. // enlarge the "tail"
  65. arrayTail++;
  66. __enable_irq();
  67. } else {
  68. //!!! no left space for new task :-(
  69. while (1);
  70. }
  71. }
  72. /**
  73. * @brief Removing a task from the list
  74. *
  75. * @param taskFunc function pointer
  76. */
  77. inline void RTOS_DeleteTask (void (*taskFunc)(void)) {
  78. int i;
  79. // go through the list of tasks
  80. for (i=0; i<arrayTail; i++) {
  81. // if the task is found in the list
  82. if (TaskArray[i].pFunc == taskFunc) {
  83. __disable_irq();
  84. // move the last task
  85. if (i != (arrayTail - 1)) {
  86. // in place of the removed
  87. TaskArray[i] = TaskArray[arrayTail - 1];
  88. }
  89. // decrement "tail" pointer
  90. arrayTail--;
  91. __enable_irq();
  92. return;
  93. }
  94. }
  95. }
  96. /**
  97. * @brief RTOS dispatcher, called in main
  98. */
  99. void RTOS_DispatchTask(void) {
  100. int i;
  101. void (*function) (void);
  102. // go through the list of tasks
  103. for (i=0; i<arrayTail; i++) {
  104. // if the execution flag is set,
  105. if (TaskArray[i].run != 0) {
  106. // we remember the task, because index may change during runtime
  107. function = TaskArray[i].pFunc;
  108. if (TaskArray[i].period == 0) {
  109. // if the period is 0, remove the task from the list,
  110. RTOS_DeleteTask(TaskArray[i].pFunc);
  111. } else {
  112. // otherwise remove the start flag
  113. TaskArray[i].run = 0;
  114. // if the task has not changed the delay
  115. if (!TaskArray[i].delay) {
  116. // set her
  117. TaskArray[i].delay = TaskArray[i].period-1;
  118. // task for itself can pause
  119. }
  120. }
  121. // run the task
  122. (*function)();
  123. }
  124. }
  125. }
  126. /**
  127. * @brief Inserts a delay time.
  128. *
  129. * @param msek specifies the delay time length, in milliseconds.
  130. */
  131. void tdelay_ms(uint32_t msek) {
  132. TDelay = msek;
  133. do {
  134. if (TDelay > 1) {
  135. /* so as not to waste time in wait - turn the dispatcher */
  136. RTOS_DispatchTask();
  137. }
  138. /* there is nothing to do - sleep, waiting for an interruption */
  139. __WFI();
  140. } while (TDelay != 0);
  141. }
  142. /**
  143. * @brief RTOS timer service and tdelay (hardware timer interrupt)
  144. */
  145. #pragma GCC optimize ("O3")
  146. /**
  147. * @brief This function handles SysTick Handler.
  148. */
  149. void SysTick_Handler(void) {
  150. /* RTOS_Timer */
  151. int i;
  152. // go through the list of tasks
  153. for (i=0; i<arrayTail; i++) {
  154. // if the time to execute has expired
  155. if (TaskArray[i].delay == 0) {
  156. // raise the launch flag,
  157. TaskArray[i].run = 1;
  158. } else {
  159. // otherwise reduce the time
  160. TaskArray[i].delay--;
  161. }
  162. }
  163. /* decrement the counter */
  164. if (TDelay != 0) {
  165. TDelay --;
  166. }
  167. }