(Специально для Arduino Uno ...)
Что происходит со стеком, когда на микроконтроллере AVR происходит прерывание, и я вызываю функцию? Встроен ли компилятор в код? Кэширует ли он где-нибудь стек, а затем сбрасывает указатель стека? Есть ли у него вторичный стек только для прерываний?
Как я понимаю, вектор для прерывания - это прямая команда GOTO в сборке. Кроме того, я не думаю, что микроконтроллер будет автоматически связываться со стеком, поэтому он, вероятно, остался один. Однако это все еще не объясняет, как функции работают во время ISR.
arduino
interrupts
compiler
Анонимный пингвин
источник
источник
Ответы:
AVR - это архитектура RISC, поэтому он имеет довольно простую аппаратную обработку прерываний. Большинство процессоров связываются со стеком во время прерываний, хотя есть пара, особенно ARM и PowerPC, которые используют разные методы.
В любом случае, это то, что AVR делает для прерываний:
При возникновении прерывания аппаратное обеспечение процессора выполняет следующие действия, которые не являются простым GOTO:
Теперь на этом этапе оборудование сделало все, что оно собирается сделать. Программное обеспечение должно быть написано правильно, чтобы не сломать вещи. Как правило, следующие шаги идут по этим направлениям.
Вставьте регистр состояния в стек. (Это должно быть сделано в первую очередь, прежде чем он будет изменен).
Вставьте любые регистры процессора, которые будут (или могут быть) изменены в стек. Какие регистры, которые необходимо сохранить таким образом, определяются моделью программирования. Модель программирования определяется компилятором.
Теперь рабочий код прерывания можно запустить. Чтобы ответить на вопрос о вызове функции, она просто делает то, что всегда делает, помещает возвращаемое значение в стек, а затем возвращает его обратно, когда все готово. Это не влияет ни на одно из этих предыдущих значений, которые мы сохраняли в стеке до сих пор.
Теперь мы закончили и хотим вернуться от прерывания. Сначала мы должны сделать очистку программного обеспечения.
Выполните инструкцию РТИ. Аппаратное обеспечение выполняет эти шаги для этой инструкции:
а. Включить глобальный флаг прерывания. (Обратите внимание, что, по крайней мере, одна инструкция должна быть выполнена до того, как будет выполнено следующее прерывание. Это препятствует тому, чтобы тяжелые прерывания полностью блокировали фоновую работу.)
б. Вставьте сохраненный обратный адрес в ПК.
Теперь мы вернулись к нормальному коду.
Обратите внимание, что есть некоторые моменты, в которых мы должны быть очень осторожны, особенно в отношении регистра состояния и сохранения регистров, которые могут быть изменены. К счастью, если вы используете компилятор C, все это обрабатывается под прикрытием.
Кроме того, вы должны следить за глубиной стека. В любой момент, когда разрешены прерывания, ISR может использовать больше стека, чем очевидно, если посмотреть на локальный код. Конечно, это мало что дает, если вы не используете свою память до предела.
Вот ссылка, описывающая этот процесс, если вы хотите ссылку.
источник
ISR_NAKED
). Это может позволить вам пропустить шаги 5,6,8,9 в контексте, где вам действительно нужны эти циклы. Недостатком является то, что вы должны быть абсолютно уверены, что вы либо сохраните любые соответствующие регистры, либо сможете перезаписать их без вреда.