Embedded OS

Sat, 19 Mar 2005 00:24:28 +0300 Alexey V Bugrov wrote to Harry Zhurov:

AV>>> Hикак. Ядро (таскманагер) писать с нуля. Все остальное может быть AV>>> и на С написано, легко перенесется. HZ>> Похоже, у нас несколько разное восприятие понятия "ядро". Вот ISR, HZ>> где возможно перепланирование - это ядро?

AV> В твоих терминах не знаю. В моих терминах перепланирование в AV> пользовательском ISR невозможно, из него только посылаются AV> сигналы ядру, которое перхватывает вызов пользовательской ISR и по AV> окончании его работы производит перепланирование при AV> необходимости. Интересно, сколько раз я уже написал этот тезис за время AV> нашей дискуссии?

AV> Т.е. у меня ISR - это не ядро, оно может быть писано на чем угодно,

В моем понимании ISR - есть кусок кода, асинхронно и _аппаратно_ вызываемый из основной программы.

AV> только вот его вызов перехватывается ядром, которое AV> делает всю черную работу.

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

AV> У меня _внутри_ пользовательского ISR никакое перпланирование невозможно.

Поэтому у тебя реально обработчик прерывания является частью ядра - т.е. он обладает всеми полномочиями ядра, а из него вызывается пользовательский код, который ты называешь "пользовательским ISR".

AV>>> Даже для uC/OS Лябрус вполне прозрачно написал, что если AV>>> интересует результат, а не процесс, то самая главная часть ОС, в AV>>> том числе планировщик, должна быть написана на асме. Обвеска на C AV>>> - сколько угодно. HZ>> Hо сам-то он все на С делает.

AV> Note that OSSched() could be written entirely in assembly language to AV> reduce scheduling time. OSSched() was written in AV> C for readability, portability and also to minimize assembly language.

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

AV> Вот если последнее не требуется (ты же не занимаешься написанием ос на AV> продажу и каждый день с платформы на платформу AV> не прыгаешь) то писание на асме полностью оправдано.

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

[...]

AV>>> Да. Обработчик прерывания - это функция. Какая разница кто ее AV>>> вызовет: внешнее событие или другой код? Единственная проблема - AV>>> это reti вместо ret на выходе. Hо это можно обойти.

HZ>> А вектора прерываний ты сам руками вставляешь?

AV> ;=============================================================== AV> OS_ISRV_SECT CODE 0x0018 ; адрес вектора прерывания. Сюда ядро AV> прибито гвоздями. AV> ;--------------------------------------------------------------- AV> ; save minimal context AV> ; AV> [skip, ибо не существенно] AV> ; AV> btfsc OS_CtxSwPending ; check OS request, переключение контекста AV> запрошено вне прывания. AV> bra _skip_user_isr AV> ;--------------------------------------------------------------- AV> ; proceed user interrupts AV> ; AV> incf OS_bIntLevel,F,ACCESS ; increment interrupt nest level AV> incf OS_bLockCount,F,ACCESS ; we are inside interrupt, so increment

AV> locker AV> ; AV> call OS_ISR ; call user ISR (это тот самый AV> обработчик, который сгенерил компилятор) AV> ; AV> decf OS_bLockCount,F,ACCESS AV> decfsz OS_bIntLevel,F,ACCESS ; decrement interrupt nest level AV> bra _os_exit ; if not zero skip task scheduler AV> ; AV> _skip_user_isr: AV> ;--------------------------------------------------------------- AV> ; тута смотрим надо ли запускать планировщик и т.д.

Т.е. этот ассемблерный кусок кода ты руками вставляешь каждый раз для каждого ISR? Или у тебя там где-то еще есть анализ, какой именно "пользовательский ISR" вызвать? А этот код, пользуясь тем, что вектор один, общий? Если так, то как быть, когда для каждого обработчика свой вектор? Дублировать руками кучу ассемблерного кода?

HZ>> Поясню, что имеется HZ>> в виду: в IAR'е, например, есть волшебное слово __interrupt, которое HZ>> придает функции особый статус - в частности, компилятор сохраняет все HZ>> используемые регистры, а не только local.

AV> Hу и что? Это даже замечательно. От этого сгенерированный код перестал быть AV> функцией, которая может быть вызвана AV> коммандой call?

Перестал - как ты знаешь, call обычно порождает на выходе ret. А функция, оформленная как __interrupt на выходе будет иметь reti.

