#вставка "myRTOS.h"
// RTOS Подготовка. Очистка очередей
пуст ТОСРВ::ПодготовитьОСРВ()
{
беззнак симв индекс;
для(индекс=0;индекс!=Длина_Очереди_Задач+1;индекс++) // Во все позиции записываем Бездействие
{
ОчередьЗадач[индекс] = Бездействие;
}
для(индекс=0;индекс!=Длина_Очереди_Таймеров+1;индекс++) // Обнуляем все таймеры.
{
ОчередьТаймеров[индекс].уЗадача = Бездействие;
ОчередьТаймеров[индекс].Период = 0;
ОчередьДлинныхТаймеров[индекс].уЗадача = Бездействие;
ОчередьДлинныхТаймеров[индекс].Период = 0;
}
СтартТаймера();
}
// Функция установки задачи в очередь. Передаваемый параметр - указатель на функцию
// Отдаваемое значение - код ошибки.
пуст ТОСРВ::ДобавитьЗадачу(ТуЗадача у_задача)
{
беззнак симв индекс = 0;
беззнак симв флаг_прерывания_запрещены = 0;
если (РЕГИСТР_СОСТОЯНИЯ & (1<<ФЛАГ_ПРЕРЫВАНИЙ)) // Если прерывания разрешены, то запрещаем их.
{
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
флаг_прерывания_запрещены = 1; // И ставим флаг, что мы не в прерывании.
}
пока(ОчередьЗадач[индекс]!=Бездействие ) // Прочесываем очередь задач на предмет свободной ячейки
{ // с значением Бездействие - конец очереди.
индекс++;
если (индекс==Длина_Очереди_Задач +1 || ОчередьЗадач[индекс]== у_задача) // Если очередь переполнена то выходим не солоно хлебавши
{ // или задача уже в очереди
если (флаг_прерывания_запрещены) РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Если мы не в прерывании, то разрешаем прерывания
return; // Раньше функция возвращала код ошибки - очередь переполнена. Пока убрал.
}
}
// Если нашли свободное место, то
ОчередьЗадач[индекс] = у_задача; // Записываем в очередь задачу
если (флаг_прерывания_запрещены) РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // И включаем прерывания если не в обработчике прерывания.
}
//Функция установки задачи по таймеру. Передаваемые параметры - указатель на функцию,
// Время выдержки в тиках системного таймера.
пуст ТОСРВ::ДобавитьТаймерЗадачи(ТуЗадача у_задача, беззнак цел период)
{
беззнак симв индекс=0;
беззнак симв флаг_прерывания_запрещены = 0;
если (РЕГИСТР_СОСТОЯНИЯ & (1<<ФЛАГ_ПРЕРЫВАНИЙ)) // Проверка запрета прерывания, аналогично функции выше
{
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
флаг_прерывания_запрещены = 1;
}
для(индекс=0;индекс!=Длина_Очереди_Таймеров+1;++индекс) //Прочесываем очередь таймеров
{
если(ОчередьТаймеров[индекс].уЗадача == у_задача) // Если уже есть запись с таким адресом
{
ОчередьТаймеров[индекс].Период = период; // Перезаписываем ей выдержку
если (флаг_прерывания_запрещены) РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Разрешаем прерывания если не были запрещены.
return; // Выходим. Раньше был код успешной операции. Пока убрал
}
}
для(индекс=0;индекс!=Длина_Очереди_Таймеров+1;++индекс) // Если не находим похожий таймер, то ищем любой пустой
{
если (ОчередьТаймеров[индекс].уЗадача == Бездействие)
{
ОчередьТаймеров[индекс].уЗадача = у_задача; // Заполняем поле перехода задачи
ОчередьТаймеров[индекс].Период = период; // И поле выдержки времени
если (флаг_прерывания_запрещены) РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Разрешаем прерывания
return; // Выход.
}
} // тут можно сделать return c кодом ошибки - нет свободных таймеров
}
//Функция установки задачи по таймеру. Передаваемые параметры - указатель на функцию,
// Время выдержки в секундах.
пуст ТОСРВ::ДобавитьДлинныйТаймерЗадачи(ТуЗадача у_задача, беззнак цел период)
{
беззнак симв индекс=0;
беззнак симв флаг_прерывания_запрещены = 0;
если (РЕГИСТР_СОСТОЯНИЯ & (1<<ФЛАГ_ПРЕРЫВАНИЙ)) // Проверка запрета прерывания, аналогично функции выше
{
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
флаг_прерывания_запрещены = 1;
}
для(индекс=0;индекс!=Длина_Очереди_Таймеров+1;++индекс) //Прочесываем очередь таймеров
{
если(ОчередьДлинныхТаймеров[индекс].уЗадача == у_задача) // Если уже есть запись с таким адресом
{
ОчередьДлинныхТаймеров[индекс].Период = период; // Перезаписываем ей выдержку
если (флаг_прерывания_запрещены) РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Разрешаем прерывания если не были запрещены.
return; // Выходим. Раньше был код успешной операции. Пока убрал
}
}
для(индекс=0;индекс!=Длина_Очереди_Таймеров+1;++индекс) // Если не находим похожий таймер, то ищем любой пустой
{
если (ОчередьДлинныхТаймеров[индекс].уЗадача == Бездействие)
{
ОчередьДлинныхТаймеров[индекс].уЗадача = у_задача; // Заполняем поле перехода задачи
ОчередьДлинныхТаймеров[индекс].Период = период; // И поле выдержки времени
если (флаг_прерывания_запрещены) РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Разрешаем прерывания
return; // Выход.
}
} // тут можно сделать return c кодом ошибки - нет свободных таймеров
}
/*
Служба таймеров ядра. Должна вызываться из прерывания раз в 1мс. Хотя время можно варьировать в зависимости от задачи
To DO: Привести к возможности загружать произвольную очередь таймеров. Тогда можно будет создавать их целую прорву.
А также использовать эту функцию произвольным образом.
В этом случае не забыть добавить проверку прерывания.
*/
пуст ТОСРВ::ДиспетчерТаймеров(пуст)
{
беззнак char индекс;
для (индекс = 0; индекс != Длина_Очереди_Таймеров + 1; индекс++) // Прочесываем очередь таймеров
{
если (ОчередьТаймеров[индекс].уЗадача == Бездействие)
{
continue; // Если нашли пустышку - щелкаем следующую итерацию
}
если (ОчередьТаймеров[индекс].Период != 1) // Если таймер не выщелкал, то щелкаем еще раз.
{
// To Do: Вычислить по тактам, что лучше !=1 или !=0.
ОчередьТаймеров[индекс].Период --; // Уменьшаем число в ячейке если не конец.
}
else
{
ДобавитьЗадачу(ОчередьТаймеров[индекс].уЗадача); // Дощелкали до нуля? Пихаем в очередь задачу
ОчередьТаймеров[индекс].уЗадача = Бездействие; // А в ячейку пишем затычку
}
}
}
пуст ТОСРВ::ДиспетчерДлинныхТаймеров(пуст)
{
беззнак char индекс;
для (индекс = 0; индекс != Длина_Очереди_Таймеров + 1; индекс++) // Прочесываем очередь таймеров
{
если (ОчередьДлинныхТаймеров[индекс].уЗадача == Бездействие)
{
continue; // Если нашли пустышку - щелкаем следующую итерацию
}
если (ОчередьДлинныхТаймеров[индекс].Период != 1) // Если таймер не выщелкал, то щелкаем еще раз.
{
// To Do: Вычислить по тактам, что лучше !=1 или !=0.
ОчередьДлинныхТаймеров[индекс].Период --; // Уменьшаем число в ячейке если не конец.
}
else
{
ДобавитьЗадачу(ОчередьДлинныхТаймеров[индекс].уЗадача); // Дощелкали до нуля? Пихаем в очередь задачу
ОчередьДлинныхТаймеров[индекс].уЗадача = Бездействие; // А в ячейку пишем затычку
}
}
}
/*=================================================================================
Диспетчер задач ОС. Выбирает из очереди задачи и отправляет на выполнение.
*/
пуст ТОСРВ::ДиспетчерЗадач(пуст)
{
беззнак симв индекс=0;
ТуЗадача уЗадача = Бездействие; // Инициализируем переменные
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; // Запрещаем прерывания!!!
уЗадача = ОчередьЗадач[0]; // Хватаем первое значение из очереди
если (уЗадача==Бездействие) // Если там пусто
{
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Разрешаем прерывания
(Бездействие)(); // Переходим на обработку пустого цикла
}
else
{
для(индекс=0;индекс!=Длина_Очереди_Задач;индекс++) // В противном случае сдвигаем всю очередь
{
ОчередьЗадач[индекс]=ОчередьЗадач[индекс+1];
}
ОчередьЗадач[Длина_Очереди_Задач]= Бездействие; // В последнюю запись пихаем затычку
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; // Разрешаем прерывания
(уЗадача)(); // Переходим к задаче
}
}
Пример. Вроде все работает.
Отредактировано Евгений (2023-03-19 00:15:11)