123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- #include "rtos.h"
- /**
- * Переменные модуля
- */
- static volatile task TaskArray[MAX_TASKS]; // очередь задач
- static volatile uint8_t arrayTail; // "хвост" очереди
- static volatile uint8_t interruptStatus;
- #define DISABLE_INTERRUPT {interruptStatus = __save_interrupt(); __disable_interrupt();}
- #define RESTORE_INTERRUPT __restore_interrupt(interruptStatus)
- // счётчик задержки
- static volatile uint16_t TDelay;
- /**
- * Инициализация РТОС и t_delay, время тика - 1 мс
- */
- inline void RTOS_Init()
- {
- // настраиваем основной таймер
- TIMER_TCCR = TIMER_CSB;
- TIMER_TCNT = TIMER_CNT;
- TIMER_TIMSK |= TIMER_INT;
- // "хвост" в 0
- arrayTail = 0;
- }
- /**
- * Добавление задачи в список
- */
- void RTOS_SetTask (void (*taskFunc)(void), uint16_t taskDelay, uint16_t taskPeriod)
- {
- uint8_t i;
- if(!taskFunc) return;
- for(i = 0; i < arrayTail; i++) // поиск задачи в текущем списке
- {
- if(TaskArray[i].pFunc == taskFunc) // если нашли, то обновляем переменные
- {
- DISABLE_INTERRUPT;
- TaskArray[i].delay = taskDelay;
- TaskArray[i].period = taskPeriod;
- TaskArray[i].run = 0;
- RESTORE_INTERRUPT;
- return; // обновив, выходим
- }
- }
- if (arrayTail < MAX_TASKS) // если такой задачи в списке нет
- { // и есть место,то добавляем
- DISABLE_INTERRUPT;
- TaskArray[arrayTail].pFunc = taskFunc;
- TaskArray[arrayTail].delay = taskDelay;
- TaskArray[arrayTail].period = taskPeriod;
- TaskArray[arrayTail].run = 0;
- arrayTail++; // увеличиваем "хвост"
- RESTORE_INTERRUPT;
- }
- }
- /**
- * Удаление задачи из списка
- */
- inline void RTOS_DeleteTask (void (*taskFunc)(void))
- {
- uint8_t i;
- for (i=0; i<arrayTail; i++) // проходим по списку задач
- {
- if(TaskArray[i].pFunc == taskFunc) // если задача в списке найдена
- {
- DISABLE_INTERRUPT;
- if(i != (arrayTail - 1)) // переносим последнюю задачу
- { // на место удаляемой
- TaskArray[i] = TaskArray[arrayTail - 1];
- }
- arrayTail--; // уменьшаем указатель "хвоста"
- RESTORE_INTERRUPT;
- return;
- }
- }
- }
- /**
- * Диспетчер РТОС, вызывается в main
- */
- void RTOS_DispatchTask(void)
- {
- uint8_t i;
- void (*function) (void);
- for (i=0; i<arrayTail; i++) // проходим по списку задач
- {
- if (TaskArray[i].run == 1) // если флаг на выполнение взведен,
- { // запоминаем задачу, т.к. во
- function = TaskArray[i].pFunc; // время выполнения может
- // измениться индекс
- if(TaskArray[i].period == 0)
- { // если период равен 0
- RTOS_DeleteTask(TaskArray[i].pFunc);// удаляем задачу из списка,
- }
- else
- {
- TaskArray[i].run = 0; // иначе снимаем флаг запуска
- if(!TaskArray[i].delay) // если задача не изменила задержку
- { // задаем ее
- TaskArray[i].delay = TaskArray[i].period-1;
- } // задача для себя может сделать паузу
- }
- (*function)(); // выполняем задачу
- }
- }
- }
- /**
- * Delay, msek
- * также, что-бы зря не терять время -- крутим диспетчер
- */
- void tdelay_ms(uint16_t msek) {
- TDelay = msek;
- do {
- RTOS_DispatchTask();
- // делать нехрен -- спим, ждём прерывание
- MCUCR = 1<<SE;
- __sleep();
- } while (TDelay>0);
- }
- /**
- * Таймерная служба РТОС и tdelay (прерывание аппаратного таймера)
- */
- #pragma vector=TIMER_OVF_VECT
- __interrupt void TIMER_OVF_ISR(void) {
- // перезарядим таймер
- TIMER_TCNT = TIMER_CNT;
- /* RTOS_Timer */
- uint8_t i;
- // проходим по списку задач
- for (i=0; i<arrayTail; i++) {
- // если время до выполнения истекло
- if (TaskArray[i].delay == 0) {
- // взводим флаг запуска,
- TaskArray[i].run = 1;
- } else {
- // иначе уменьшаем время
- TaskArray[i].delay--;
- }
- }
- /* TDelay_Timer -- уменьшим счётчик */
- if (TDelay > 0) {
- TDelay --;
- }
- }
|