rtos.c 4.7 KB

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