Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Выпущена scmRTOS 4.0.
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
Страницы: 1, 2, 3, 4, 5, 6
IgorKossak
Хочется надеяться, что на том и порешили.
Дальше, если можно, по делу.
Nixon
Хотелось бы в рантайме иметь возможность определения типа контроллера на котором работает scmRTOS (хотя бы один байт). Чтобы не плодить плагины для IAR под разные типы контроллеров.
mdmitry
Цитата(Nixon @ Apr 12 2012, 16:33) *
Хотелось бы в рантайме иметь возможность определения типа контроллера на котором работает scmRTOS (хотя бы один байт). Чтобы не плодить плагины для IAR под разные типы контроллеров.

Тип контроллера задается при сборке (или его можно как define задать) и использовать в коде. Задать статическую переменную и её использовать по своему усмотрению (иногда надо было). Это же не связано с RTOS.
Или я вопроса не понял?
Сергей Борщ
QUOTE (Nixon @ Apr 12 2012, 15:33) *
Хотелось бы в рантайме иметь возможность определения типа контроллера на котором работает scmRTOS (хотя бы один байт). Чтобы не плодить плагины для IAR под разные типы контроллеров.
Что мешает этот байт вставить в прошивку в виде константы и считывать ее из памяти контроллера плагином?
Nixon
Все правильно, но из плагина я читаю переменную или по имени или по адресу. Второе делать постоянным (для плагина) нет возможности, а первое делать постоянным лучше внутри OS.
_Артём_
Цитата(Nixon @ Apr 12 2012, 16:04) *
Все правильно, но из плагина я читаю переменную или по имени или по адресу. Второе делать постоянным (для плагина) нет возможности, а первое делать постоянным лучше внутри OS.

А о каких плагинах речь?
Aprox
Цитата(IgorKossak @ Apr 12 2012, 16:24) *
Дальше, если можно, по делу.

А по делу, - хочется видеть в составе scmRTOS класс задач, которые умеют ожидать настоящие прерывания от периферии. Безумный вариант через SW не предлагать. Еще хочется видеть эти прерывания вложенными по приоритету, т.е никаких запретов на время исполнения ISR. Видите, как просто -хочется, чтобы C++ наконец-то заработал на современных чипах.

PS. Забыл совсем. SW прерывания для медленных фоновых задач вполне можно оставить, какие они сейчас уже есть.
IgorKossak
Цитата(Aprox @ Apr 12 2012, 20:42) *
А по делу, - хочется видеть в составе scmRTOS класс задач, которые умеют ожидать настоящие прерывания от периферии. Безумный вариант через SW не предлагать. Еще хочется видеть эти прерывания вложенными по приоритету, т.е никаких запретов на время исполнения ISR.

Один из моих бывших коллег, мельком взглянув на эту ОС сразу же от неё отказался, т. к. у неё, видите ли, количество процессов всего 32, а ему надо было больше сотни. То, что он просто не умеет грамотно спланировать программу в расчёт не принималось. Этакий вариант "перепланирование не предлагать".
У меня к Вам встречный вопрос - а на фейхуа оно надо? За более чем шестилетний срок работы с этой ос с первой её версии и реализованную массу проектов у меня такого пожелания не возникло.
Правда, было пару случаев, когда я высказывал авторам свои хотелки, но при этом серьёзно и обстоятельно их обосновывал.
Цитата(Aprox @ Apr 12 2012, 20:42) *
Видите, как просто -хочется, чтобы C++ наконец-то заработал на современных чипах.

Я вижу то, что Ваше пожелание никоим образом C++ не касается.
MrYuran
Цитата(Aprox @ Apr 12 2012, 21:42) *
А по делу, - хочется видеть в составе scmRTOS класс задач, которые умеют ожидать настоящие прерывания от периферии. Безумный вариант через SW не предлагать.

А вы сами как это себе представляете?
Задача, целиком размещенная в обработчике прерывания?
По-моему, это будет уже совершенно другая система со своей идеологией.
ReAl
Цитата(MrYuran @ Apr 12 2012, 20:57) *
А вы сами как это себе представляете?
Я думаю — никак. Иначе уже хотя бы какой-то конструктив проскочил. В виде «высокоуровневого» (на человеческом языке) описания происходящих процессов.

Цитата(MrYuran @ Apr 12 2012, 20:57) *
Задача, целиком размещенная в обработчике прерывания?
Не, это будет то, что тут сказано — задача, спрятанная в обработчик целиком. А не ожидающая "настоящие прерывания".
Если я правильно понял многократно повторенное желание — то-то в духе того, что можно сейчас сделать путём:

Код
OS::TEventFlag ef;

template<> void TProc1::exec()
{
    ...
    ef.wait();
    ...
}

OS_INTERRUPT void SomeISR()
{
    OS::TISRW isrw;
    ef.signal_isr(); // и больше тут ничего, к аппаратуре будет обращаться сама задача
}
Но только чтобы это было без этой SomeISR(). Вот как только аппаратное прерывание возникло, так с точки за ef.wait() и продолжить. А как в другом месте поднимется флаг прерывания, кторого ждёт более приоритетный процесс, так чтобы так же без отдельного обработчика и флага сразу туда. А если менее приоритетный, то чтобы «оно» ждало.
Я не могу понять
  • Причём к этой хотелке фраза "C++ наконец-то заработал на современных чипах" (если бы такое можно было сделать, то это можно было бы и на С)
  • Чем так кардинально отличается Cortex-M3 или там ARM9 от AVR или MSP430, что в нём уже можно это сделать. На мой взгляд, такая хотелка подразумевает аппаратную реализацию планировщика ОС и переключения контекста, всё остальное по реально происходящим действиям (вход в ISR, отмашка конкретного события и отметка задачи как готовой к исполнению, перепланирование и переключение консткста) и временам (отрабатываемым инструкциям процессора) практически не будет отличаться от приведенного выше примера с вырожденным обработчиком прерывания, даже если при помощи каких-то языковых или внеязыковых средств визуально оно будет выглядеть без такого вырожденного обработчика и с каким-то OS::Wait(TIMER1_IRQ); в коде процесса.

Повторюсь — с точки зрения хотелки, если я её правильно понял, все используемые нами микроконтроллеры одинаковые (ну некоторые не имеют приоритетной системы прерываний). Это где-то в районе могилы iAPX 432 копать надо.
dxp
QUOTE (IgorKossak @ Apr 13 2012, 00:56) *
Правда, было пару случаев, когда я высказывал авторам свои хотелки, но при этом серьёзно и обстоятельно их обосновывал.

Одну я помню - про принудительное завершение работы процесса (с последующим перезапуском), это в v4 реализовано. А какая вторая?

QUOTE (ReAl @ Apr 13 2012, 03:33) *
Но только чтобы это было без этой SomeISR(). Вот как только аппаратное прерывание возникло, так с точки за ef.wait() и продолжить. А как в другом месте поднимется флаг прерывания, кторого ждёт более приоритетный процесс, так чтобы так же без отдельного обработчика и флага сразу туда. А если менее приоритетный, то чтобы «оно» ждало.

Ну, а системе-то надо как-то "объяснить", по какому конкретно прерыванию в какой код переходить. Т.е. всё равно тут должно быть для того средство. Вот описание такого ISR и является по сути этим средством. Но выраженным штатными возможностями программных пакетов и предоставляющем дополнительную функциональность (можно внутри обработчика какой-то "неотложный"/служебный код выполнить). А сам такой обработчик, если он ничего, кроме сигнала флага не делает, можно вообще в одну строку записать без потери читабельности.

