Перейти к содержанию
    

Правда, было пару случаев, когда я высказывал авторам свои хотелки, но при этом серьёзно и обстоятельно их обосновывал.

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

 

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

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

 

И технически можно было бы сделать так, чтобы при возникновении аппаратного прерывания передача управления сразу была в нужный код (забивать адрес, на который переходить), только учитывая, что всё равно имеет место вытеснение и приоритетность, без переключения контекста и выяснения приоритетности не обойтись. Поэтому эта хотелка вырождается именно в то, что имеем сейчас, практически в чистом виде, ничего лишнего у нас там нет: в ISR делается 1) активизация ожидающего процесса; 2) вызов планировщика, где обрабатываются приоритеты с последующим переключением контекстов (если необходимо).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, а системе-то надо как-то "объяснить", по какому конкретно прерыванию в какой код переходить. Т.е. всё равно тут должно быть для того средство.
Так я об этом и говорю. Даже если налепить «синтаксический сахар» OS::wait_TRUE_hardware_interrupt(TIMER1_IRQ); (толи допиливанием языка, как во всяких DynamicC, толи внешним препроцессором), всё равно в микроконтроллере — частично аппаратно, частично программно — будет произведена та же самая последовательность действий.

  • Возникновение аппаратного прерывания — тут с приоритетами и т.п. все в железе.
  • Переход (возможно, через некоторое время) на обработчик — это тоже в железе.
  • В обработчике программно (ну где-то же надо, а аппаратно не реализовано) решить

    • ждёт ли данный процесс этого события или он и так выполняется, но занят чем-то другим — нужно пометить, что потом ему не нужно ждать,
    • имеет ли право данный процесс выполняться сразу — переключиться на него сразу,
    • если права не имеет — пометить, что на него нужно перейти как только он право получит.
  • Если процесс ждал и звёзды благосклонны к данному процессу — переключить на него. Может быть частично поддержано/ускорено аппаратно.

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

Ну никакой надежды на то, чтобы «C++ наконец-то заработал на современных чипах» :biggrin:

 

Причём, как уже было сказано не раз, нужно просто один из методов «драйверного» класса вызывать непосредственно в прерывании и реакция будет максимально быстрая. Если отталкиваться от точки зрения, что вызов метода есть посылкой сообщения объекту, то вызов метода из 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] побежал я на работу...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Про персонализацию мютексов. Кто из процессов залочил - тот и разлочить может.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Позиция авторов, что задачи с одинаковым приоритетом избыточны, не потерпит изменения в будущем?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я думаю — никак. Иначе уже хотя бы какой-то конструктив проскочил. В виде «высокоуровневого» (на человеческом языке) описания происходящих процессов.

Не, это будет то, что тут сказано — задача, спрятанная в обработчик целиком. А не ожидающая "настоящие прерывания".

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

 

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

[ пример skipped]

Ваш вариант использования того, что есть в scmRTOS - плох тем, что хочешь не хочешь, а придется идти длинным путем через OS, через диспетчер, через полинг, через арбитр приоритетов.... когда сработает, да и сработает ли вообще посланный signal - никто толком не знает. В моем варианте- все четко и практически мгновенно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если чип позволяет вложенные прерывания по приоритету, как например в последних Cortex, то автоматически решается проблема приоритетов задач. А использование задачи в виде класса с защищенными данными и методами автоматически решает проблему сохранения контекстов на переключениях, нет нужды в стеках для каждой отдельной задачи.
:blink:

Отличное описание обычной (без OS) программы.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, Cortex-M3 таки молодчинка. Если глянуть табличку времён переключения процесса (по 1-EventFlag, от поднятия лапки в прерывании до опускания в приоритетном процессе), состоящее из перепланирования и переключения контекста, взять оттуда и перемножить микросекунды на мегагерцы, то получим

BlackFin: 360 (ну тут, наверное, контекст большой)

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

 

 

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

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

 

Про персонализацию мютексов. Кто из процессов залочил - тот и разлочить может.

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

 

 

Позиция авторов, что задачи с одинаковым приоритетом избыточны, не потерпит изменения в будущем?

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

 

Ваш вариант использования того, что есть в scmRTOS - плох тем, что хочешь не хочешь, а придется идти длинным путем через OS, через диспетчер, через полинг, через арбитр приоритетов....

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

 

когда сработает, да и сработает ли вообще посланный signal - никто толком не знает. В моем варианте- все четко и практически мгновенно.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хотел бы еще добавить свои пять копеек. IMHO полезность rtos лижит именно в области обеспечения целостности и непротиворечивости алгоритма работы программы (конечно при условии грамотного проектирования). Скорость, потребление ресурсов и другие параметры это уже проблемы второго плана.

Если же вы хотите экстремально быстро и/или минимально объемно, то отбрасывайте все обертки в виде rtos/библиотек/др. и пишите все ручками.

А все разговоры о включении в rtos каких-либо мифических классов DMA-обработчиков полностью несостоятельны - даже мегасупер OS не сделает за вас всей вашей работы - придется и мозгами пошевелить.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поискал по форумы, zltigo тоже утверждал, что ему такая штука необходима для обслуживание некого количества однотипных каналов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

... такая штука необходима для обслуживание некого количества однотипных каналов

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

2. Если порядок не важен, то, как частный случай, можно согласиться с решением п. 1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В моем варианте- все четко и практически мгновенно.

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

 

Если не хотите ничего в виде кода писать, то может пора завязать? :maniac:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поискал по форумы, zltigo тоже утверждал, что ему такая штука необходима для обслуживание некого количества однотипных каналов

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

 

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

 

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

 

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

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, не целиком. Я вижу задачу периферии в виде статического класса C++, у которого только метод exec() оформлен как ISR от периферии. Конструктор же класса- отдельно. Также отдельно от ISR методы коммуникации с другими процессами. Если чип позволяет вложенные прерывания по приоритету, как например в последних Cortex, то автоматически решается проблема приоритетов задач.
Какой такой павлин-шмавлин exec() ? В этом методе, «оформленном как ISR» нельзя будет оспользовать sleep() или wait(), иначе это поломает всю работу планировщика. Т.е. нельзя будет пользоваться сервисами ОС, предназнаяґченными для процессов.

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

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

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

 

Ваш вариант использования того, что есть в 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 Короче говоря, получилось «вашими отвёртками неудобно дырки ковырять, вот если бы ваши отвертки были круглые с коническим заострённым кончиком! Если бы они наконец-то использовали возможности современного металла!»

Кто ж знал, что вместо доказывания того, что отвёртки такими не бывают в принципе, что «+»-овые, что «—»-овые, нужно было просто об́яснить, что это называется шило и именно его и нужно брать для ковыряния дырок...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отличное описание обычной (без OS) программы.

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

 

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

//******************************************************************************
//*     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() уже сообщает наверх о том, что пакет передан полностью, вызывает сервисы ОС и после него происходит перепланирование.

 

Точнее сказать, без привычной из прошлого OS.

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

 

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

 

А то, что Вы описали — это таки не вытесняющая ОС вообще. Это расталкивание всей работы по обработчикам прерываний с оставшейся программой без каких-либо признаков ОС либо с зачатками кооперативной ОС, пользующейся результатом работы выполненной в прерываниях обработки. Вполне себе решение, пользовался раньше и пользуюсь сейчас. Без ОС или с кооперативной ОС часто иначе невозможно.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...