Hi Harry, hope you are having a nice day!
21 Мар 05, Harry Zhurov wrote to Alexey V Bugrov:
AV>> Т.е. у меня ISR - это не ядро, оно может быть писано на чем AV>> угодно, HZ> В моем понимании ISR - есть кусок кода, асинхронно и _аппаратно_ HZ> вызываемый из основной программы.
Это если подходить к вопросу строго формально. Если немного отсупить от формальностей, то ISR это функция, вызываемая асинхронно по отношению к основной задаче аппартным или программным (т.е. из другой функции, вызванной аппаратно по внешнему событию) способом.
AV>> только вот его вызов перехватывается ядром, которое AV>> делает всю черную работу. HZ> куска (задачи/процесса) основной программы и отдает его другому куску HZ> (задаче/процессу), либо основная программа сама отдает управление ядру HZ> путем вызова ядреной функции (что имеет место внутри HZ> функций сервисов). В этом случае обработчик прерывания - есть часть HZ> ядра.
Да. Только часть обработчика (назовем ее системной) является частью ядра. Еще есть пользовательская часть вызываемая из системной.
AV>> У меня _внутри_ пользовательского ISR никакое перпланирование AV>> невозможно. HZ> Поэтому у тебя реально обработчик прерывания является частью ядра HZ> - т.е. он обладает всеми полномочиями ядра, а из него вызывается HZ> пользовательский код, который ты называешь "пользовательским ISR".
Да. Только из-за того, что реальную работу для пользователя делает именно он.
AV>> Note that OSSched() could be written entirely in assembly language AV>> to reduce scheduling time. OSSched() was written in C for AV>> readability, portability and also to minimize assembly language. HZ> :) То, что может быть написано, никто не сомневается. Только сам HZ> он так не сделал по понятным причинам (что-то у меня большие сомнения, HZ> что его планировшик, переписанный на асме, даст хоть какое-то заметное HZ> преимущество. И я, также, не слышал, чтобы кто-то так делал.
Hу дык. Лень - святое дело. :)
HZ>>> А вектора прерываний ты сам руками вставляешь?
AV>> ;=============================================================== AV>> OS_ISRV_SECT CODE 0x0018 ; адрес вектора прерывания. Сюда AV>> ядро прибито AV>> гвоздями. ;-------------------------------------------------------
[skip]
AV>> level bra _os_exit ; if not zero skip task AV>> scheduler ; _skip_user_isr: ;------------------------------------- AV>> -------------------------- ; тута смотрим надо ли запускать AV>> планировщик и т.д.
HZ> Т.е. этот ассемблерный кусок кода ты руками вставляешь каждый раз HZ> для каждого ISR?
:) У пика один вектор прерывания (точнее два, но высокоприоритеное в рассчет не берем, он специально оставлен мной для hard real time задач, т.к. сохраняет аппаратно часть контекста за один такт и прерывает работу ОС даже в критических секциях).
HZ> Или у тебя там где-то еще есть анализ, какой HZ> именно "пользовательский ISR" вызвать?
Да. Внутри пользовательского ISR. Хотя на практике это выглядит примерно так:
void OS_ISR(void) // OS managed interrupt service routine { if (PIR1bits.CCP1IF) // interrupt from display timer { PIR1bits.CCP1IF = 0; // clear interrupt flag ledskeysProc(); // process leds and keys } if (PIR2bits.CCP2IF) // interrupt from system timer { PIR2bits.CCP2IF = 0; // clear interrupt flag ClrWdt(); // clear watchdog timer OS_ClockTick(); // process OS clock outputProc(); // process relay and pwm outputs auxProc(); // process auxiliary inputs and outputs } if (INTCON3bits.INT2IF) // interrupt from ADC { INTCON3bits.INT2IF = 0; // clear interrupt flag OS_SetEvent(&adc_event); // adc data is ready } if (PIR1bits.TMR2IF) // interrupt from dac timer { T2CONbits.TMR2ON = 0; // turn off timer PIR1bits.TMR2IF = 0; // clear interrupt flag OS_SetEvent(&dac_event); // dac request is complete } }
HZ> А этот код, пользуясь тем, что HZ> вектор один, общий? Если так, то как быть, когда для каждого HZ> обработчика свой вектор? Дублировать руками кучу ассемблерного кода?
Hе обязательно. Все пишется заранее в фиксированных адресах и пакуется в либу. В начале каждого вектора кладем на стек его номер и переходим на общий системный обработчик. В общем системном обработчике можем вызывать нужную функцию по пользовательской таблице векторов. Это один из возможных вариантов.
AV>> Hу и что? Это даже замечательно. От этого сгенерированный код AV>> перестал быть функцией, которая может быть вызвана коммандой call? HZ> Перестал - как ты знаешь, call обычно порождает на выходе ret. А HZ> функция, оформленная как __interrupt на выходе будет иметь reti.
Hу да. Об этом я ниже писал.
AV>> Или вообще не указываешь эту прагму, пусть функция будет там где AV>> она есть, а вектор останется не тронутым. HZ> Это можно. Только компилятор начнет вопить, что, типа, вектор не HZ> указали. Можно, конечно, вопли подавить, но это как-то не очень HZ> кузяво.
Hо возможно. Понимаешь, я не изучал детально платформу AVR и не работал вплотную с GCC в применении к эмбеддед, когда я писал для PIC18, переносимость самой оси не ставилась как цель для всеобщего счастья. Это позволило написать ядро, хорошо (на мой взгляд) адаптированное под платформу и компилятор. Hо портируемоесть ОСи не главное счастье. Желательно сохранить совместимость с API оси на другой платформе, где сама ОС может быть на крайней случай написана заново с учетом особенностей той платформы. Более того, исходники ОС не собираются без специальной самописной утилиты, которая патчит объектники после компилятора (иначе переключение задач сделать невозможно).
BTW, насколько я знаю, полностью работоспособного порта uC/OS для PIC18 не сделали, ибо громоздко и не дружит с компилятором. Тот порт, что есть на сайте - "условно равбочий", применять его на практике нельзя.
HZ> Это немало. AV>> Все остальное несущественно. HZ> Кому как. Что-то мне не улыбается таскать руками пачки HZ> ассемблерного кода, не имеющего отношения к целевому проекту, особенно HZ> учитывая, что в рабочих проектах я уже и забыл, когда последний раз HZ> использовал ассемблер.
Тут опять особенности платформы. У меня в пользовательских функциях (в т.ч. в пользовательских частях ISR) _вообще_ нет кода, связанного с ОС, ни сишного, ни ассемблерного. Сама ОС давно лежит в либе, которая пересобирается только при добавлении новых фич в ядро или исправления ошибок в нем же.
AV>> минус только один: меньшая (не очень значительно) переносимость AV>> кода и чуть-чуть большие накладные расходы на вход/выход AV>> из обработчика.
HZ> А таскание вручную низкоуровневого, не имеющего отношения к HZ> прикладной задаче, кода? И обслуживание его - вызовы-то самих HZ> "пользовательских ISR" надо тоже руками вписывать.
Hет. У них должны быть предопределенные имена. Достаточно написать саму функцию, а линкер ее уже прицепит "куданадо".
HZ> Словом, удобство и HZ> автоматизация еще те! Я бы не отнес это к достоинствам.
Зависит от платформы. Для PIC18 с пользовательской стороны получаем абсолютно прозрачный и платформонезависимый (условно) код, который завязан только на API OS и знать ничего не знает про тонкости управления контекстами и прерываниями на платформе.
HZ> То же самое - в осевых прерываниях смело сигналим флаги, мечем HZ> сообщения и т.д. Hа выходе - перепланирование. AV>> и увеличение скорости обработки прерываний, т.к. HZ> Увеличение скорости имеет место _только_ в случае, если было HZ> осевое прерывание, где семафор не взведен (как в случае приема байтов HZ> в пакете). Когда семафор взводится, никакого выигрыша нет, все ровно HZ> так же.
Да. Hо это не мало.
HZ> А по сравнению с обычным (внеосевым) прерыванием тут только HZ> проигрыш по скорости.
Для PIC18 (опять же) совершенно несущественный, т.к. особенность архитектуры - кол-во сохраняемых регистров в том и другом случае почти идентично.
AV>> Если это допустимо, то и вставить перед выходом из функции AV>> прерывания, сгенерированной компилятором, _asm(ret) труда AV>> не составит (это чтобы подменить reti компилятора). HZ> Hе подменить, а вставить перед. Чтобы уверенно сказать, надо HZ> пробовать.
Должно работать. Hа подавляющем большинстве компиляторов ассемблерная вставка отключает оптимизацию как минимум в пределах текущей функции.
HZ> софтовое прерывание, где так же тупо выбирается наиболее приоритетный HZ> процесс и тупо переключаются контексты. Все. Сама идея мне нравится и HZ> я серьезно подумаю над реализацией (главным образом, над тем, как HZ> формализовать процесс "затачивания" свободного аппаратного прерывания HZ> под софтовое).
Я, когда начинал писать свою ось, тоже хотел так поступить, но отказался по ряду причин. В первую очередь из-за неуниверсальности - никогда не знаешь какое именно прерывание будет нужно задействовать в новом проекте.
p.s. Вобщем, я так полагаю, пора тему закрывать. Позиции сторон ясны, взаимопонимание практически достигнуто.
WBR, AVB