HZ>> И еще там же предназначена к HZ>> использованию волшебная прагма: #pragma vector=..., где указываешь HZ>> адрес ISR.

AV> Хинт: в этой прагме указываешь не адрес вектора, а некий произвольный адрес AV> вне таблицы векторов.

Хе, дык компилятор-то этот левый адрес и вставит в таблицу векторов и будет вызывать что попало.

AV> Или вообще не указываешь эту прагму, пусть функция будет там где она есть, AV> а вектор останется не тронутым.

Это можно. Только компилятор начнет вопить, что, типа, вектор не указали. Можно, конечно, вопли подавить, но это как-то не очень кузяво.

AV> В таблице векторов располагаешь врапер на асме, который делает описанную AV> мной работу и вызывает этот самый обработчик (OS_ISR), AV> расположенный по AV> адресу, указанному в прагме.

Понятно. Я так и делал, когда не удавалось подружить __interrupt и __C_task в каких-то версиях EWAVR: сам обработчик делал обычной функцией, на входе и на выходе руками все обрамление, в таблицу векторов - адрес. Работало. Но геморройно это.

HZ>> Таким образом, компилятор делает всю остальную работу - HZ>> помещение адреса ISR в таблицу векторов прерываний, реализует HZ>> поведение внутри ISR как это полагается делать (все же HZ>> обработчик прерываний - непростая функция).

AV> Единственное отличие - это reti в конце вместо ret.

Это немало.

AV> Все остальное несущественно.

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

AV> [skip]

HZ>> Если будет требоваться скорость (либо какие-то другие причины HZ>> вынудят), то так и делаем. Что выбрать - второй вопрос. Hо пока по HZ>> скорости устраивает, можно и не дергаться, а решить все в лоб.

AV> Это вопрос для отдельной дискуссии, но все-таки я надеюсь, что обсуждаем AV> разные способы реализации планировщика и AV> пытаемся взвесить их плюсы и минусы. Для моего варианта я вижу пока минус AV> только один: меньшая (не очень значительно) AV> переносимость кода и чуть-чуть большие накладные расходы на вход/выход из AV> обработчика.

А таскание вручную низкоуровневого, не имеющего отношения к прикладной задаче, кода? И обслуживание его - вызовы-то самих "пользовательских ISR" надо тоже руками вписывать. Словом, удобство и автоматизация еще те! Я бы не отнес это к достоинствам.

AV> Зато мы получаем прозрачность написания пользовательских прерываний (не AV> делим их на осевые и неосевые),

Ой, а что уж там непрозрачного? В одном случае я пишу

__interrupt void ISR() { ... }

В другом:

OS_INTERRUPT void ISR() { TISR_Wrapper ISR_Wrp; ... }

Что уж тут сложного?

AV> не стесняясь использовать функции ОС по прямому назначению (т.е фукции AV> сигнализации в прерываниях)

То же самое - в осевых прерываниях смело сигналим флаги, мечем сообщения и т.д. На выходе - перепланирование.

AV> и увеличение скорости обработки прерываний, т.к.

Увеличение скорости имеет место _только_ в случае, если было осевое прерывание, где семафор не взведен (как в случае приема байтов в пакете). Когда семафор взводится, никакого выигрыша нет, все ровно так же.

А по сравнению с обычным (внеосевым) прерыванием тут только проигрыш по скорости. И не надо говорить, что такие прерывания не нужны. Нужны. Например, был у меня в проекте использован термодатчик TMP03 (АД), который цифровой и выдает результат в виде ШИМ (температура вычисляется из соотношения времен полупериодов). Я завел его на Input Capture, где только с буфер складировались значения полупериодов. А когда надо было получить температуру, прикладной процесс просто брал значения и вычислял. Зачем тут городить какие-то контексты и прочее. Пришел фронт - быстренько прыгнули, сложили значение в кольцевой буферок и все. Максимально быстро и просто. Это я к тому, что не всякое прерывание может служить источником событий для ОС.

AV>>> Hа асме?

HZ>> Естественно. Пишется макрос, который состоит из ассемблерных HZ>> вставок. Один на входе (сохранение), другой на выходе HZ>> (восстановление).

AV> Если это допустимо, то и вставить перед выходом из функции прерывания, AV> сгенерированной компилятором, _asm(ret) труда не AV> составит (это чтобы подменить reti компилятора).

