реклама на сайте
подробности

 
 
> Нарисовал сигналы к FreeRTOS, давайте вместе думать.
klen
сообщение Aug 23 2006, 18:31
Сообщение #1


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Ниже FreeRTOS я буду называть всетаки планировщиком задач а не ОС. Сами знаете почему.
Вчера завершил этап написания софта для бортовой ЭВМ которую хочу поставить на авиамодель. Процессор LPC2103. В качестве основы использую FreeRTOS 4.0.5. С целью жесткой временной синхронизации всех веременных событий - прем пакета с радиомодема, отработка системной команды, вычисление требуемых управляющих воздействий, обмен по I2С c исполнительными устройствами, и выдача телеметрии назад радиомодему , плюс возможные асинхронные события.

Все построено на взаимодействии задач - собственно планировщики для этого и придуманы. Очень удобно но! МЕДЛЕННО. Почему? Потому что в FreeRTOS нет специализированных средств синхронизации задач. Единственно доступный способ - через очереди сообщенй, семафоры сделаны как макросы их использующие. В результате все медленно.
За критерий производительности средств синхронизации буду понимать задержку между моментами вызова разблокирующй функции в ведущей задаче до момента выхода из блокирующей функции в синхонизируемой ведомой задаче.
Проблема - сделать синхронизацию задач быстрее.
1. В простейшем случае можно использовать vTaskResume/xTaskResumeFromISR/vTaskSuspend
но сами понимаете вариант органически УБОГИЙ но БЫСТРЫЙ. Если вам прийдется передвать информацию, то нада использовать глобальные переменные. Основной недостаток это отсутствие в таком подходе понятий "задача выполняется но ждет сигнала = реально не выполняется" или "задача заблокирована и ждет сигнала= реально не выполняется" - суть совершенно разные состояния задачи. И тд и тп с вытекающими.
2. Использование очередей - вариант НЕУБОГИЙ но МЕДЛЕННЫЙ. Как говорили мои учителя этот вариант соответствует забиванию гвоздей соток видеомагнитафоном. С пляжа....
3. Предлагается третий вариант - подход класический : отбросить плохие качества и соеденить хорошие. Сложная реализация этой простоий и гениальной ничего неговорящей по сути идеи:
а) Быстее чем vTaskResume/xTaskResumeFromISR/vTaskSuspend сделать не удастся по причине того что любая синхронизация - суть переключение контекстов. А vTaskResume/xTaskResumeFromISR/vTaskSuspend это иесть оное переключение в ПРАВИЛЬНОМ и ЛЫСОМ виде. Отсюда вывод - будем использовать vTaskResume/xTaskResumeFromISR/vTaskSuspend как ядро объектов синхронизации, а нативную логику обектов - в БЫСТРОЙ оболочке вызывающей vTaskResume/xTaskResumeFromISR/
vTaskSuspend.
б) После изучения исходников линукса и того что есть по виндам "объекты синхронизации" можно разложитьб на две большие кучи:
1. Сигналы - суть есть програмные прерывания. Ососбенность - "приемник" сигналов есть ЗАДАЧА. Тоесть сигнал послать можно именно задаче. В МОМЕНТ ПРИЕМА ПРОИСХОДИТ ПРЕРЫВАНИЕ ЗАДАЧИ И ВЫПОЛНЕТСЯ ОБРАБОТЧИК СИГНАЛА , далее задача продолжает свое выполнение с места прерывания.
2. События/семафоры/так далее - суть отдельные от ЗАДАЧИ объекты которые живут в памяти и во времени ОТДЕЛНО. Особенность - "приемник" события - есть обект, которым может владеть любая ЗАДАЧА (пример - использование очередей в FreeRTOS для синхронизации ЗАДАЧ) В МОМЕНТ ПРИЕМА ПРОИСХОДИТ РАЗБЛОКИРОВАНЕ ЗАДАЧИ, далее задача продолжает свое выполнение.

У меня получился ГИБРИД - семантически всетаки это реализация сигналов(СИГНАЛЫ ПОСЫЛАЮТСЯ ЗАДАЧАМ И ИМ ПРЕНАДЛЕЖАТ), синтаксически - события(ФУНКЦИОНАЛЬН РЕАЛИЗОВАНО КАК БЛОКИРОВАНИЕ/РАЗБЛОКИРОВАНИЕ ЗАДАЧ). Как назвать эту поронграфию я не придумал - и сигналы и события не правльно, поэтому командирским решение буду назыать это СИГНАЛЫ всетаки.

Теперь собственно ближе к телу.
Добавлено к ядру файл signal.с и signal.h в которых реализованы

