P.S.: Delegate.h не нашел в инклудах, так что в классическом виде наверное не реализовать.
События в AVRGCC C++, как реализовать ?
- Сообщения: 64
- Зарегистрирован: Вт окт 10, 2006 08:38:11
Хочу по прерыванию делать калбеки чтобы в теле прерывания не выполнять длительные обработки, есть ли возможность в AVRGCC C++ реализовать классические калбеки или какой другой хитрый способ.
P.S.: Delegate.h не нашел в инклудах, так что в классическом виде наверное не реализовать.
P.S.: Delegate.h не нашел в инклудах, так что в классическом виде наверное не реализовать.
- Реклама
в моём понимании "классический callback" - это просто вызов из обработчика прерывания пользовательской функции, задаваемой в run-time... и это абсолютно ничем принципиально не отличается от "длительной обработки" в прерываниях.
ускоряет обработку прерываний очередь сообщений, но в AVR для этого маловато памяти... да и лично я не понимаю смысла этой задумки.
если я что-то понял не правильно - поправьте меня.
ускоряет обработку прерываний очередь сообщений, но в AVR для этого маловато памяти... да и лично я не понимаю смысла этой задумки.
если я что-то понял не правильно - поправьте меня.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Если я правильно понял что Вы хотите, то в обработчике прерывания сделать то, что надо сделать быстро и в нем же установить пользовательский флаг.
В основной рутине программы уже вызывать функции согласно установленным пользовательским флагам.
В основной рутине программы уже вызывать функции согласно установленным пользовательским флагам.
- Сообщения: 64
- Зарегистрирован: Вт окт 10, 2006 08:38:11
Z_h_e, по сути вы правы, но я не хочу полагаться на while в функции main, ибо есть ситуации когда я не могу предсказать попадет в этот while программа или нет. Я хочу в прерывании дернуть делегат, что приведет, как я думаю, к выходу из прерывания и начнет выполнять обработчик команды, или же мне просто надо отдохнуть и собрать мысли в кучу.
т.е. по сути вы хотите разрешить обработку других прерываний, не дожидаясь завершения обработки текущего? так это делается без всяких новомодных слов:Pit-Bul писал(а):что приведет, как я думаю, к выходу из прерывания и начнет выполнять обработчик команды
Код: Выделить всё
ISR(MY_vect, ISR_NOBLOCK){
// тут обрабатываете прерывание, но при этом остальные прерывания так же будут вызываться, прерывая эту функцию
}Код: Выделить всё
ISR(My_vect){
static uint8_t busy = 0;
if(busy) return;
busy = 1;
sei();
// дальше делаете обработку, не мешая другим прерываниям обрабатываться
busy = 0; // это обязательно в конце обработки
}если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Реклама
Несколько опасно.
1. Для перменной busy нужно запретить кеширование ее значения в регистре
2. Перед установкой busy в ноль, бывает смысл запретить прервания и убедиться, что нет пропущенных событий.
То есть, примерно так:
1. Для перменной busy нужно запретить кеширование ее значения в регистре
2. Перед установкой busy в ноль, бывает смысл запретить прервания и убедиться, что нет пропущенных событий.
То есть, примерно так:
Код: Выделить всё
ISR(My_vect){
volatile static uint8_t busy = 0;
uint8_t loop_control;
if(busy) return;
busy = 1;
do {
sei();
// дальше делаете обработку, не мешая другим прерываниям обрабатываться
cli();
// Проверяем, нет ли пропущенных событий
if ( something_exists ) {
loop_control=1;
} else {
loop_control=0;
}
} while(loop_control);
// И только если таких нет, сбрасываем флаг занятости обработчика и завершаем работу обработчика
busy = 0; // это обязательно в конце обработки
}
Последний раз редактировалось ptr128 Пт дек 16, 2016 15:02:28, всего редактировалось 1 раз.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Переменная размером в байт стирается одной командой. Ровно столько же потребуется для запрета прерывания.ptr128 писал(а):2. Перед установкой busy в ноль, бывает смысл запретить прервания и убедиться, что нет пропущенных событий.
Но если прерывания не запрещены, то между проверкой на пропущенные события и сбросом busy флага можно пропустить событие, если между этими командами возникнет прерывание.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Пожалуй соглашусь с запретом прерываний перед обнулением busy, чтобы случайно снова не войти в обработчик прерывания в котором находишься, стек можно переполнить если это будет очень часто это происходить. Но добавлять разрешение не надо, ибо это будет автоматом.
Но логику проверки событий не понимаю, что Вы хотели тут сделать?
Вообще мне кажется надо постараться избежать алгоритма вложенных прерываний, граблями попахивает.
Но логику проверки событий не понимаю, что Вы хотели тут сделать?
Вообще мне кажется надо постараться избежать алгоритма вложенных прерываний, граблями попахивает.
Специально не проверял, но во всех примерах в даташит на ATMega328P перед выходом из прерывания выполняют команду sei. Поэтому я тоже так делаю. Я с AVR знаком то всего три месяца. Или C автоматом sei генерит при выходе из обработчика прерываний?Z_h_e писал(а):Но добавлять разрешение не надо, ибо это будет автоматом.
Например, если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORnZ_h_e писал(а): Но логику проверки событий не понимаю, что Вы хотели тут сделать?
Собственно говоря, busy флаг и ограничивает вложенность перерываний.Z_h_e писал(а):Вообще мне кажется надо постараться избежать алгоритма вложенных прерываний, граблями попахивает.
Хотя тут я с Вами согласен и сам предпочитаю организацию очереди событий, разгребаемой основной программой.
Например, кольцевой буфер из N структур, состоящих из указателя на обработчик события и параметр для этого обработчика.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Из обработчика прерываний Си генерит команду reti, которая и разрешает прерыванияptr128 писал(а):Или C автоматом sei генерит при выходе из обработчика прерываний?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Терзают смутные сомнения, что есть такие примеры в ДШ обработчиков прерываний.ptr128 писал(а):Специально не проверял, но во всех примерах в даташит на ATMega328P перед выходом из прерывания выполняют команду sei.
Добавлено after 7 minutes 36 seconds:
Абсолютно бесполезное занятие. Флаг события будет сброшен, если оно возникнет до Вашей проверки.ptr128 писал(а):Например, если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
busy==1, возникает событие, программа входит в тот же обработчик котором была и тут же выходит. Флаг события утерян.
рассматривая сферических коней вы как-то упустили из виду, что повторный вход в обработчик прерывания до его завершения - это не просто грабли, это катастрофа в большинстве случаев. если часть событий обработчик пропускает (хоть из-за busy, хоть из-за запрета прерываний и т.п.), что он сможет хорошего сделать-то? я ввел busy скорее как инструмент отладки, по уму там надо было какой-то светодиод зажечь, дескать "что-то идет не так"... а пропускать обработку - это уже не нормально.
ну и если уж делать по-вашему, то перед сбросом busy логичнее не прерывания запрещать, а сбрасывать флаг запроса ЭТОГО прерывания, в надежде, что запросы поступают все-таки реже, чем каждые 2-4 такта
ну и если уж делать по-вашему, то перед сбросом busy логичнее не прерывания запрещать, а сбрасывать флаг запроса ЭТОГО прерывания, в надежде, что запросы поступают все-таки реже, чем каждые 2-4 такта
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Все разглядел. Это делается, если выход из прерывания не по reti. Так что sei перед выходом из прерывания действительно не требуется.Z_h_e писал(а):Терзают смутные сомнения, что есть такие примеры в ДШ обработчиков прерываний.ptr128 писал(а):Специально не проверял, но во всех примерах в даташит на ATMega328P перед выходом из прерывания выполняют команду sei.
Какой флаг? В честь чего будут сброшены в UCSRnA биты RXCn и DORn?Z_h_e писал(а):Абсолютно бесполезное занятие. Флаг события будет сброшенptr128 писал(а):Например, если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
Кто их сбросит?
В приведеном мной примере:ARV писал(а):если часть событий обработчик пропускает (хоть из-за busy, хоть из-за запрета прерываний и т.п.), что он сможет хорошего сделать-то?
обработать очередной байт из UDRn (при установленном RXCn) и предпринять какие-то действия, если было переполнение (при установленном DORn).ptr128 писал(а): если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
Чем это плохо?
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
зачем нужно перед ret ставить sei если есть специально обученная команда, где такое может понадобится?ptr128 писал(а):Это делается, если выход из прерывания не по reti.
Переходя на вектор прерывания, МК очищает соответствующий флаг. Как же иначе то, иначе его бы ручками надо было бы сбрасывать в прерывании, Вы же этого не делаете, что Вас тут удивило?ptr128 писал(а):В честь чего будут сброшены в UCSRnA биты RXCn и DORn?
Кто их сбросит?
А вот так как раз стек не heap и наезжает. Спасибо, не надо.ARV писал(а):перед сбросом busy логичнее не прерывания запрещать, а сбрасывать флаг запроса ЭТОГО прерывания
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Кстати, если поставить sei перед ret возникает опасность зависнуть в обработчике с переполнением стека, не может быть чтобы такое в ДШ было.
предположим, байты в УАРТ сыплятся каждые 10 мс, а обработка одного байта занимает 11 мс... вошли в прерывание, и начинаем обработку... вроде доделали - "смотрим события"... а там уже флажок нового байта... т.е. из прерывания не выходим, обрабатываем свеженький... только закончили - а уже новенький есть... я верно понял предлагаемый вами вариант обработки событий до выхода из обработчика?
если же байты идут каждые 12 мс, то даже и без флага busy ничего не произойдет... и контроль событий вообще не нужен.
если же байты идут каждые 12 мс, то даже и без флага busy ничего не произойдет... и контроль событий вообще не нужен.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
как это он наезжает? я же сказал: предполагается, что запросы прерывания следуют реже, чем те самые такты, что тратятся на сброс флага и выход из обработчика... если они следуют чаще - то выше показано, что это тот же каюк, но с другой стороны...ptr128 писал(а):как раз стек не heap и наезжает
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Из прерывания можно выйти не только по reti (или ret). Никто не запрещает, выходить из прерывания по JMP, не забыв проинициализировать SP.Z_h_e писал(а):зачем нужно перед ret ставить sei если есть специально обученная команда, где такое может понадобится?ptr128 писал(а):Это делается, если выход из прерывания не по reti.
Очень удивило. Читаю даташит и вижу совершенно обратное Вашему утверждению:Z_h_e писал(а):ptr128 писал(а):В честь чего будут сброшены в UCSRnA биты RXCn и DORn?
Кто их сбросит?
Переходя на вектор прерывания, МК очищает соответствующий флаг. Как же иначе то, иначе его бы ручками надо было бы сбрасывать в прерывании, Вы же этого не делаете, что Вас тут удивило?
Bit 7 – RXCn: USART Receive Complete
This flag bit is set when there are unread data in the receive buffer and cleared when the receive buffer is empty
(i.e., does not contain any unread data).
Bit 3 – DORn: Data OverRun
This bit is set if a Data OverRun condition is detected. A Data OverRun occurs when the receive buffer is full
(two characters), it is a new character waiting in the Receive Shift Register, and a new start bit is detected. This
bit is valid until the receive buffer (UDRn) is read.
Добавлено after 2 minutes 13 seconds:
У Вас навязчивая идея?Z_h_e писал(а):Кстати, если поставить sei перед ret
ptr128 писал(а): sei перед выходом из прерывания действительно не требуется.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.



