Воспрос по ISR
- Войдите на сайт для отправки комментариев
Использую макрос ISR для установки программы обработки прерывания, что в нем содержится не знаю, в какой момент запускается заданный ISR обработчик тоже не знаю, но предполагаю что до выполнения setup().
ISR (my_vector) {/* ...*/;;; }
Из-за раннего запуска ISR не успеваю проинициализировать устройство и оно не будучи должным образом инициализированным и получая информацию извне, зависает.
На момент начала действия ISR повлиять не могу, временно решаю проблему выставлением флага "устройство не инициализировано", по проверке которого прерывание завершает работу без каких-то действий. Но это временная затычка, так как нет времени для такой проверки.
Поэтому хочу сначала определить ISR на другой обработчик
ISR (my_vector) {return;}
а после инициализации поменять вектор в таблице прерываний с пустышки my_vector на реально действющую функцию my_vector2.
Для этого мне нужно знать пролог и эпилог (сохранение и восстановление регистров и др. действия) программы обработки прерывания. Где их взять в виде asm вставки ?
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
http://www.nongnu.org/avr-libc/
http://www.nongnu.org/avr-libc/user-manual/pages.html
Использую макрос ISR для установки программы обработки прерывания, что в нем содержится не знаю, в какой момент запускается заданный ISR обработчик тоже не знаю, но предполагаю что до выполнения setup().
ничего там секретного не происходит, макрос раскрывается примерно так:
Вместо "17" компилятор пишет реальный номер вектора, который Вы используете.
атрибут "signal" - как раз и обозначает, что получтися прерывание с прологом и эпилогом.
Если есть желание писать пролог и эпилог ручками - то используем ISR(vector, ISR_NAKED).
Это и профессионал почти никогда не станет делать, а Вам, судя по заданному вопросу, это недоступно совершенно.
В разделе атомарных функций avr-gcc есть все нужные инструменты, чтобы писать руками. Это лежит у вас в каталоге с IDE на пути ../hardware/tools/avr/avr/include/util/atomic.h. Понимая, что именно нужно - там можно найти подходящее.
1. при входе сохраняем SREG;
2. используя заготовку (см. выше) сохраняем все регистры;
3. пишем свой код;
4. восстанавливаем все регистры;
5. восстанавливаем SREG;
6. reti() вместо return;
----------------
То что Вы написали дальше - какая-то бессмыслица.
Прерывание произойдет только тогда, когда оно разрешено. Не только sei() но и конкретный вектор.
Программа работает так:
1. отрабатыват функция init(), потом setup(), потому запускается loop() в бесконечном цикле.
init() содержит настройки таймеров и АЦП. Всё! Точка! больше ничего в Ардуино не происходит.
Вектор прерывания указывает на Вами написанный код, конечно, вот-прям-сразу, после загрузки. НО прерывания. кроме таймера0, ВСЕ ЗАПРЕЩЕНЫ, пока Вы их сами не разрешите. В init() разрешается прерывание по переполнению таймера 0 и всё. Так что копайте свой код и ищите ошибку. Никакое прерывание не может "прийти" пока вы сами этого не захотите.
------------------------------
и самое главное забыл добавить: АВР - это Гарвардская архитектура. Это означает, что после запуска программы Вы не можете изменить ни одного байта програмного кода. Поэтому идея с изменением обработчика прерывания ВО ВРЕМЯ ИСПОЛНЕНИЯ - чушь собачья. Простите мой фрацузский.