rtos.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "rtos.h"
  2. /**
  3. * Переменные модуля
  4. */
  5. static volatile task TaskArray[MAX_TASKS]; // очередь задач
  6. static volatile uint8_t arrayTail; // "хвост" очереди
  7. static volatile uint8_t interruptStatus;
  8. #define DISABLE_INTERRUPT {interruptStatus = __save_interrupt(); __disable_interrupt();}
  9. #define RESTORE_INTERRUPT __restore_interrupt(interruptStatus)
  10. // счётчик задержки
  11. static volatile uint16_t TDelay;
  12. /**
  13. * Инициализация РТОС и t_delay, время тика - 1 мс
  14. */
  15. inline void RTOS_Init()
  16. {
  17. // настраиваем основной таймер
  18. TIMER_TCCR = TIMER_CSB;
  19. TIMER_TCNT = TIMER_CNT;
  20. TIMER_TIMSK |= TIMER_INT;
  21. // "хвост" в 0
  22. arrayTail = 0;
  23. }
  24. /**
  25. * Добавление задачи в список
  26. */
  27. void RTOS_SetTask (void (*taskFunc)(void), uint16_t taskDelay, uint16_t taskPeriod)
  28. {
  29. uint8_t i;
  30. if(!taskFunc) return;
  31. for(i = 0; i < arrayTail; i++) // поиск задачи в текущем списке
  32. {
  33. if(TaskArray[i].pFunc == taskFunc) // если нашли, то обновляем переменные
  34. {
  35. DISABLE_INTERRUPT;
  36. TaskArray[i].delay = taskDelay;
  37. TaskArray[i].period = taskPeriod;
  38. TaskArray[i].run = 0;
  39. RESTORE_INTERRUPT;
  40. return; // обновив, выходим
  41. }
  42. }
  43. if (arrayTail < MAX_TASKS) // если такой задачи в списке нет
  44. { // и есть место,то добавляем
  45. DISABLE_INTERRUPT;
  46. TaskArray[arrayTail].pFunc = taskFunc;
  47. TaskArray[arrayTail].delay = taskDelay;
  48. TaskArray[arrayTail].period = taskPeriod;
  49. TaskArray[arrayTail].run = 0;
  50. arrayTail++; // увеличиваем "хвост"
  51. RESTORE_INTERRUPT;
  52. }
  53. }
  54. /**
  55. * Удаление задачи из списка
  56. */
  57. inline void RTOS_DeleteTask (void (*taskFunc)(void))
  58. {
  59. uint8_t i;
  60. for (i=0; i<arrayTail; i++) // проходим по списку задач
  61. {
  62. if(TaskArray[i].pFunc == taskFunc) // если задача в списке найдена
  63. {
  64. DISABLE_INTERRUPT;
  65. if(i != (arrayTail - 1)) // переносим последнюю задачу
  66. { // на место удаляемой
  67. TaskArray[i] = TaskArray[arrayTail - 1];
  68. }
  69. arrayTail--; // уменьшаем указатель "хвоста"
  70. RESTORE_INTERRUPT;
  71. return;
  72. }
  73. }
  74. }
  75. /**
  76. * Диспетчер РТОС, вызывается в main
  77. */
  78. void RTOS_DispatchTask(void)
  79. {
  80. uint8_t i;
  81. void (*function) (void);
  82. for (i=0; i<arrayTail; i++) // проходим по списку задач
  83. {
  84. if (TaskArray[i].run == 1) // если флаг на выполнение взведен,
  85. { // запоминаем задачу, т.к. во
  86. function = TaskArray[i].pFunc; // время выполнения может
  87. // измениться индекс
  88. if(TaskArray[i].period == 0)
  89. { // если период равен 0
  90. RTOS_DeleteTask(TaskArray[i].pFunc);// удаляем задачу из списка,
  91. }
  92. else
  93. {
  94. TaskArray[i].run = 0; // иначе снимаем флаг запуска
  95. if(!TaskArray[i].delay) // если задача не изменила задержку
  96. { // задаем ее
  97. TaskArray[i].delay = TaskArray[i].period-1;
  98. } // задача для себя может сделать паузу
  99. }
  100. (*function)(); // выполняем задачу
  101. }
  102. }
  103. }
  104. /**
  105. * Delay, msek
  106. * также, что-бы зря не терять время -- крутим диспетчер
  107. */
  108. void tdelay_ms(uint16_t msek) {
  109. TDelay = msek;
  110. do {
  111. RTOS_DispatchTask();
  112. // делать нехрен -- спим, ждём прерывание
  113. MCUCR = 1<<SE;
  114. __sleep();
  115. } while (TDelay>0);
  116. }
  117. /**
  118. * Таймерная служба РТОС и tdelay (прерывание аппаратного таймера)
  119. */
  120. #pragma vector=TIMER_OVF_VECT
  121. __interrupt void TIMER_OVF_ISR(void) {
  122. // перезарядим таймер
  123. TIMER_TCNT = TIMER_CNT;
  124. /* RTOS_Timer */
  125. uint8_t i;
  126. // проходим по списку задач
  127. for (i=0; i<arrayTail; i++) {
  128. // если время до выполнения истекло
  129. if (TaskArray[i].delay == 0) {
  130. // взводим флаг запуска,
  131. TaskArray[i].run = 1;
  132. } else {
  133. // иначе уменьшаем время
  134. TaskArray[i].delay--;
  135. }
  136. }
  137. /* TDelay_Timer -- уменьшим счётчик */
  138. if (TDelay > 0) {
  139. TDelay --;
  140. }
  141. }