И технически можно было бы сделать так, чтобы при возникновении аппаратного прерывания передача управления сразу была в нужный код (забивать адрес, на который переходить), только учитывая, что всё равно имеет место вытеснение и приоритетность, без переключения контекста и выяснения приоритетности не обойтись. Поэтому эта хотелка вырождается именно в то, что имеем сейчас, практически в чистом виде, ничего лишнего у нас там нет: в ISR делается 1) активизация ожидающего процесса; 2) вызов планировщика, где обрабатываются приоритеты с последующим переключением контекстов (если необходимо).
ReAl
Цитата(dxp @ Apr 13 2012, 06:35) *
Ну, а системе-то надо как-то "объяснить", по какому конкретно прерыванию в какой код переходить. Т.е. всё равно тут должно быть для того средство.
Так я об этом и говорю. Даже если налепить «синтаксический сахар» OS::wait_TRUE_hardware_interrupt(TIMER1_IRQ); (толи допиливанием языка, как во всяких DynamicC, толи внешним препроцессором), всё равно в микроконтроллере — частично аппаратно, частично программно — будет произведена та же самая последовательность действий.
  • Возникновение аппаратного прерывания — тут с приоритетами и т.п. все в железе.
  • Переход (возможно, через некоторое время) на обработчик — это тоже в железе.
  • В обработчике программно (ну где-то же надо, а аппаратно не реализовано) решить
    • ждёт ли данный процесс этого события или он и так выполняется, но занят чем-то другим — нужно пометить, что потом ему не нужно ждать,
    • имеет ли право данный процесс выполняться сразу — переключиться на него сразу,
    • если права не имеет — пометить, что на него нужно перейти как только он право получит.
  • Если процесс ждал и звёзды благосклонны к данному процессу — переключить на него. Может быть частично поддержано/ускорено аппаратно.

Всё это во всех современных микроконтроллерах, в документацию на которые я заглядывал, будет одинаково молотиться программно. Если и можно что-то возложить на ПДП, то по прерыванию об окончании его работы всё равно пойдут те же процессы.
Ну никакой надежды на то, чтобы «C++ наконец-то заработал на современных чипах» biggrin.gif

Причём, как уже было сказано не раз, нужно просто один из методов «драйверного» класса вызывать непосредственно в прерывании и реакция будет максимально быстрая. Если отталкиваться от точки зрения, что вызов метода есть посылкой сообщения объекту, то вызов метода из ISR становится посылкой аппаратного сообщения тем образом, которым «современный чип» только и может это сделать.

Кстати, Cortex-M3 таки молодчинка. Если глянуть табличку времён переключения процесса (по 1-EventFlag, от поднятия лапки в прерывании до опускания в приоритетном процессе), состоящее из перепланирования и переключения контекста, взять оттуда и перемножить микросекунды на мегагерцы, то получим
BlackFin: 360 (ну тут, наверное, контекст большой)
AVR: ~320 (контекст великоват да и push/pop выполняются по два такта)
ARM7, MSP430: ~250
Cortex-M3: 195 (а с учётом последней поправки — 180 ?)

p.s[0] STM8/IAR — собственно переключение контекста немного короче, чем у AVR, перепланирование немного длиннее, но в целом немного быстрее.
p.s[1] Вот же ж зараза, вместо того, чтобы ещё абзац родить для странички STM8 Port в вики scmRTOS, сижу и, как и во времена RU.EMBEDDED, пишу не так для того, с кем формально «дискутирую», как для других — чтобы ему не поверили :-)
p.s[2] побежал я на работу...
IgorKossak
Цитата(dxp @ Apr 13 2012, 06:35) *
Одну я помню - про принудительное завершение работы процесса (с последующим перезапуском), это в v4 реализовано. А какая вторая?

Про персонализацию мютексов. Кто из процессов залочил - тот и разлочить может.
Lotor
Позиция авторов, что задачи с одинаковым приоритетом избыточны, не потерпит изменения в будущем?
Aprox
Цитата(ReAl @ Apr 13 2012, 00:33) *
Я думаю — никак. Иначе уже хотя бы какой-то конструктив проскочил. В виде «высокоуровневого» (на человеческом языке) описания происходящих процессов.
Не, это будет то, что тут сказано — задача, спрятанная в обработчик целиком. А не ожидающая "настоящие прерывания".

Нет, не целиком. Я вижу задачу периферии в виде статического класса C++, у которого только метод exec() оформлен как ISR от периферии. Конструктор же класса- отдельно. Также отдельно от ISR методы коммуникации с другими процессами. Если чип позволяет вложенные прерывания по приоритету, как например в последних Cortex, то автоматически решается проблема приоритетов задач. А использование задачи в виде класса с защищенными данными и методами автоматически решает проблему сохранения контекстов на переключениях, нет нужды в стеках для каждой отдельной задачи. Это вероятно дилетантский подход с точки зрения знатоков С++ и OS, но у меня, как ни странно, он работает в задачах связи.

Цитата
Если я правильно понял многократно повторенное желание — то-то в духе того, что можно сейчас сделать путём:
[ пример skipped]

Ваш вариант использования того, что есть в scmRTOS - плох тем, что хочешь не хочешь, а придется идти длинным путем через OS, через диспетчер, через полинг, через арбитр приоритетов.... когда сработает, да и сработает ли вообще посланный signal - никто толком не знает. В моем варианте- все четко и практически мгновенно.
Nixon
Цитата(Aprox @ Apr 13 2012, 10:18) *
Если чип позволяет вложенные прерывания по приоритету, как например в последних Cortex, то автоматически решается проблема приоритетов задач. А использование задачи в виде класса с защищенными данными и методами автоматически решает проблему сохранения контекстов на переключениях, нет нужды в стеках для каждой отдельной задачи.
blink.gif
Отличное описание обычной (без OS) программы.
dxp
QUOTE (ReAl @ Apr 13 2012, 12:18) *
Кстати, Cortex-M3 таки молодчинка. Если глянуть табличку времён переключения процесса (по 1-EventFlag, от поднятия лапки в прерывании до опускания в приоритетном процессе), состоящее из перепланирования и переключения контекста, взять оттуда и перемножить микросекунды на мегагерцы, то получим
BlackFin: 360 (ну тут, наверное, контекст большой)

Да, контекст здоровенный, порядка 180 байт. Частично компенсируется высокой скоростью проца (при низком потреблении).


QUOTE (ReAl @ Apr 13 2012, 12:18) *
p.s[1] Вот же ж зараза, вместо того, чтобы ещё абзац родить для странички STM8 Port в вики scmRTOS, сижу и, как и во времена RU.EMBEDDED, пишу не так для того, с кем формально «дискутирую», как для других — чтобы ему не поверили :-)

Не, нормально - такие посты очень полезны - расставляют точки над "ё", структурируют обсуждение и выводы. Такое, даже если знаешь суть, все равно всегда приятно читать.

QUOTE (IgorKossak @ Apr 13 2012, 13:42) *
Про персонализацию мютексов. Кто из процессов залочил - тот и разлочить может.

А, ну это тоже сделано. + ещё можно разлочить в ISR, такое тоже может быть необходимым. Ну, и теперь можно никого не спрашивая, родить свой собственный мутекс. И поделиться им с другими. sm.gif


QUOTE (Lotor @ Apr 13 2012, 13:44) *
Позиция авторов, что задачи с одинаковым приоритетом избыточны, не потерпит изменения в будущем?

Смысл в такой фиче?

QUOTE (Aprox @ Apr 13 2012, 14:18) *
Ваш вариант использования того, что есть в scmRTOS - плох тем, что хочешь не хочешь, а придется идти длинным путем через OS, через диспетчер, через полинг, через арбитр приоритетов....

А как вы собираетесь организовывать псевдопараллельную работу процессов (задач) с вытеснением? И, кстати, о каком поллинге идёт речь?

QUOTE (Aprox @ Apr 13 2012, 14:18) *
когда сработает, да и сработает ли вообще посланный signal - никто толком не знает. В моем варианте- все четко и практически мгновенно.

Если signal послан, то сработает. В соответствии с логикой работы программы и приоритетами. В вашем варианте имеет место просто работа программы на голом железе и ни о какой синхронизации между процессами и передаче управления речь не идёт.
Nixon
Хотел бы еще добавить свои пять копеек. IMHO полезность rtos лижит именно в области обеспечения целостности и непротиворечивости алгоритма работы программы (конечно при условии грамотного проектирования). Скорость, потребление ресурсов и другие параметры это уже проблемы второго плана.
Если же вы хотите экстремально быстро и/или минимально объемно, то отбрасывайте все обертки в виде rtos/библиотек/др. и пишите все ручками.
А все разговоры о включении в rtos каких-либо мифических классов DMA-обработчиков полностью несостоятельны - даже мегасупер OS не сделает за вас всей вашей работы - придется и мозгами пошевелить.

По поводу предложений - хотелось бы поменьше disable_interrupt() иметь в коде rtos. Или хотя бы запрещать прерывания только по определенной маске. Оно конечно полностью запретить все прерывания на момент переключения контекста вроде бы как правильно и универсально, но иногда нужно иметь немаскируемое операционкой прерывание.
Lotor
Цитата(dxp @ Apr 13 2012, 17:08) *
Смысл в такой фиче?

