Sleep для RTOS

Хочу написать о достаточно полезной вещи(на мой взгляд) — функции sleep для RTOS.
Что это такое и зачем это надо? Допустим вам необходимо вывести что нибудь на LCD дисплей, а контроллер который там установлен не такой быстрый как наш stm32 и нам приходитбся делать паузы чтобы он успешно обработал наши запросы. Но если мы будем использовать обычный for для реализации паузы — то это будет напрасная трата ресурсов процессора, пока мы ждем мы могли бы выполнить еще что нибудь полезное.

update: Задача решена в любом RTOS, а это только доработка планировщика задач от DI. Рекомендуется использовать полноценные RTOS

По этому нужно пока мы ждем дать обработать другие задачи. Мой вариант реализации достаточно простой. При запуске функции замерить время старта, а после в цикле вызывать process manager, и после его отработки посмотреть сколько времени прошло с момента старта, если меньше чем требовалось, то продолжаем цикл, если больше, то выходим из цикла.
Вот код который у меня получился, для модификации RTOS DI HALT'а:
ERTOS.c

//Входной параметр - это минимальное количество тактов которое мы будем ждать
void SleepSoft(uint32_t TicksCount)
{
	int64_t startTick;
	int64_t endTick;
        //Формируем в переменной startTick время старта
	startTick = TimerTick; //В константе TimerTick храниться 
                               //число для перезагрузки таймера SisTick 
                               //на прерывание которого опирается операционная система 
	startTick -= SysTick->VAL;// В SysTick->VAL значение таймера до которого дотикало 
	SysTickCounter = 0;//Сбрасываем значение глобальной переменной
                           // которая инкрементиться в службе таймеров
	do{
		TaskManager();//Даём отработать какой нибудь полезной задаче 
		endTick = TimerTick - SysTick->VAL;// И считываем значение
                                                   //до которого успело дотикать
		endTick += (uint64_t)SysTickCounter*TimerTick;
		endTick -= startTick;//И вычисляем разность
	}while(endTick<TicksCount);//Если уже прошло больше тактов чем надо то выходим.
}


Вначале файла нужно прописать глобальную переменную SysTickCounter, и не забываем добавить инкремент этой переменной в службу таймеров:
ERTOS.c

void TimerService(void)
{
uint32_t index;

__disable_irq();
__disable_fault_irq();
SysTickCounter++;//ВОТ ЭТУ СТРОЧКУ надо не забыть добавить...
for(index=0;index!=MainTimerQueueSize+1;index++)      			// Прочесываем очередь таймеров
   {
   if(MainTimer[index].GoToTask == Idle_task) continue;      	// Если нашли пустышку - щелкаем следующую итерацию

   if(MainTimer[index].Time !=1)                  				// Если таймер не выщелкал, то щелкаем еще раз.
      {                                    						// To Do: Вычислить по тактам, что лучше !=1 или !=0.
      MainTimer[index].Time --;                  				// Уменьшаем число в ячейке если не конец.
      }
   else
      {
      SetTask(MainTimer[index].GoToTask);            			// Дощелкали до нуля? Пихаем в очередь задачу
      MainTimer[index].GoToTask = Idle_task;            		// А в ячейку пишем затычку
      }
   }

__enable_irq();
__enable_fault_irq();
}


Ну вот собственно и все. Из минусов данной реализации можно сразу подчеркнуть, что время слипа всегда больше того которое запросили, на неопределенную величину(зависит от задач которые попадутся в Таск Менеджере). Второй минус — функция скорее всего будет глючить если одновременно пересекутся два и более ее вызовов, т.к. мы сбрасываем глобальную переменную на которую опирается функция.
В идеале хорошо бы придумать как сделать подобную функцию, но чтобы Sleep происходил на точное время. Но эта задачка потяжелее, и я пока не придумал как ее грамотно реализовать.

Комментарии (7)

RSS свернуть / развернуть
хм. Это ты о чем? Без слипа ртос существовать не может.
Да и внимательно присмотрись к планировщику от DI. Он многозадачный но не ртос.
0
  • avatar
  • a9d
  • 26 мая 2012, 04:12
Он планировался как полноценная RTOS, но неплохо справлялся задачами насущными и в текущем виде, потому я допиливать его не стал, а названия в файлах так и остались :)))
0
Я догадывался что изобретаю велосипед, но не знал что все настолько в базовой комплектации решается. Надо де переименовать свой планировщик, в планировщик, а не RTOS, а то это сбивает.

Ну буду что нить типа freeRTOS устанавливать.
0
freeRTOS очень хорошая система. НО для новичков она, в начале, кажется очень запутанной. Авторы перемудрили с функциями.
0
… и макросами. К тому же зачастую весьма неочевидным образом. Я несколько часов потратил на то, что бы понять, почему в программе неправильно отсчитывается время в функции, которая должна вызываться через определенные интервалы времени по таймеру, пока не заменил xSemaphoreGiveFromISR на xSemaphoreGive в обработчике прерывания от таймера.
0
Во многих ОСРВ есть встроенная функция задержки. Например в замечательной CoOS CoTickDelay(int Delay). Если есть глобальный счетчик, как в Кортекса, проще использовать его.
0
Я для похожей кооперативки хочу на базе ProtoThreads сделать функции ожидания.
А вообще, по идее, в этом планировщике они реализуются как запихивание в очередь таймеров задачи с кодом, который должен выполниться после слипа. Только это довольно неудобно и количество задач сильно растет.
0
  • avatar
  • Vga
  • 26 мая 2012, 13:41
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.