Thu, 17 Mar 2005 21:00:20 +0300 Alexey V Bugrov wrote to Harry Zhurov:
[...]
HZ>> Как быть в случае использования ОС для другой платформы?
AV> Hикак. Ядро (таскманагер) писать с нуля. Все остальное может быть и на С AV> написано, легко перенесется.
Похоже, у нас несколько разное восприятие понятия "ядро". Вот ISR, где возможно перепланирование - это ядро?
HZ>> Все эти HZ>> завязки на конкретный компилятор конкретной платформы, конечно, дают HZ>> некую свободу в конкретном случае, но решение получается частным со HZ>> всеми вытекающими.
AV> Даже для uC/OS Лябрус вполне прозрачно написал, что если интересует AV> результат, а не процесс, то самая главная часть ОС, AV> в том числе планировщик, должна быть написана на асме. Обвеска на C - AV> сколько угодно.
Но сам-то он все на С делает. На асме только низкоуровневый код вроде переключения контекстов. И тут я с ним целиком и полностью согласен, и делаю именно так. Но функции переключения контекстов - очень небольшая часть от всего остального. А все остальное прекрасно пишется на С и оверхеда почти не создает.
[...]
AV>>> 4. Вызов "внеосевого прерывания" с его собственным AV>>> сохранением восстановлением "контекста", тех самых двух регистров.
HZ>> Как это "вызов"? Оно уже вызвано. Аппаратно. Мы в нем уже HZ>> находимся.
AV> Да. Обработчик прерывания - это функция. Какая разница кто ее вызовет: AV> внешнее событие или другой код? Единственная AV> проблема - это reti вместо ret на выходе. Hо это можно обойти.
А вектора прерываний ты сам руками вставляешь? Поясню, что имеется в виду: в IAR'е, например, есть волшебное слово __interrupt, которое придает функции особый статус - в частности, компилятор сохраняет все используемые регистры, а не только local. И еще там же предназначена к использованию волшебная прагма: #pragma vector=..., где указываешь адрес ISR. Таким образом, компилятор делает всю остальную работу - помещение адреса ISR в таблицу векторов прерываний, реализует поведение внутри ISR как это полагается делать (все же обработчик прерываний - непростая функция).
Если отказываться от этого сервиса, то придется кое-что делать руками, что не есть удобно и вдобавок граблечревато.
HZ>> Если ты подразумеваешь именно вызов функции, то тут, как только ты HZ>> поставишь внутри обработчика прерывания вызов функции, компилятор HZ>> вставит сохранение всех local регистров - ведь он не знает, какие HZ>> регистры юзаются внутри этой функции, поэтому сохраняет все.
AV> Ой. Эти десять строчек надо на асме писать.
Понятно. Т.е. в сухом остатке: надо, чтобы ISR был обычной функцией, где часть кода написана на асме. Больше вопросов не имею.
[...]
AV>>> Hу что, запредельные накладные расходы? HZ>> Hет. Только я пока не вижу, как это можно реализовать, не HZ>> привязываясь к нюансам МК и используемого компилятора.
AV> Интересует процесс или результат? :) AV> Hикто же тебе не предлагает всю ось каждый раз писать с нуля. Только AV> небольшую часть на асме для каждой платформы и/или AV> компилятора. Или это противоречит идее? :)
Никакой особой идеи тут нет. Есть реальные требования. Мне приходится работать не с одним семейством МК, тут надо учитывать это обстоятельство. В итоге мой путь - как в uCOS: все на ЯВУ за исключением малой части низкоуровневого кода, который пишется на асме для каждой платформы и который по-другому просто не реализовать. ISR - на ЯВУ со всеми возможными для пользователя удобствами при максимальной безопасности. Т.е. достаточно написать:
#pragma vector=... OS_INTERRUPT void Slon_ISR() { TISR_Wrapper ISR_Wrapper;
... // прикладной код }
И все. Остальное делает компилятор, включая сохранение/восстановление контекста, переключение на стек прерываний, перепланирование.
Единственный минус тут (с чего, собсно, и началось обсуждение) - это неэффективное использование ресурсов в случае, когда прерывание не является источником событий для ОС. Для этих случаев можно применить и альтернативные варианты реализации. Хоть складывание в буфер байтов с периодическим относительно редким опросом, хоть путем эмуляции софтового прерывания, задействовав для этого любое свободное аппаратное, хоть путем подмены векторов прерываний, как в случае двух ISR.
Решение, конечно, частное. Но и ситуация тоже вполне частная. И альтернативный метод, предлагаемый тобой, тоже, кстати, является частным решением. Вполне естественно, что частное специализированное решение оказывается эффективнее универсального. Но за него и цена заплачена в виде дополнительных усилий по реализации и поддержке.
Если будет требоваться скорость (либо какие-то другие причины вынудят), то так и делаем. Что выбрать - второй вопрос. Но пока по скорости устраивает, можно и не дергаться, а решить все в лоб.
[...]
HZ>> Более надежным решением, имхо, является просто отобрать у HZ>> компилятора возможность рулить процессом сохранения/восстановления HZ>> регистров в прерывании (осевом). Т.е. чтобы он вообще к этому не HZ>> касался. Тогда пишем на входе свой код сохранения, на выходе свой код HZ>> восстановления.
AV> Hа асме?
Естественно. Пишется макрос, который состоит из ассемблерных вставок. Один на входе (сохранение), другой на выходе (восстановление).
HZ>> сидят, одно ПЛИС, другое МК. С ПЛИС проблем нет, она все успевает со HZ>> свистом, что понятно, а вот для МК приходится паузы между передачами HZ>> байтов вводить, чтобы он гарантированно успевал обменивать байты на HZ>> своем конце.
AV> Я никак не против, но если этого не делают, значит без этого можно AV> обойтись. Или взять то, где это есть. :)
Подозреваю, что просто на момент появления мода еще не пришла. Но тенденция, имхо уже есть. Думаю, через несколько лет в старших членах семейств мелких МК будет появляться коммуникационная периферия с буферами.