У меня была ситуация, когда надо было принимать и писать на карточку непрерывный поток данных и в тоже время рисовать на дисплее, реагировать на кнопки. Явно указать места блокировки было затруднительно, поэтому реализовал это с помощью одинаковых приоритетов.
Поискал по форумы, zltigo тоже утверждал, что ему такая штука необходима для обслуживание некого количества однотипных каналов
IgorKossak
Цитата(Lotor @ Apr 13 2012, 16:46) *
... такая штука необходима для обслуживание некого количества однотипных каналов

1. Если порядок обслуживания однотипных каналов (или другого рода процессов сходного приоритета) важен, то можно им назначить сетку рядом стоЯщих приоритетов.
2. Если порядок не важен, то, как частный случай, можно согласиться с решением п. 1.
haker_fox
QUOTE (Aprox @ Apr 13 2012, 15:18) *
В моем варианте- все четко и практически мгновенно.

Уважаемый Aprox, вот Вы много чего интересного предложили, критикуя и критикуя эту ОС. Древние говорили: "критикуя, предлагай!". А проект является открытым. Намек понятен? rolleyes.gif

Если не хотите ничего в виде кода писать, то может пора завязать? maniac.gif
dxp
QUOTE (Nixon @ Apr 13 2012, 20:27) *
По поводу предложений - хотелось бы поменьше disable_interrupt() иметь в коде rtos. Или хотя бы запрещать прерывания только по определенной маске. Оно конечно полностью запретить все прерывания на момент переключения контекста вроде бы как правильно и универсально, но иногда нужно иметь немаскируемое операционкой прерывание.

Это тогда просится определение класса TCritSect отдать на откуп пользователю. Потому как заранее ведь неизвестно, какие прерывания можно маскировать, а какие нет. Кроме того, не все процы нормально поддерживают такие вещи, а, как правило, только те, у которых есть аппаратный приоритетный контроллер прерываний. В любом случае щас то дело конкретного порта. Ну, а по факту запеты эти оказываются очень недолгими - там же всё мелкое, простое и быстрое.

QUOTE (Lotor @ Apr 13 2012, 20:46) *
У меня была ситуация, когда надо было принимать и писать на карточку непрерывный поток данных и в тоже время рисовать на дисплее, реагировать на кнопки. Явно указать места блокировки было затруднительно, поэтому реализовал это с помощью одинаковых приоритетов.
Поискал по форумы, zltigo тоже утверждал, что ему такая штука необходима для обслуживание некого количества однотипных каналов

Да, тему поднимали неоднократно, в том числе и с zltigo. Ему задавался этот же вопрос. Он на него не привёл технических аргументов, а сказал лишь, что ему лично так больше нравится, это его эстетическое предпочтение.

По сути. Если задачи требуют какого-то реалтайма, то они выстраиваются по приоритетам - когда есть срочность выполнения, всегда встаёт приоритет. Если задачи просто должны быть выполнены в фоне приоритетных, то их можно выполнять просто в пределах одного процесса по очереди. Планировка задач с одинаковым приоритетом по схеме round-robin с вытеснением ничего тут не даёт, кроме накладных расходов на вытеснение (где оно по сути-то и не нужно) и на стеки дополнительных процессов.

Кроме того, следует иметь в виду, что ничего там безплатно не даётся. Любая функциональность потребует расходов. В scmRTOS планировщик сделан намеренно максимально простым и быстрым, и возможно это стало благодаря тому, что механизм организации процессов в виде битовой карты, представляющей собой упакованное слово без "дырок", позволяет манипулировать процессами буквально считанными инструкциями процессора. Позволь тут хотя бы "дырки", и уже код планировщика будет выполняться вдвое дольше. Позволь тут более сложные схемы - с одинаковыми приоритетами и "каруселью", и время время работы планировщика вырастет в разы.

И чего ради? Чем это лучше варинта, когда срочные задачи живут в более приоритетных процессах, а несрочные - в одном-двух низкоприоритетных, где они выполняются по очереди. Получается, и реалтайм соблюдён, и накладных минимум. Я вообще всю несрочную работу отправляю в фон путём делегирования выполнения (через очередь сообщений).

Вариант с равными приоритетами и карусельным вытеснением хорошо ложится на большие ОСи, где множество процессов живёт своей жизнью, очень долго, и реальтайм не важен. В RTOS же ситуация в корне другая, и такой способ планировки, ПМСМ, ничего кроме недостатков не имеет.

ReAl
Цитата(Aprox @ Apr 13 2012, 10:18) *
Нет, не целиком. Я вижу задачу периферии в виде статического класса C++, у которого только метод exec() оформлен как ISR от периферии. Конструктор же класса- отдельно. Также отдельно от ISR методы коммуникации с другими процессами. Если чип позволяет вложенные прерывания по приоритету, как например в последних Cortex, то автоматически решается проблема приоритетов задач.
Какой такой павлин-шмавлин exec() ? В этом методе, «оформленном как ISR» нельзя будет оспользовать sleep() или wait(), иначе это поломает всю работу планировщика. Т.е. нельзя будет пользоваться сервисами ОС, предназнаяґченными для процессов.
Кроме того, тут нигде нет «задача ожидает настоящего аппаратного прерывания», той Вашей фразы, которая вызвала всеобщее недоумение. Этот метод сам есть обработчиком. Не процессом, который не работает-работает, да и подождет прерывания, а обработчиком, который только по прерыванию вызывается, отрабатывает и из прерывания выходит:
Цитата(ReAl @ Apr 13 2012, 08:18) *
Причём, как уже было сказано не раз, нужно просто один из методов «драйверного» класса вызывать непосредственно в прерывании и реакция будет максимально быстрая. Если отталкиваться от точки зрения, что вызов метода есть посылкой сообщения объекту, то вызов метода из ISR становится посылкой аппаратного сообщения тем образом, которым «современный чип» только и может это сделать.

Если бы Вы драйвер не назвали процессом (и не страдали от того, что якобы в scmRTOS их нельзя сделать), то и такого длинного обсуждения не было бы.

Цитата(Aprox @ Apr 13 2012, 10:18) *
Ваш вариант использования того, что есть в scmRTOS - плох тем
Это Ваш вариант этим плох. У нас прекрасно рядом с классами процессов, имеющих метод exec() и переключающихся через планировщик ОС, уживаются классы драйверов периферии, не имеющие метода exec() и не являющиеся процессами ОС. Но в «методах коммуникации с другими процессами» захватывающие мьютексы и ожидающие событий, а в методах xxx_isr(). Иногда по нескольку таких методов на один класс драйвера, скажем, методы rxc_isr(), txc_isr(), udre_isr() oc1a_iar() (последний для отработки прерывания защитного тайм-аута). Но это не процессы ОС, а драйвера!
Им и не нужны отдельные стеки, так как вызовы со стороны процессов отрабатываются на стеках процессов а обработка прерываний — как по реализации сделано, на стеках подвернувшихся под горячую руку процессов либо на отдельном стеке обработки прерываний.
Просто никому до сих пор не пришло в голову назвать эти классы процессами, оформить их как процессы, заставить работать как процессы и страдать от их медлительности.

http://electronix.ru/forum/lofiversion/index.php/t56221.html
http://electronix.ru/forum/lofiversion/index.php/t82907.html
http://electronix.ru/forum/lofiversion/ind...hp/t100210.html

p.s Короче говоря, получилось «вашими отвёртками неудобно дырки ковырять, вот если бы ваши отвертки были круглые с коническим заострённым кончиком! Если бы они наконец-то использовали возможности современного металла!»
Кто ж знал, что вместо доказывания того, что отвёртки такими не бывают в принципе, что «+»-овые, что «—»-овые, нужно было просто об́яснить, что это называется шило и именно его и нужно брать для ковыряния дырок...
Aprox
Цитата(Nixon @ Apr 13 2012, 11:25) *
Отличное описание обычной (без OS) программы.

Точнее сказать, без привычной из прошлого OS. В реальности я получаю те же самые функции OS, вытеснение процессов с учетом приоритета, но использую фичи железа современных чипов, а не софт. Видимо, отсюда и непонимание друг-друга, программистов и железячников. В результате произведенной разведки scmRTOS, я понял главное - мне она не нужна. Извините, если кого обидел.

ReAl
Вы её просто не умеете готовить. Как, видимо, и любую другую вытесняющую ОС, так как то же самое будет в любой другой независимо от языка реализации.

