Воспрос по ISR

Sticker
Offline
Зарегистрирован: 09.06.2017

Использую макрос ISR для установки программы обработки прерывания, что в нем содержится не знаю, в какой момент запускается заданный ISR обработчик тоже не знаю, но предполагаю что до выполнения setup().

ISR (my_vector) {/* ...*/;;; }

Из-за  раннего запуска ISR не успеваю проинициализировать устройство и  оно не будучи должным образом инициализированным и получая информацию извне, зависает.

На момент начала действия ISR повлиять не могу, временно решаю проблему выставлением флага "устройство не инициализировано", по проверке которого прерывание завершает работу без каких-то действий. Но это временная затычка, так как нет времени для такой проверки.

Поэтому хочу сначала определить ISR на другой обработчик

ISR (my_vector) {return;}

а после инициализации поменять вектор в таблице прерываний с пустышки my_vector    на   реально действющую функцию  my_vector2. 

Для этого мне нужно знать пролог и эпилог (сохранение и восстановление регистров и др. действия) программы обработки прерывания. Где  их взять в виде asm вставки ?

 

Condensator
Offline
Зарегистрирован: 02.06.2017
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Sticker пишет:

Использую макрос ISR для установки программы обработки прерывания, что в нем содержится не знаю, в какой момент запускается заданный ISR обработчик тоже не знаю, но предполагаю что до выполнения setup().

ISR (my_vector) {/* ...*/;;; }

ничего там секретного не происходит, макрос раскрывается примерно так:

extern "C" void vector (void) __attribute__ ((signal, used, externally_visible)) __VA_ARGS__; \
    void __vector_17 (void)
{
// Ваш код
}

Вместо "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 и всё. Так что копайте свой код и ищите ошибку. Никакое прерывание не может "прийти" пока вы сами этого не захотите.

------------------------------

и самое главное забыл добавить: АВР - это Гарвардская архитектура. Это означает, что после запуска программы Вы не можете изменить ни одного байта програмного кода. Поэтому идея с изменением обработчика прерывания ВО ВРЕМЯ ИСПОЛНЕНИЯ - чушь собачья. Простите мой фрацузский.