rtos.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "main.h"
  2. /*
  3. * Переменные модуля
  4. */
  5. static volatile task TaskArray[MAX_TASKS]; // очередь задач
  6. static volatile uint8_t arrayTail; // "хвост" очереди
  7. // счётчик задержки
  8. static volatile uint32_t TDelay;
  9. /*
  10. * Инициализация РТОС и t_delay, время тика - 1 мс
  11. */
  12. inline void RTOS_Init(void) {
  13. // настраиваем основной таймер
  14. SysTick->LOAD = (uint32_t)(SystemCoreClock/1000 - 1UL); /* set reload register */
  15. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  16. SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
  17. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  18. SysTick_CTRL_TICKINT_Msk |
  19. SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
  20. // "хвост" в 0
  21. arrayTail = 0;
  22. }
  23. /*
  24. * Добавление задачи в список
  25. */
  26. void RTOS_SetTask (void (*taskFunc)(void), uint32_t taskDelay, uint32_t taskPeriod) {
  27. int i;
  28. if (!taskFunc) {
  29. return;
  30. }
  31. // поиск задачи в текущем списке
  32. for(i = 0; i < arrayTail; i++) {
  33. // если нашли, то обновляем переменные
  34. if (TaskArray[i].pFunc == taskFunc) {
  35. __disable_irq();
  36. TaskArray[i].delay = taskDelay;
  37. TaskArray[i].period = taskPeriod;
  38. TaskArray[i].run = 0;
  39. __enable_irq();
  40. // обновив, выходим
  41. return;
  42. }
  43. }
  44. // если такой задачи в списке нет
  45. if (arrayTail < MAX_TASKS) {
  46. // и есть место, то добавляем
  47. __disable_irq();
  48. TaskArray[arrayTail].pFunc = taskFunc;
  49. TaskArray[arrayTail].delay = taskDelay;
  50. TaskArray[arrayTail].period = taskPeriod;
  51. TaskArray[arrayTail].run = 0;
  52. // увеличиваем "хвост"
  53. arrayTail++;
  54. __enable_irq();
  55. } else {
  56. //!!! no left space for new task :-(
  57. // tube power off
  58. TIM1->CCER &= ~(TIM_CCER_CC1E);
  59. TIM3->CCER &= ~(TIM_CCER_CC4E);
  60. TIM3->CCER &= ~(TIM_CCER_CC3E);
  61. TIM3->CCER &= ~(TIM_CCER_CC2E);
  62. TIM3->CCER &= ~(TIM_CCER_CC1E);
  63. GPIOA->BSRR = 0x10;
  64. // color - orange
  65. TIM1->CCR2 = 0xff;
  66. TIM1->CCR3 = 0x7f;
  67. TIM1->CCR4 = 0x0;
  68. while (1);
  69. }
  70. }
  71. /*
  72. * Удаление задачи из списка
  73. */
  74. inline void RTOS_DeleteTask (void (*taskFunc)(void)) {
  75. int i;
  76. // проходим по списку задач
  77. for (i=0; i<arrayTail; i++) {
  78. // если задача в списке найдена
  79. if (TaskArray[i].pFunc == taskFunc) {
  80. __disable_irq();
  81. // переносим последнюю задачу
  82. if (i != (arrayTail - 1)) {
  83. // на место удаляемой
  84. TaskArray[i] = TaskArray[arrayTail - 1];
  85. }
  86. // уменьшаем указатель "хвоста"
  87. arrayTail--;
  88. __enable_irq();
  89. return;
  90. }
  91. }
  92. }
  93. /*
  94. * Диспетчер РТОС, вызывается в main
  95. */
  96. void RTOS_DispatchTask(void) {
  97. int i;
  98. void (*function) (void);
  99. // проходим по списку задач
  100. for (i=0; i<arrayTail; i++) {
  101. // если флаг на выполнение взведен,
  102. if (TaskArray[i].run != 0) {
  103. // запоминаем задачу, т.к. во время выполнения может измениться индекс
  104. function = TaskArray[i].pFunc;
  105. if (TaskArray[i].period == 0) {
  106. // если период равен 0, удаляем задачу из списка,
  107. RTOS_DeleteTask(TaskArray[i].pFunc);
  108. } else {
  109. // иначе снимаем флаг запуска
  110. TaskArray[i].run = 0;
  111. // если задача не изменила задержку
  112. if (!TaskArray[i].delay) {
  113. // задаем ее
  114. TaskArray[i].delay = TaskArray[i].period-1;
  115. // задача для себя может сделать паузу
  116. }
  117. }
  118. // выполняем задачу
  119. (*function)();
  120. }
  121. }
  122. }
  123. /**
  124. * @brief Inserts a delay time.
  125. * @param nTime: specifies the delay time length, in milliseconds.
  126. * @retval None
  127. */
  128. void tdelay_ms(uint32_t msek) {
  129. TDelay = msek;
  130. do {
  131. if (TDelay > 1) {
  132. /* что-бы зря не терять время -- крутим диспетчер */
  133. RTOS_DispatchTask();
  134. }
  135. /* делать нехрен -- спим, ждём прерывание */
  136. __WFI();
  137. } while (TDelay != 0);
  138. }
  139. /******************************************************************************************
  140. * Таймерная служба РТОС и tdelay (прерывание аппаратного таймера)
  141. */
  142. #pragma GCC optimize ("O3")
  143. /**
  144. * @brief This function handles SysTick Handler.
  145. * @param None
  146. * @retval None
  147. */
  148. void SysTick_Handler(void) {
  149. /* RTOS_Timer */
  150. int i;
  151. // проходим по списку задач
  152. for (i=0; i<arrayTail; i++) {
  153. // если время до выполнения истекло
  154. if (TaskArray[i].delay == 0) {
  155. // взводим флаг запуска,
  156. TaskArray[i].run = 1;
  157. } else {
  158. // иначе уменьшаем время
  159. TaskArray[i].delay--;
  160. }
  161. }
  162. /* TDelay_Timer -- уменьшим счётчик */
  163. if (TDelay != 0) {
  164. TDelay --;
  165. }
  166. }