Если Вы «драйверные» по сути вещи будете запихивать в отдельные процессы с ожиданием посланного сообщения из тупого обработчика прерываний, то будет то же самое — большие задержки, большие расходы не переключение задач, на стеки процессов.

Если Вы «драйверные» вещи выделите в отдельные классы, как в обсуждениях по ссылкам в предыдущем моём сообщении, а в процесс будете отправлять уже «высокоуровневый» результат работы драйвера, то отрабатывать драйверные прерывания будут так же быстро, как и в программе без какой-либо ОС. Всю быструю работу будет делать драйвер, остальное — разбуженный результатом процесс. Это вполне реализуемо в рамках scmRTOS.

Не нравится отдельный драйверный класс — сделайте свой хитрый процесс. Раз он хитрый — Вам не удастся воспользоваться готовым шаблоном для стандарнтых процессов, но Вы тут так много говорили про С++, что у Вас не должно быть проблем сделать, например, такое (за основу взят пример 2 из пакета avr-gcc и проверено в железе):
CODE

//******************************************************************************
//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
//* NICKNAME: scmRTOS
//* PROCESSOR: AVR (Atmel)
//* TOOLKIT: avr-gcc (GNU)
//* PURPOSE: avr-gcc Port Test File

... порезано ...

//******************************************************************************

//---------------------------------------------------------------------------
#include <avr/io.h>
#include "pin_macros.h"
#include <scmRTOS.h>

#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
// for analog comparator initialisation in main()
#include <util/delay.h>
#endif


//---------------------------------------------------------------------------
// Sample target
// The sample is intended for following AVR microcontrollers:
// atmega48..atmega328
// atmega64, atmega128
// atmega640..atmega2561
// Some changes in register names may be needed for other AVRs.

#if defined(TIMSK1)
# define TIMER1_IE_REG TIMSK1
#elif defined(TIMSK)
# define TIMER1_IE_REG TIMSK
#else
# error "Timer1 interrupt mask register not defined"
#endif

//---------------------------------------------------------------------------
// "Hello, scope!" pins in pin_macros.h notation.
#define TIMER1_ISR D,5,H
#define TIMER1_TO_PROC1 B,0,H
#define PROC1 B,1,H
#define PROC2 B,2,H
#define PROC3 B,3,H
#define TIMER_HOOK B,4,H
#define IDLE_HOOK B,5,H
#define MAMONT_TRUNK C,5,H

//---------------------------------------------------------------------------
struct TMamont // data type for sanding by message
{
enum TSource { PROC_SRC, ISR_SRC } src;
int data;
};

//---------------------------------------------------------------------------
// Process types

// Два процесса стандартные
typedef OS::process<OS::pr1, 160> TProc2;
typedef OS::process<OS::pr2, 120> TProc3;

// Третий имеет методы для общения с себе подобными и метод, отрабатывающий
// «в ожидании НАСТОЯЩЕГО прерывания»

// avr-gcc не позволяет объявить статический член класса обработчиком прерывания,
// приходится пользоваться помощью друга
OS_INTERRUPT void TIMER1_COMPA_vect();

// Наследуем от базового типа процесса scmRTOS
class TProc1 : public OS::TBaseProcess
{
friend void TIMER1_COMPA_vect();
public:
// Раз не воспользовались шаблоном стандратного процесса — солнце закатываем вручную
TProc1()
: OS::TBaseProcess( &Stack[stack_size/sizeof(stack_item_t)],
OS::pr0, reinterpret_cast<void (*)()>(exec) )
{
TCCR1B = (1 << WGM12) | (1 << CS10); // CTC mode, clk/1
OCR1A = 40000U;
TIMER1_IE_REG = (1 << OCIE1A); // Timer1 OC interrupt enable
}

// Это для вызова из других процессов
static void send_message(TMamont::TSource source, int data);

private:
static const size_t stack_size = 120;
OS_PROCESS static void exec();

static TMamont Mamont;
static OS::message<TMamont> MamontMsg;

// А это НАСТОЯЩЕЕ прерывание
INLINE void compa_isr();

stack_item_t Stack[stack_size/sizeof(stack_item_t)];
};

TProc1 Proc1;
TMamont TProc1::Mamont;
OS::message<TMamont> TProc1::MamontMsg;

void TProc1::send_message(TMamont::TSource source, int data)
{
TMamont m;
m.src = source;
m.data = data;
MamontMsg = m;
MamontMsg.send();
}

// Этот метод будет вызываться из НАСТОЯЩЕГО прерывания до любого перепланирования и т.п.
// Отрабатывает максимально быстро и может накопить работу (например, принять весь пакет
// по каналу связи) и только потом послать результирующее сообщение.
void TProc1::compa_isr()
{
TMamont m;
m.src = TMamont::ISR_SRC;
m.data = 10;
MamontMsg = m;
ON(MAMONT_TRUNK);
MamontMsg.send_isr();
}


//---------------------------------------------------------------------------
// Process objects
//
TProc2 Proc2;
TProc3 Proc3;

//---------------------------------------------------------------------------
int main()
{
// Start System Timer
TIMER0_CS_REG = (1 << CS01) | (1 << CS00); // clk/64
TIMER0_IE_REG |= (1 << TOIE0);

#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
// Setup analog comparator as software interrupt source
#if PORT_TOGGLE_BY_PIN_WRITE // see pin_macros.h for PORT_TOGGLE_BY_PIN_WRITE definition and sing
ACSR = (1 << ACBG); // Ref ON, interrupt on both edges
#else
ACSR = (1 << ACBG) | (1 << ACIS1); // Ref ON, falling edge
#endif
DRIVER(RAISE_PIN,OUT); // AIN1 - output
// analog comparator propagation and synchronization delay
_delay_us(2);
ACSR |= (1 << ACI); // needed for chips with improved sbi/cbi behavior
ACSR |= (1 << ACIE);
#endif

DRIVER(TIMER1_ISR,OUT);
DRIVER(TIMER_HOOK,OUT);
DRIVER(IDLE_HOOK,OUT);
DRIVER(MAMONT_TRUNK,OUT);
//
OS::run();
}

//---------------------------------------------------------------------------
void TProc1::exec()
{
DRIVER(PROC1,OUT);
DRIVER(TIMER1_TO_PROC1,OUT);
for(;;) {
OFF(PROC1);
MamontMsg.wait();
ON(PROC1);
OFF(TIMER1_TO_PROC1);
MamontMsg.out(Mamont);
if(Mamont.src == TMamont::PROC_SRC) {
OFF(MAMONT_TRUNK);
} else {
OFF(MAMONT_TRUNK);
ON(MAMONT_TRUNK);
OFF(MAMONT_TRUNK);
}
}
} // TProc1::exec()


//---------------------------------------------------------------------------
namespace OS {
template<> OS_PROCESS void TProc2::exec()
{
DRIVER(PROC2,OUT);
for(;;) {
OFF(PROC2);
sleep(20);
ON(PROC2);
}
} // TProc2::exec()
} // namespace OS

//---------------------------------------------------------------------------
namespace OS {
template<> OS_PROCESS void TProc3::exec()
{
DRIVER(PROC3,OUT);
for(;;) {
OFF(PROC3);
sleep(1);
ON(PROC3);
ON(MAMONT_TRUNK);
Proc1.send_message(TMamont::PROC_SRC, 5); // обращаемся к процессу от другого процесса
}
} // TProc3::exec()
} // namespace OS

//---------------------------------------------------------------------------
OS_INTERRUPT void TIMER1_COMPA_vect()
{
ON(TIMER1_ISR);
ON(TIMER1_TO_PROC1);
OS::TISRW ISRW;
// Часть логики процесса работает непосредственно в прерывании без перепланирования
// и без переключения задач
Proc1.compa_isr();
OFF(TIMER1_ISR);
}
Тут имеем быструю реакцию (уже не класса драйвера, а непосредственно класса процесса) на прерывание. Но не в его методе exec(), предназначенном для работы в рамках ненастоящего прерывания вытесняющего планирования ОС, а в его методе compa_isr().
Всё как Вы хотели «но не знали как и постеснялись спросить».
Если ядро имеет приоритетную систему прерываний, как в современных "Электроника-60", 1801ВМ, MSP430, i8051 (вычёркиваем, C++ для него нет и scmRTOS не спортится, но на С всё то же в виде модулей и инкапсуляцией static-об’ектами это работает), ARM, то этот подход, как и с классами драйверов, автоматически ею воспользуется. Нет — не судьба. Но страдать от необходимости «идти длинным путем через OS, через диспетчер, через полинг, через арбитр приоритетов....» не приходится и на AVR.
Более того, в классе драйвера UART для работы в рамке SLIP в передатчике у меня два isr-метода. Метод udre_isr() вообще «внеосевой», оне не пользуется сервисами ОС и очень лёгкий, после него не производится перепланирование (оно и не нужно, данное прерывание ничего не поменяло в состояниях процессов). А вот метод txc_isr() уже сообщает наверх о том, что пакет передан полностью, вызывает сервисы ОС и после него происходит перепланирование.