Не подменить, а вставить перед. Чтобы уверенно сказать, надо пробовать.

AV> Значит мой вариант реализуем на 100%. Hикаких макросов для AV> сохранения/восстановления контекста в ISR не потребуется.

В общем, не вижу я, чтобы все это было лучше тех двух ISR с подменой вектора. И если уж отказываться от универсальности, то лично мне значительно более симпатичен вариант с софтовым прерыванием или его эмуляцией с помощью аппаратного. В этом случае все гораздо проще и прозрачнее: любой ISR, кроме того самого софтового, не является частью ядра и пишется как обычно (ну, с ма-аленьким добавлением), а управление именно _отбирается_ (с помощью софтового прерывания) при необходимости ядром после выхода из любого ISR - если внутри ISR взводится семафор, то там же тупо выставляется запрос на софтовое прерывание - тогда после выхода сразу же управление будет передано в это софтовое прерывание, где так же тупо выбирается наиболее приоритетный процесс и тупо переключаются контексты. Все. Сама идея мне нравится и я серьезно подумаю над реализацией (главным образом, над тем, как формализовать процесс "затачивания" свободного аппаратного прерывания под софтовое).

Reply to
Harry Zhurov
Loading thread data ...

Hello, Alexey Boyko !

Потому что не должен прерываться ток. Кстати его DC составляющая не должна быть больше долей процента от номинального.

С уважением, Дима Орлов.

Reply to
Dima Orlov

Здравствуйте, Уважаемый Maxim!

Fri Mar 18 2005 21:01, Maxim Polyanskiy wrote to Alexander Golov:

MP> .... на асм это не нужно. Cовсем не нужно. MP> Так-же как и передача расположения строки в ее адресе. Проще выделить и MP> выставить бит, который будет управлять логикой работы процедуры (если это MP> надо) или вообще ничего не делать (т.к. у нормального программиста, одно MP> и то-же не лежит и там и там, и функции типа strcat просто не MP> применяются).

Увы, очень даже применяют. Пример- сборка строки перед выводом на LCD. Сборка производится из "рассчитанной" строки в SRAM и темплейта(формата), что хранится во Flash. Известно, что люди прямо в названии функции указывают типы памяти, с которыми будет иметь дело данная функция. Это много экономнее, чем битиками кодировать типы для одной универсальной и ужасно громоздкой функции.

Всего Вам Хорошего Ольга

Reply to
Olga Nonova

Здравствуйте, Уважаемый Kirill!

Sun Mar 20 2005 11:23, Kirill Frolov wrote to George Shepelev:

KF> Эффективен смешанный вариант. И не спорь. Чисто паскалевский требует KF> хранить длину в отдельном регистре и всё время её перевычислять, что KF> жутко неудобно. Чисто сишный имеет трудности с определением длины когда KF> это действительно нужно.

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

Всего Вам Хорошего Ольга

Reply to
Olga Nonova
Reply to
Andy Mozzhevilov

Olga, ты ещё здесь сидишь?

Воскресенье Март 20 2005 11:53, Olga Nonova wrote to George Shepelev:

ON>>> Результат будет обрезан до размера 255. GS>> Hо это, по-твоему, проблемой не будет являться? Hикаких хлопот, GS>> просто часть нужной инфы куда-то тихонько пропала ;))) ON> Hе фатально.

Кто сказал? В реальной жизни это может оказаться _очень_ фатально!

GS>> Понимаешь, в чём дело, Olga, меня больше заботит получение GS>> _корректного_ результата, а не то, чтобы не сбился абстрактный GS>> "ход программы". Посему в критичных местах делаются проверки на GS>> переполнение и принимаются меры на случай "нештатных ситуаций". GS>> Это при наличии минимального желания можно делать с любыми GS>> строками, как сишными, так и паскалевскими. ON> Полностью согласна, что проверки необходимы.

О, неужели консенсус? ;)))

ON> Однако, чтобы эти проверки сработали, нужно как минимум, чтобы ON> выполнение программы сумело до них добежать.

И в чём проблема? У меня - всегда добегает, независимо от формы представления входных данных.

ON> Hа Паскале -гарантировано достигнешь проверок, а с сишными z-строками ON> можно зависнуть по дороге или вообще обвалить всю программу.

"Руки!" (c)

GS>> Если программист не умеет программы писать, результат в любом GS>> случае будет никудышний. По мне, пусть лучше такая программа GS>> сразу "рушится", чем создаёт впечатление "работы"... ON> Я говорю не про "неумение писать программы",

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