// функция устанавливает сигнал Signal (сигнальное битовое поле) для задачи pxTask
// если это позволяет сделать сигнальная маска задачи, устанавливает флаг сброса события по приему SignalReset
void vSignalSet ( xTaskHandle pxTask , // дескриптор задачи-приемника сигнала
portBASE_TYPE Signal , // битовое поле сигнала
portBASE_TYPE SignalReset // флаг сброса битов сигнала после приема ожидающей задачей
);

// аналогично предыдущей но для вызовов из обработчиков прерывания
void vSignalSetFromISR
( xTaskHandle pxTask , // дескриптор задачи-приемника события
portBASE_TYPE Signal , // битовая маска события
portBASE_TYPE SignalReset // флаг сброса события после приема ожидающей задачей
);

// блокирующая функция ожидания сигнала
// если сигнал установлен то функция немедленно возвращает управление ,
// при установленом для задачи флаге SignalReset сбрасывает сигнал и флаг сброса
// в буффер помещается принятый сигнал
void vSignalWait
( portBASE_TYPE *Signal // указатель на буффер-приемник битового поля сигнала
) ;

// функция выполняет прямое чтение битового поля сигнала задачи ее вызвавшей
void vSignalTest
( portBASE_TYPE *Signal // указатель на буффер-приемник битового поля сигнала
) ;

// функция установки сигнальной маски SignalMask задачи pxTask
void vSignalMaskSet
( xTaskHandle pxTask , // дескриптор задачи-приемника маски сигнала
portBASE_TYPE SignalMask // сигнальная маска
) ;
// функция чтения сигнальной маски в *SignalMask задачи pxTask
void vSignalMaskGet
(
xTaskHandle pxTask , // дескриптор задачи-источника маски сигнала
portBASE_TYPE *SignalMask // буффер сигнальная маска
);


vTaskResume/xTaskResumeFromISR/vTaskSuspend перепилены для реализации переключения не двух а четырех состояний ЗАДАЧИ.


a)Каждая задача содержит управлющую событиями структуру (расширина структура taskTCB)
б)Посылать сигналы можгут другие задачи
в)Задача имеет сигнальную маску фильтрующую посылаймые сигналы
г) "Сигнал" - битовое 32-битное поле, каждый разрад которого соответствует определенному типу сигнала, тоесть одновремено можно посылать комбинацию сигнальчиков которые и состовляют сигнал.
д)Реализованы состояния "задача выполняется но ждет сигнала = реально не выполняется" или "задача заблокирована и ждет сигнала = реально не выполняется" путем рашснирения состояний ЗАДАЧ SUSPEND и RESUME. Это означает что если ЗАДАЧА вызовет vSignalWait и перейдет врежим блоировани она будет в состоянии "задача ВЫПОЛНЯЕТЯ и ждет сигнала = реально не выполняется" вызов vSignalSet разблокирует ее. Если в состоянии блоктровки какой либо ЗАДАЧЕЙ она была заблокирована xTaskSuspend то вызов vSignalSet не разблокирует ее а только переведет в состояне "задача ЗАБЛОКИРОВАНА и не ждет сигнала = реально не выполняется"
е) Задача может находится в 4 состояниях (Pending я тут не считаю за состояние, так как это больше состояне процесора и относится к аппаратным прерываниям)

Внижеприведенных рисунках показыны циклограммы перехода ЗАДАЧИ из ожидающего состояния в активное. Момент подняти пина соответствует команда перед вызвом разблокирующей функции, опускание пина - выход синхронизируймой ЗАДАЧИ из блокирующей функции - тоесть окончание акта синхронизации. 1 рисунок - сделано на очередях 2 - на сигналах 3- на ЛЫСЫХ vTaskResume/xTaskResumeFromISR/vTaskSuspend

В итоге пеерключение на очередях - 42,0мкс, на сигналах 12,8 мкс, на лысых 10,4 мкс на частоте 88МГц ядра. Тоесть я получил частично что хотел. В архиве демо-проект под CrossWorks. там можно посмотреть ИМПЛЕМЕНТАЦИЮ СЕГО УЖАСА НАШЕГО ГОРОДЖКА ninja.gif

Предлагаю обсудить куда двигатся дальше, мож у кого еще иде и есть. Давайте дискутировать. Вопрос быстрой синхронизации - как говорят подонки ЗЫЖОВОТРИПЫХАЮЩИСЯ !!! тоесть очень важный.

Сообщение отредактировал klen - Aug 23 2006, 18:35
Эскизы прикрепленных изображений
Прикрепленное изображение
 

Прикрепленные файлы
Прикрепленный файл  FreeRTOS_dev.rar ( 131.49 килобайт ) Кол-во скачиваний: 45
 
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:30
Рейтинг@Mail.ru


Страница сгенерированна за 0.01374 секунд с 7
ELECTRONIX ©2004-2016