Цитата(Aprox @ Apr 14 2012, 12:01) *
Точнее сказать, без привычной из прошлого OS.

Из какого прошлого? Кому привычной? Привычной нам ОС или неправильного её использования Вами из-за привычной работы без ОС?

В RT11 (FB) было то же самое — драйвера отрабатывали быстро, при необходимости было более медленное переключение на ожидающую задачу. Без С++ и современных чипов.

А то, что Вы описали — это таки не вытесняющая ОС вообще. Это расталкивание всей работы по обработчикам прерываний с оставшейся программой без каких-либо признаков ОС либо с зачатками кооперативной ОС, пользующейся результатом работы выполненной в прерываниях обработки. Вполне себе решение, пользовался раньше и пользуюсь сейчас. Без ОС или с кооперативной ОС часто иначе невозможно.
Если некоторые поселенные в прерывания задачи довольно длительны, то такой подход просит приоритетной системы вложенных прерываний. да. Но никаких современных чипов для этого не нужно, это есть в MSP430. Это было в 1801ВМ1, ВМ2 30+ лет назад. Там, кстати, в RT11 для драйверов готовые макросы были для регулирования приоритета обработчика, самое важное он делал на большом приоритете, потом снижал приоритет ядра до более низкого и его могли прервать даже те прерывания, которых он победил при первоначальном арбитраже. То же самое я делал на i8051 — после критической по времени части обработчика очищал уровень приоритета и данный обработчик уже могли прервать не только более приоритетные прерывания, но и вобще все, т.е. я снижал уровень приоритета обработчика прерываний до приоритета основного кода. Иногда при этом даже то же самое прерывание прерывало как бы само себя, но шло при этом по другой ветке (по бедности — таймеров не хватало, вот и было на один таймер навешано несколько задач разной периодичности и длительности). Не совсем то, что было в 1801ВМ или что есть у MSP430 или современных чипов, но это именно эта идеология.
Aprox
Цитата(ReAl @ Apr 14 2012, 14:38) *
Если Вы «драйверные» вещи выделите в отдельные классы, как в обсуждениях по ссылкам в предыдущем моём сообщении, а в процесс будете отправлять уже «высокоуровневый» результат работы драйвера, то отрабатывать драйверные прерывания будут так же быстро, как и в программе без какой-либо ОС. Всю быструю работу будет делать драйвер, остальное — разбуженный результатом процесс. Это вполне реализуемо в рамках scmRTOS.

А смысл? Зачем нужна вообще scmOS, если и без нее реализуются все те же самые функции вытеснения процессов с приоритетом и защищенность данных каждой отдельной задачи? Зачем мне осваивать ставшую ненужной OS и подлаживаться под ее условности?
Цитата
Не нравится отдельный драйверный класс — сделайте свой хитрый процесс. Раз он хитрый — Вам не удастся воспользоваться готовым шаблоном для стандарнтых процессов, но Вы тут так много говорили про С++...

Этот язык я использую для опреления задачи реального времени как класса с защищенными методами и данными. Отдельные стеки, сохранять контекст каждой задачи, уже не неужно. Соответственно, одна из главных фич многозадачных OS с приходом C++ выглядит ненужной.
[ коды skipped]
Цитата
Тут имеем быструю реакцию (уже не класса драйвера, а непосредственно класса процесса) на прерывание. Но не в его методе exec(), предназначенном для работы в рамках ненастоящего прерывания вытесняющего планирования ОС, а в его методе compa_isr().

Разделение приложения на "драйвер" и системную часть - очень условно и субьективно. В моем случае можете считать, в программе одни только" драйверы". И эти "драйверы", которые я упорно называю автономными паралелльными процессами, прекрасно взаимодействуют друг с другом и вытесняют друг-друга, без всякой центральной системной части. Конечно, это благодаря только современным чипам, в которых реализованы вложенные прерывания периферии с приоритетом.

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

Видите ли, ссылаться на опыт прошлого, на проблемы со старыми чипами... как-то неконструктивно. Я знаю все те проблемы, сам наплясался с бубном всласть. Сейчас время другое- в чипах появились нормальные прерывания с приоритетом, периферия вся забуферирована через FIFO, не надо программно торопиться с пересылками блоков данных- это за нас делает DMA. Напичкали все, о чем мечталось лет десять назад. Так, пользоваться надо!
sasamy
Цитата(Aprox @ Apr 15 2012, 12:20) *
одна из главных фич многозадачных OS с приходом C++ выглядит ненужной


Вспоминаются слова Высоцкого: "Капитан, Никогда ты не будешь майором!.." Ни один язык не заменит ОС, тем более убогий С++.
AHTOXA
Цитата(Aprox @ Apr 15 2012, 14:20) *
Зачем нужна вообще scmOS, если и без нее реализуются все те же самые функции вытеснения процессов с приоритетом и защищенность данных каждой отдельной задачи?

Может, хватит вам уже позориться, а? Неужели трудно понять, что механизмы инкапсуляции C++ ну никак не защищают данные при конкурентном доступе к ним из разных потоков выполнения (в вашем случае - из прерываний)?
Я, если честно, немного переживаю за "задачи связи" sm.gif
ReAl
Цитата(Aprox @ Apr 15 2012, 11:20) *
Видите ли, ссылаться на опыт прошлого, на проблемы со старыми чипами... как-то неконструктивно.
Я знаю все те проблемы, сам наплясался с бубном всласть. Сейчас время другое- в чипах появились нормальные прерывания с приоритетом
Для тех, кто в танке — повторяю:
  • Система прерываний "Электроники-60" и 1801ВМ ни на гран не хуже таковой у Cortex-M3 (а предзагрузка слова состояния для обработчика из вектора — временами вообще песня, но это к вложенности не имеет отношения, просто удобно).
  • У і8051 система прерываний вполне себе приоритетная с поддержкой вложенных прерываний. Уровней, правда, два или четыре, но для такого мелкого кристалла больше не очень и нужно, с учётом возможности опустить приоритет обработчика на уровень фонового процесса мне больше трёх никогда не было нужно. На AVR первое время страдал от нехватки таких возможностей :-)
  • MSP430 тоже не дурак в этом смысле.

Да, многое у коретксов получше, чем у предыдущих ядер, но не настолько, чтобы совсем отменить всё предыдущее.
То, что Вы с рвением неофита повторяете слова «новые», «современные» — говорит только о недознании Вами вопроса и о непонимании того, что развитая система прерываний ортогональна ОС, не отменяет её, а помогает ей. Чем примитивнее система прерываний, тем тяжелее живётся ОС, а не ОС исправляет недостатки системы прерываний.
В отличие от Вашего отношения к современным процессорам никто тут не считает ОС панацеей и пользуется ею совместно с возможностями аппаратуры, а не вместо них. «Сейчас время другое» в том, что можно использовать ОС всё более и более широко.
Считаете возможности современных процессоров панацеей, отменяющей всё и вся — Ваше право. Про это даже песенка есть:
Нам электричество сделать все сумеет,
Нам электричество мрак и тьму развеет.
Нам электричество заменит всякий труд,
Нажал на кнопу чик-чирик и тут как тут.
Lotor
Цитата(dxp @ Apr 13 2012, 21:29) *
Да, тему поднимали неоднократно, в том числе и с zltigo. Ему задавался этот же вопрос. Он на него не привёл технических аргументов, а сказал лишь, что ему лично так больше нравится, это его эстетическое предпочтение.

По сути. Если задачи требуют какого-то реалтайма, то они выстраиваются по приоритетам - когда есть срочность выполнения, всегда встаёт приоритет. Если задачи просто должны быть выполнены в фоне приоритетных, то их можно выполнять просто в пределах одного процесса по очереди. Планировка задач с одинаковым приоритетом по схеме round-robin с вытеснением ничего тут не даёт, кроме накладных расходов на вытеснение (где оно по сути-то и не нужно) и на стеки дополнительных процессов.

