События в AVRGCC C++, как реализовать ?

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 64
Зарегистрирован: Вт окт 10, 2006 08:38:11

Сообщение Pit-Bul »

Хочу по прерыванию делать калбеки чтобы в теле прерывания не выполнять длительные обработки, есть ли возможность в AVRGCC C++ реализовать классические калбеки или какой другой хитрый способ.

P.S.: Delegate.h не нашел в инклудах, так что в классическом виде наверное не реализовать.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

в моём понимании "классический callback" - это просто вызов из обработчика прерывания пользовательской функции, задаваемой в run-time... и это абсолютно ничем принципиально не отличается от "длительной обработки" в прерываниях.

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

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Если я правильно понял что Вы хотите, то в обработчике прерывания сделать то, что надо сделать быстро и в нем же установить пользовательский флаг.
В основной рутине программы уже вызывать функции согласно установленным пользовательским флагам.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Открыл глаза
Сообщения: 64
Зарегистрирован: Вт окт 10, 2006 08:38:11

Сообщение Pit-Bul »

Z_h_e, по сути вы правы, но я не хочу полагаться на while в функции main, ибо есть ситуации когда я не могу предсказать попадет в этот while программа или нет. Я хочу в прерывании дернуть делегат, что приведет, как я думаю, к выходу из прерывания и начнет выполнять обработчик команды, или же мне просто надо отдохнуть и собрать мысли в кучу.
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Код: Выделить всё

ISR(MY_vect, ISR_NOBLOCK){
   // тут обрабатываете прерывание, но при этом остальные прерывания так же будут вызываться, прерывая эту функцию
}
или так

Код: Выделить всё

ISR(My_vect){
   static uint8_t busy = 0;
   if(busy) return;
   busy = 1;
   sei();
   // дальше делаете обработку, не мешая другим прерываниям обрабатываться
   busy = 0; // это обязательно в конце обработки
}
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

Несколько опасно.
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 раз.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

ptr128 писал(а):2. Перед установкой busy в ноль, бывает смысл запретить прервания и убедиться, что нет пропущенных событий.
Переменная размером в байт стирается одной командой. Ровно столько же потребуется для запрета прерывания.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

Но если прерывания не запрещены, то между проверкой на пропущенные события и сбросом busy флага можно пропустить событие, если между этими командами возникнет прерывание.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

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

Но логику проверки событий не понимаю, что Вы хотели тут сделать?

Вообще мне кажется надо постараться избежать алгоритма вложенных прерываний, граблями попахивает.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

Z_h_e писал(а):Но добавлять разрешение не надо, ибо это будет автоматом.
Специально не проверял, но во всех примерах в даташит на ATMega328P перед выходом из прерывания выполняют команду sei. Поэтому я тоже так делаю. Я с AVR знаком то всего три месяца. Или C автоматом sei генерит при выходе из обработчика прерываний?
Z_h_e писал(а): Но логику проверки событий не понимаю, что Вы хотели тут сделать?
Например, если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
Z_h_e писал(а):Вообще мне кажется надо постараться избежать алгоритма вложенных прерываний, граблями попахивает.
Собственно говоря, busy флаг и ограничивает вложенность перерываний.
Хотя тут я с Вами согласен и сам предпочитаю организацию очереди событий, разгребаемой основной программой.
Например, кольцевой буфер из N структур, состоящих из указателя на обработчик события и параметр для этого обработчика.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

ptr128 писал(а):Или C автоматом sei генерит при выходе из обработчика прерываний?
Из обработчика прерываний Си генерит команду reti, которая и разрешает прерывания
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

ptr128 писал(а):Специально не проверял, но во всех примерах в даташит на ATMega328P перед выходом из прерывания выполняют команду sei.
Терзают смутные сомнения, что есть такие примеры в ДШ обработчиков прерываний.

Добавлено after 7 minutes 36 seconds:
ptr128 писал(а):Например, если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
Абсолютно бесполезное занятие. Флаг события будет сброшен, если оно возникнет до Вашей проверки.

busy==1, возникает событие, программа входит в тот же обработчик котором была и тут же выходит. Флаг события утерян.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

ну и если уж делать по-вашему, то перед сбросом busy логичнее не прерывания запрещать, а сбрасывать флаг запроса ЭТОГО прерывания, в надежде, что запросы поступают все-таки реже, чем каждые 2-4 такта :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

Z_h_e писал(а):
ptr128 писал(а):Специально не проверял, но во всех примерах в даташит на ATMega328P перед выходом из прерывания выполняют команду sei.
Терзают смутные сомнения, что есть такие примеры в ДШ обработчиков прерываний.
Все разглядел. Это делается, если выход из прерывания не по reti. Так что sei перед выходом из прерывания действительно не требуется.

Z_h_e писал(а):
ptr128 писал(а):Например, если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
Абсолютно бесполезное занятие. Флаг события будет сброшен
Какой флаг? В честь чего будут сброшены в UCSRnA биты RXCn и DORn?
Кто их сбросит?
ARV писал(а):если часть событий обработчик пропускает (хоть из-за busy, хоть из-за запрета прерываний и т.п.), что он сможет хорошего сделать-то?
В приведеном мной примере:
ptr128 писал(а): если это прерывание по приему байта UART, можно проверить в UCSRnA биты RXCn и DORn
обработать очередной байт из UDRn (при установленном RXCn) и предпринять какие-то действия, если было переполнение (при установленном DORn).

Чем это плохо?
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

ptr128 писал(а):Это делается, если выход из прерывания не по reti.
зачем нужно перед ret ставить sei если есть специально обученная команда, где такое может понадобится?
ptr128 писал(а):В честь чего будут сброшены в UCSRnA биты RXCn и DORn?
Кто их сбросит?
Переходя на вектор прерывания, МК очищает соответствующий флаг. Как же иначе то, иначе его бы ручками надо было бы сбрасывать в прерывании, Вы же этого не делаете, что Вас тут удивило?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

ARV писал(а):перед сбросом busy логичнее не прерывания запрещать, а сбрасывать флаг запроса ЭТОГО прерывания
А вот так как раз стек не heap и наезжает. Спасибо, не надо.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Кстати, если поставить sei перед ret возникает опасность зависнуть в обработчике с переполнением стека, не может быть чтобы такое в ДШ было.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

предположим, байты в УАРТ сыплятся каждые 10 мс, а обработка одного байта занимает 11 мс... вошли в прерывание, и начинаем обработку... вроде доделали - "смотрим события"... а там уже флажок нового байта... т.е. из прерывания не выходим, обрабатываем свеженький... только закончили - а уже новенький есть... я верно понял предлагаемый вами вариант обработки событий до выхода из обработчика?

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

Мой уютный бложик... заходите!
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

Z_h_e писал(а):
ptr128 писал(а):Это делается, если выход из прерывания не по reti.
зачем нужно перед ret ставить sei если есть специально обученная команда, где такое может понадобится?
Из прерывания можно выйти не только по reti (или ret). Никто не запрещает, выходить из прерывания по JMP, не забыв проинициализировать SP.
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 перед выходом из прерывания действительно не требуется.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Ответить

Вернуться в «AVR»