Георгий

Reply to
George Shepelev

Kirill, ты ещё здесь сидишь?

Воскресенье Март 20 2005 11:03, Kirill Frolov wrote to Anton Abrosimov:

AA>> Я тоже знаю ответ. Пишется легко, пpичем абсолютно так-же, как в AA>> C, используя аналог функций из stdarg.h. KF> Гражданин, вы с паскалем хоть сколько-нибудь знакомы? Hет там хотя KF> бы возможности передать в функцию переменное число аргументов. Hе надо KF> путать с delphi. Вот у меня Pascal/MT+ (C) 1983 by Digital Research, KF> Inc есть -- как в нём это реализовать? Или, чтоб не возиться с KF> эмуляторами CP/M можно взять хотя бы p2c транслятор с паскаля на c -- KF> а тот тут GS мучается, не знает как для AVR можно на паскале писать.

Гражданин, я не мучаюсь. Меня вполне устраивает паскаль в той нише, для которой он создан. А для AVR я могу и на ассемблере программку сделать (собственно, как раз сейчас делаю), хоть это и не самое приятное занятие.

Hу а трахаться с переконвертацией и последующей отладкой в режиме паскаль-си предоставляю мазохистам...

Георгий

P.S. Скунсам же советую читать H.Вирта. Там ответы на многие вопросы.

Reply to
George Shepelev

Kirill, ты ещё здесь сидишь?

Воскресенье Март 20 2005 11:20, Kirill Frolov wrote to Olga Nonova:

ON>> И если компилятор не дает сообщений про ошибки, то пусть будет ON>> хуже пользователю такого компилятора. KF> Компилятор, который вместо работающих программ выдаёт сообщения о KF> дурацких ошибках, называется паскаль...

Компилятор, который вместо сообщений о дурацких ошибках выдаёт неработающие программы, называется си ;)

Георгий

Reply to
George Shepelev

Kirill, ты ещё здесь сидишь?

Воскресенье Март 20 2005 11:23, Kirill Frolov wrote to George Shepelev:

MB>>> Компенсиpовано. GS>> Hе совсем. Для разных задач могут оказаться удобными разные GS>> представления! KF> Эффективен смешанный вариант.

Зачем? В огромной массе случаев удобен один из простейших вариантов.

KF> И не спорь. Чисто паскалевский требует хранить длину в отдельном KF> регистре

В "нулевом" элементе символьного массива, хранящего строку. Занимает ровно столько же места, сколько сишный "нуль-терминатор".

KF> и всё время её перевычислять,

А каждый раз парсить строку в поисках "нуль-терминатора" тебя не напрягает?

KF> что жутко неудобно.

Перевычислить одно значение всё таки гораздо проще, чем постоянно искать, где кончается хвост ;)

KF> Чисто сишный имеет трудности с определением длины когда это KF> действительно нужно.

Чисто сишный имеет преимущество в возможности создания строк произвольной длины, а также ряд недостатков (невозможность использования в строке символа "нуль", повышенные накладные расходы на определение длины. Так что для "сишного" варианта, действительно, может оказаться эффективным "смешанный вариант". С длиной, хранящейся отдельно от самой строки, ибо в "сишной строке" для этого параметра места нету...

Георгий

Reply to
George Shepelev
Reply to
Alex Mogilnikov
Reply to
Vladimir Vassilevsky
Reply to
Andy Mozzhevilov
Reply to
Anton Abrosimov
Reply to
Anton Abrosimov
Reply to
Anton Abrosimov

Hello, Olga Nonova !

Hа хрена ее производить перед выводом? Выводи последовательно куски строк, индикатор их сам склеит.

То есть printf...

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

С уважением, Дима Орлов.

Reply to
Dima Orlov

Hello, Olga Nonova !

Они и для С срабатывают с той же скоростью. Я правда никак не возьму в толк что за задачи ваш коллектив авторов решает на восьмиразрядных гарвардовских контроллерах, что вам так критичны функции обработки строк? Лично я даже не помню какие там есть эти функции, не приходится ничем таким пользоваться.

Ага, выводится в качестве help'а чем-то вроде

while(c=*str++) putchar(c);

както-то совершенно без стандартных функций.

вообще не зависают.

С уважением, Дима Орлов.

Reply to
Dima Orlov

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.