Кроме того, следует иметь в виду, что ничего там безплатно не даётся. Любая функциональность потребует расходов. В scmRTOS планировщик сделан намеренно максимально простым и быстрым, и возможно это стало благодаря тому, что механизм организации процессов в виде битовой карты, представляющей собой упакованное слово без "дырок", позволяет манипулировать процессами буквально считанными инструкциями процессора. Позволь тут хотя бы "дырки", и уже код планировщика будет выполняться вдвое дольше. Позволь тут более сложные схемы - с одинаковыми приоритетами и "каруселью", и время время работы планировщика вырастет в разы.

И чего ради? Чем это лучше варинта, когда срочные задачи живут в более приоритетных процессах, а несрочные - в одном-двух низкоприоритетных, где они выполняются по очереди. Получается, и реалтайм соблюдён, и накладных минимум. Я вообще всю несрочную работу отправляю в фон путём делегирования выполнения (через очередь сообщений).

Вариант с равными приоритетами и карусельным вытеснением хорошо ложится на большие ОСи, где множество процессов живёт своей жизнью, очень долго, и реальтайм не важен. В RTOS же ситуация в корне другая, и такой способ планировки, ПМСМ, ничего кроме недостатков не имеет.

Я согласен, что введение одинаковых приоритетов будет накладно. Просто я прекрасно обходился конечными автоматами, пока не наткнулся на то, что код чужой библиотеки надо было "параллелить" со своими задачами. Срочно пришлось смотреть RTOS, которые имели порты под мой мк - среди них была и ваша. Но, т.к. явно места блокировки в чужой библиотеки указать было затруднительно, пришлось выбрать FREERTOS, задать задачам одинаковый приоритет, переключение контекста 1 мс - и тогда я получил желаемый результат.
dxp
QUOTE (Aprox @ Apr 15 2012, 15:20) *
Отдельные стеки, сохранять контекст каждой задачи, уже не неужно. Соответственно, одна из главных фич многозадачных OS с приходом C++ выглядит ненужной.

Это надо выбить в мраморе и покрасить золотыми буквами. И разместить в аллее троллинга.

QUOTE (sasamy @ Apr 15 2012, 18:08) *
" Ни один язык не заменит ОС, тем более убогий С++.

Да уж куда ему до мегаязыка Цэ.

QUOTE (Lotor @ Apr 16 2012, 11:20) *
Я согласен, что введение одинаковых приоритетов будет накладно. Просто я прекрасно обходился конечными автоматами, пока не наткнулся на то, что код чужой библиотеки надо было "параллелить" со своими задачами. Срочно пришлось смотреть RTOS, которые имели порты под мой мк - среди них была и ваша. Но, т.к. явно места блокировки в чужой библиотеки указать было затруднительно, пришлось выбрать FREERTOS, задать задачам одинаковый приоритет, переключение контекста 1 мс - и тогда я получил желаемый результат.

Почему бы просто не вынести код этой библиотеки просто в отдельный процесс, и пусть он себе там живёт? Приоритет установить из требований приложения
Lotor
Цитата(dxp @ Apr 16 2012, 08:52) *
Почему бы просто не вынести код этой библиотеки просто в отдельный процесс, и пусть он себе там живёт? Приоритет установить из требований приложения

У меня шел непрерывный поток данных, который надо было писать библиотечными функциями на карту. Я пробовал сделать так, как вы предлагаете - получалось, что отображение и реакция на кнопки тормозилась. Если бы я мог указать в библиотеки места блокировки - расставить семафоры и т.п., то этот вариант сработал. Для меня это единственный случай, когда нужны были одинаковые приоритеты. Но он определил мой выбор RTOS.
VslavX
Цитата(Lotor @ Apr 16 2012, 07:20) *
Я согласен, что введение одинаковых приоритетов будет накладно.

Не очень-то оно и накладно. Например, TNKernel поддерживает и уровни приоритетов и round-robin в пределах каждого приоритета, а время планирования и переключения контекста такое же (или даже лучше, правда новую версию SCM4.0 я не тестил) как у SCM. И реально этот round-robin используется, недавний конкретный пример - потоки выполнения CGI в HTTP-сервере. С точки зрения системы, как бы не должны обработчики двух одновременных HTTP-запросов между собой по приоритетам отличаться. Или если у процессора два абсолютно одинаковых MAC-а. ИМХО, некрасиво если потоки драйвера одинакового "железа" будут иметь различные приоритеты.
dxp
QUOTE (Lotor @ Apr 16 2012, 12:48) *
У меня шел непрерывный поток данных, который надо было писать библиотечными функциями на карту. Я пробовал сделать так, как вы предлагаете - получалось, что отображение и реакция на кнопки тормозилась. Если бы я мог указать в библиотеки места блокировки - расставить семафоры и т.п., то этот вариант сработал. Для меня это единственный случай, когда нужны были одинаковые приоритеты. Но он определил мой выбор RTOS.

Всё равно не понял. Почему тормозилось? Какой-то более приоритетный код надолго отбирал управление? Или этот код библиотеки тормозил остальное?

Если второе, то не очень понятно, почему ему не понизить приоритет, чтобы кнопки не блокировал?

QUOTE (VslavX @ Apr 16 2012, 13:19) *
Не очень-то оно и накладно.

Это что считать наклАдным. Переключение контекста сама по себе приличная по объёму инструкций операция. И отдельный стек. Я понимаю, что при наличие 32К оперативы выделить лишних полкилобайта особых вопросов не вызывает. Но чем это лучше, чем просто выполнять задания по очереди в одном процессе?

QUOTE (VslavX @ Apr 16 2012, 13:19) *
Например, TNKernel поддерживает и уровни приоритетов и round-robin в пределах каждого приоритета, а время планирования и переключения контекста такое же (или даже лучше, правда новую версию SCM4.0 я не тестил) как у SCM.

Чудес-то не бывает. Если планировщик более сложный, то и время его работы тоже будет больше. В своё время сранивал с uC-OS/II, там карта процессов состоит из распределённой структуры и приоритет вычисляется в два приёма - время передачи управления было в 2-2.5 раза больше. При прочих равных. Именно время передачи управления, а не переключение контекстов. Время переключения контекстов само по себе зависит от размера контекста, от процессора и его тактовой, но не от ОС.

Другое дело, что кому-то пофиг, что время передачи управления в несколько раз меньше. Например, zltigo прямо говорил, что ему не важно, сколько он там времени тратит, на его задачах всё успевает, а наличие возможностей ему нравится, поэтому его выбор FreeRTOS. Точнее, то, что от неё осталось после его доработок. sm.gif

QUOTE (VslavX @ Apr 16 2012, 13:19) *
И реально этот round-robin используется, недавний конкретный пример - потоки выполнения CGI в HTTP-сервере. С точки зрения системы, как бы не должны обработчики двух одновременных HTTP-запросов между собой по приоритетам отличаться. Или если у процессора два абсолютно одинаковых MAC-а. ИМХО, некрасиво если потоки драйвера одинакового "железа" будут иметь различные приоритеты.

Это почему ещё? Это зависит от приложения. Кто сказал, что МАСи должны иметь одинаковые приоритеты? Если по одному из них трафик большой, а по второму малый, то вот и разница.
ReAl
Цитата(dxp @ Apr 16 2012, 09:35) *
Кто сказал, что МАСи должны иметь одинаковые приоритеты? Если по одному из них трафик большой, а по второму малый, то вот и разница.
Та не™, у Вячеслава по обеим (одинаково) большой :-)
Lotor
Цитата(dxp @ Apr 16 2012, 10:35) *
Всё равно не понял. Почему тормозилось? Какой-то более приоритетный код надолго отбирал управление? Или этот код библиотеки тормозил остальное?
Если второе, то не очень понятно, почему ему не понизить приоритет, чтобы кнопки не блокировал?

Проще всего мою ситуацию можно представить как две задачи, каждой из которой нужно постоянно выполняться и нельзя указать места входа в блокировку. Если повысить приоритет одной из них, страдает другая, т.к. отбирается управление на достаточно долгое время. Возможно можно было обойтись разными приоритетами, и дело в моем малом опыте в этих вопросах. Но наиболее просто такое решилось именно одинаковыми приоритетами. sm.gif
dxp
QUOTE (ReAl @ Apr 16 2012, 14:29) *
Та не™, у Вячеслава по обеим (одинаково) большой :-)

Тем более, зачем тут лишние накладняки на передачу управления в непредсказуемый момент?

QUOTE (Lotor @ Apr 16 2012, 14:29) *
Проще всего мою ситуацию можно представить как две задачи, каждой из которой нужно постоянно выполняться и нельзя указать места входа в блокировку. Если повысить приоритет одной из них, страдает другая, т.к. отбирается управление на достаточно долгое время. Возможно можно было обойтись разными приоритетами, и дело в моем малом опыте в этих вопросах. Но наиболее просто такое решилось именно одинаковыми приоритетами. sm.gif

Внешне ситуация понятна. Но внутри-то всегда особенности. Скажем, вот обработка кнопок управления - она выполняется очень периодически. Т.е. там большие паузы между реальной работой. Поэтому, передвинув, задачу в приоритет выше, чем у той, которая пишет на карту, никаких проблем возникнуть не должно - приоритетная задача выполняется коротко, а скважность большая. Кстати, про задачу, которая пишет на карту, - неужели она съедает там всё время? Ведь сам процесс записи на такой носитель как правило требует значительных циклов ожидания, пока там очередная порция запишется - это ведь не в оперативу писать. И вот в эти моменты и отдавать управление. Или там окончания записи поллингом проверяется?
VslavX
Цитата(dxp @ Apr 16 2012, 09:35) *
Это что считать наклАдным. Переключение контекста сама по себе приличная по объёму инструкций операция. И отдельный стек. Я понимаю, что при наличие 32К оперативы выделить лишних полкилобайта особых вопросов не вызывает. Но чем это лучше, чем просто выполнять задания по очереди в одном процессе?

Оперативы ровно столько же - ведь меняется только схема приоритетов, а количество процессов и их стеки остаются теми же самыми. Или Вы про "сознательный" встроенный кооператив с явными yield говорите? Такой кооператив не всегда приемлем - в тех же CGI - там скрипты давно понаписаны, к тому же пишу их не я, зачем людей (да и специализация у них на сайтостроительстве и контенте) еще и кооперативом грузить. Я кооператив не отрицаю и не так уж редко им пользуюсь (для той же экономии числа процессов и стеков), но, увы, оно не всегда "в тему".

Цитата(dxp @ Apr 16 2012, 09:35) *
Чудес-то не бывает. Если планировщик более сложный, то и время его работы тоже будет больше. В своё время сранивал с uC-OS/II, там карта процессов состоит из распределённой структуры и приоритет вычисляется в два приёма - время передачи управления было в 2-2.5 раза больше. При прочих равных. Именно время передачи управления, а не переключение контекстов. Время переключения контекстов само по себе зависит от размера контекста, от процессора и его тактовой, но не от ОС.

От процессора зависит само собой. И от ОС зависит - от планировщика, схемы данных диспетчера, от активированных фич и просто от качества кода. Я сравнивал uC/OS, FreeRTOS, SCM и TNKernel - есть вот такая тема, там проведено практическое исследование вопроса (в разрезе по ОС и процессорам sm.gif). Поэтому я продолжаю настаивать что "не так уж оно и накладно" sm.gif.

Цитата(dxp @ Apr 16 2012, 09:35) *
Это почему ещё? Это зависит от приложения. Кто сказал, что МАСи должны иметь одинаковые приоритеты? Если по одному из них трафик большой, а по второму малый, то вот и разница.

Я просто привел в качестве примера проект из своей практики где MAC-и абсолютно идентичны, таких проектов у меня было несколько - не такая уж это и редкая ситуация. Кстати, схема приоритетов с поддержкой round-robin для меня была одним из плюсов, который повлиял на мой выбор ОС.


Цитата(dxp @ Apr 16 2012, 10:46) *
Тем более, зачем тут лишние накладняки на передачу управления в непредсказуемый момент?

А код в вытесняемой среде надо всегда писать с учетом того что в непредсказуемый момент заберут управление.
Я не хочу сейчас дискутировать о достоинствах и недостатках кооперативной и/или вытесняемой многозадачности. Просто у пользователей TNKernel всегда есть выбор между кооперативом и вытесняйкой, а вот у пользователей SCM - выбора нет, только кооператив (ессно, речь о задачах с одинаковым приоритетом).
Lotor
Цитата(dxp @ Apr 16 2012, 11:46) *
Кстати, про задачу, которая пишет на карту, - неужели она съедает там всё время? Ведь сам процесс записи на такой носитель как правило требует значительных циклов ожидания, пока там очередная порция запишется - это ведь не в оперативу писать. И вот в эти моменты и отдавать управление. Или там окончания записи поллингом проверяется?

Поллингом - использовал чужой драйвер, а допиливать "под себя" было некогда. Хотя по идеи, если время переключения контекста мало, то и в поллинге можно вставить небольшие задержки и выкрутиться. Так или иначе с одинаковыми приоритетами решить подобные задачи проще всего, особенно для не очень искушенных людей в подобных вопросах. sm.gif
AHTOXA
Цитата(VslavX @ Apr 16 2012, 14:40) *
Поэтому я продолжаю настаивать что "не так уж оно и накладно" sm.gif.

ваш вариант TNKernel : 2.83uS для LPC1768, @100МГц,
scmRTOS: 2.55uS STM32F103 @72MHz (приведённое к 100МГц - 1.83uS).
Более чем в полтора раза однако sm.gif

VslavX
Цитата(AHTOXA @ Apr 16 2012, 11:50) *
ваш вариант TNKernel : 2.83uS для LPC1768, @100МГц,
scmRTOS: 2.55uS STM32F103 @72MHz (приведённое к 100МГц - 1.83uS).
Более чем в полтора раза однако sm.gif

Та не™ biggrin.gif
Сравнивать надо на одинаковых процах, одинаковый прикладной код, одинаковым методом (скопом импульс на одной и той же ножке наблюдаем, например), с одинаковыми опциями компилятора, и исполнением из одного и того же места (из флеша, да sm.gif, и с одинаковыми waitstates). В упомянутой теме апдейт давний написан - включаешь у компилятора оптимизацию по скорости - и уже имеем 2.50uS на 1768@100МГц для TNKernel. BTW, я там еще оптимизаций добавил, надо бы потестить - а то что-то давно я ерундой не страдал biggrin.gif

AHTOXA
У меня нет ни IAR-а ни LCP17xx sm.gif
BTW, а не было ли среди ваших оптимизаций TNKernel-а отключения round-robin? biggrin.gif
VslavX
Цитата(AHTOXA @ Apr 16 2012, 12:27) *
У меня нет ни IAR-а ни LCP17xx sm.gif
BTW, а не было ли среди ваших оптимизаций TNKernel-а отключения round-robin? biggrin.gif

Не-а, оно вообще-то условными флагами не отключается (не было надобности в таких флагах). Тестировался полнофункциональный релизный вариант.
Я постараюсь при возможности попробовать scmRTOS 4.0 на той же платформе. Думаю что результаты будут очень близкими. Потому как при грамотной структуре данных реализация round-robin не так уж и страшна.
AHTOXA
Цитата(VslavX @ Apr 16 2012, 15:34) *
Думаю что результаты будут очень близкими. Потому как при грамотной структуре данных реализация round-robin не так уж и страшна.

Предсказываю процентов 40 выигрыша scmRTOS. Потому что это всё равно что-то (реализация round-robin, пусть даже при грамотной структуре данных) против ничего (две инструкции для выбора младшей единицы в слове-карте процессов).
VslavX
Цитата(AHTOXA @ Apr 16 2012, 12:48) *
Предсказываю процентов 40 выигрыша scmRTOS. Потому что это всё равно что-то (реализация round-robin, пусть даже при грамотной структуре данных) против ничего (две инструкции для выбора младшей единицы в слове-карте процессов).

Это все из серии "Пастернака не читал - но осуждаю" biggrin.gif. TNKernel точно так же ищет младший бит в битовой маске приоритетов - для кортекса юзается та же банальная инструкция CLZ (а для ARM7TDMI остроумный алгоритм из 5-6 инструкций)

CODE

//________________________________________________________________
//
// Функция быстрого поиска номера младшего установленного бита
//
// Входные параметры:
// value - исходное 32-битовое слово
// Возвращает:
// номер самого младшего единичного бита + 1;
// (для бита 0 - возвращается 1, для бита 31 - 32)
// если исходное значение было нулевое, то возвращается 0
//
INLINE_FORCED
DWORD
ffs_asm(DWORD value)
{
value = value & (0 - value);
value = 32 - __CLZ(value);
return value;
}

А round-robin там списком реализован, поэтому TCB новой планируемой задачи при переключении максимум дополнительно извлечения указателя потребует (и то я не уверен в этом, TNKernel элемент списка встраивает прямо в объект, поэтому просто возможна банальная коррекция указателя инструкцией ADD/SUB #const вместо извлечения нового указателя).
То есть - SCMRTOS ищет самый приоритетный бит и берет из массива указатель на TCB по индексу этого бита. А TNKernel по индексу бита извлекает из того же массива указатель на список round-robin, и потом из этого указателя делает указатель на TCB. Вот и вся разница, делов-то. Если где и будет некоторый расход ресурсов - так это в таймере, который будет тикать и листать список round-robin - переходить на следующий TCB. Но собственно к переключению контекста оно никак не относится. Так что какие там 40 процентов laughing.gif
dxp
QUOTE (VslavX @ Apr 16 2012, 15:40) *
Оперативы ровно столько же - ведь меняется только схема приоритетов, а количество процессов и их стеки остаются теми же самыми.

Я про вариант, когда низкоприоритетные задачи просто выполняются по очереди - одна отработала, другой управление передаётся в рамках одного и того же процесса. На практике я просто делаю это через очередь заданий, которую обрабатывает низкоприоритетный процесс.


QUOTE (VslavX @ Apr 16 2012, 17:09) *
А round-robin там списком реализован, поэтому TCB новой планируемой задачи при переключении максимум дополнительно извлечения указателя потребует (и то я не уверен в этом, TNKernel элемент списка встраивает прямо в объект, поэтому просто возможна банальная коррекция указателя инструкцией ADD/SUB #const вместо извлечения нового указателя).
То есть - SCMRTOS ищет самый приоритетный бит и берет из массива указатель на TCB по индексу этого бита. А TNKernel по индексу бита извлекает из того же массива указатель на список round-robin, и потом из этого указателя делает указатель на TCB. Вот и вся разница, делов-то. Если где и будет некоторый расход ресурсов - так это в таймере, который будет тикать и листать список round-robin - переходить на следующий TCB. Но собственно к переключению контекста оно никак не относится. Так что какие там 40 процентов laughing.gif

А идентификация задачи как производится? В scmRTOS таким идентификатором является как раз значение приоритета. И каждый сервис при переводе процесса в спячку или пробуждении оперирует с этим значением, которое всегда доступно и однозначно определяет процесс.
AHTOXA
Цитата(VslavX @ Apr 16 2012, 16:09) *
Это все из серии "Пастернака не читал - но осуждаю" biggrin.gif.

Я не читал, но отнюдь не осуждаюsm.gif
Цитата(VslavX @ Apr 16 2012, 16:09) *
Так что какие там 40 процентов laughing.gif

Посмотрим-посмотримsm.gif


VslavX
Цитата(dxp @ Apr 16 2012, 14:03) *
Я про вариант, когда низкоприоритетные задачи просто выполняются по очереди - одна отработала, другой управление передаётся в рамках одного и того же процесса. На практике я просто делаю это через очередь заданий, которую обрабатывает низкоприоритетный процесс.

Угу, именно это я называю "кооператив". Если система одновременно не поддерживает несколько процессов одинакового приоритета, то остается только такой выход. Хороший кооператив - это тоже достаточно непросто, вон мой HTTP-сервер в основном потоке кооперативный, и то потребовалось внутри три очереди создавать, а как дошло дело до скриптов CGI тут чистый кооператив сдох, пришлось выносить скриптовую часть в чистую вытесняйку.

Цитата(dxp @ Apr 16 2012, 14:03) *
А идентификация задачи как производится?

По значению указателя на TCB (task control block, аналог экземпляра TBaseProcess, если не ошибаюсь). И с объектом TCB сразу можно работать - не надо преобразовывать id (приоритет) в указатель. Понятно что это извлечение из массива, но - надо сделать ldr адреса массива (ага, из очен-но быстрой флеши), потом сам ldr из массива (ну тот уже в RAM).

Цитата(dxp @ Apr 16 2012, 14:03) *
И каждый сервис при переводе процесса в спячку или пробуждении оперирует с этим значением, которое всегда доступно и однозначно определяет процесс.

Ну так оперируем сразу с TCB. При глубокой отладке опционально возможно включение проверки, что указатель на TCB действителен, и содержится в списке действительных на данный момент в системе задач (сканирутся список, при отладке это допустимо).

P.S. Ага, я посмотрел листиг - таки round-robin потребовал при переключении одной дополнительной инструкции subs для коррекции указателя списка в указатель на TCB. Одна инструкция - это как, подъемная цена за round-robin среди процессов одного приоритета? И количество процессов не будет ограничено.

Update: я как-то упустил из вида что scmRTOS на 8/16-битных платформах тоже работает (мой порт TNKernel исключительно предусматривался для 32-х разпядных - как минимум предполагает что операции загрузки/сохранения указателей атомарны). На 8-битной платформе идентификация процесса по уровню приоритета вероятно даст выигрыш по размеру и быстродействия кода. Но для 16/32-битных платформ это уже становится явных архитектурным ограничением.
dxp
QUOTE (VslavX @ Apr 16 2012, 18:17) *
По значению указателя на TCB (task control block, аналог экземпляра TBaseProcess, если не ошибаюсь). И с объектом TCB сразу можно работать - не надо преобразовывать id (приоритет) в указатель. Понятно что это извлечение из массива, но - надо сделать ldr адреса массива (ага, из очен-но быстрой флеши), потом сам ldr из массива (ну тот уже в RAM).

Про какое ldr речь? Что-то нету у нас в AVR никакой ldr. sm.gif Шутка. Но идея та же.

QUOTE (VslavX @ Apr 16 2012, 18:17) *
Ну так оперируем сразу с TCB. При глубокой отладке опционально возможно включение проверки, что указатель на TCB действителен, и содержится в списке действительных на данный момент в системе задач (сканирутся список, при отладке это допустимо).

Это хорошо на 32-битном проце, одна инструкция. На мелочи манипуляции с указателями вместо битов уже не так красиво выглядят. Кроме того, Битовая маска, являющаяся идентификатором процесса, одновременно является и средством для манипуляции картами процессов в каждом сервисе. С указателем на процесс так не получится. Там потребуются отдельные телодвижения, чтобы обслуживать все эти вещи. Поскольку битовая маска не может быть уникальной для процесса/задачи, то для фиксации ожидающего процесса, например, нужно будет завести для этого отдельную переменную в TCB. А как, скажем, достичь такой функциональности: Event Flag, когда его сигналят, переводит все процессы, которые встали на ожидание флага, в готовые к выполнению - своего рода широковещательный "подъём" спящих, но не broadcast, а multicast - т.е. не просто всех поднять, а выборочно, только тех, кто "записался" на ожидание? В случае битовых карт процессов с уникальными приоритетами это делается одной командой по маске.
VslavX
Цитата(dxp @ Apr 16 2012, 14:47) *
Это хорошо на 32-битном проце, одна инструкция. На мелочи манипуляции с указателями вместо битов уже не так красиво выглядят.

Да, это я уже сообразил - одновременно с Вами апдейт своего поста написал.

Цитата(dxp @ Apr 16 2012, 14:47) *
в TCB. А как, скажем, достичь такой функциональности: Event Flag, когда его сигналят, переводит все процессы, которые встали на ожидание флага, в готовые к выполнению - своего рода широковещательный "подъём" спящих, но не broadcast, а multicast - т.е. не просто всех поднять, а выборочно, только тех, кто "записался" на ожидание? В случае битовых карт процессов с уникальными приоритетами это делается одной командой по маске.

Наверное да - тут проще OR сделать на маску активных процессов. Но тут есть нюанс - у меня редко (я даже не могу вспомнить такой случай) бывает что какой-то объект с автосбросом ждет несколько процессов. Такое может быть с мьютексом - но там нужно выбрать и пробудить один самый приоритетный процесс (unicast, Вашими словами). Критическая секция на семафоре - то же самое - пробудить один процесс, первый в очереди.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.