Как почистить стек контроллера avr

Как почистить стек контроллера avr

При написании подпрограмм на языке ассемблера AVR (обычно это обработчик прерывания) иногда нужно сохранить в стек и потом восстановить оттуда регистр состояния процессора SREG. Однако простой командой pop SREG этого сделать нельзя, компилятор выдает ошибку.

Ошибка происходит потому, что SREG не является регистром общего назначения, таким как R16, R24 и т. п. Поэтому для сохранения SREG в стек нужно использовать промежуточный регистр, например:

Для сохранения SREG в промежуточный регистр можно использовать команды ассемблера lds и sts. Также не следует забывать о том, что промежуточный регистр тоже нужно сохранять в стеке. Пример обработчика прерывания Timer0:

http://microsin. net/programming/avr/how-to-push-sreg. html

Как почистить стек контроллера avr

Стек представляет собой область памяти, которую ЦПУ использует для сохранения и восстановления адресов возврата из подпрограмм.
Практически у всех микроконтроллеров AVR стек размещается в SRAM. Для адресации текущего элемента (вершины стека) используется указатель стека SP (Stack Pointer). Это однобайтовый РВВ SPL у моделей с объемом памяти данных до 256 б, или двухбайтовый SPH:SPL (SPH – старший байт, SPL – младший байт).

Когда микропроцессор встречает одну из инструкций вызовов rcall/call/ecall/icall/eicall, то адрес следующего за ними слова в памяти программ аппаратно копируется в стек. В момент выхода из подпрограммы по команде ret адрес возврата восстанавливается из стека в программный счетчик. В моделях с объемом памяти программ 128 и 256 к/слов для сохранения PC в стеке потребуется 3 байта, для всех остальных – 2 байта. При сохранении каждого байта содержимое SP уменьшается на единицу, а при восстановлении, соответственно увеличивается.


Рис.9 Расположение стека в памяти данных

Программист должен самостоятельно определить местоположение стека в самом начале программы. С точки зрения максимальной его глубины, вершину стека нужно поместить в самом конце SRAM, как это показано на рис.9:

Константа RAMEND из стандартного заголовочного файла m8def. inc имеет значение адреса последней ячейки SRAM.

В диапазоне адресов SRAM между РВВ и текущим положением SP размещаются переменные прикладной программы. Поэтому очень важно предварительно оценить максимальный размер стека (глубину стека). Может случиться так, что вершина стека поднимется слишком высоко и начнет “затирать” пользовательские данные, а это одна из самых сложно-выявляемых ошибок!

Стек AVR, помимо сохранения адресов возврата, имеет еще одно очень важное предназначение. Он позволяет сохранять любые данные специально предназначенными для этого командами push Rr (загрузка в стек) и pop Rd (выгрузка из стека). Каждый раз при выполнении push Rr содержимое Rr копируется в стек, после чего SP уменьшается на единицу. При выполнении pop Rr содержимое ячейки стека, на которую указывает SP, восстанавливается в Rr, а само значение SP инкрементируется. Стек подобного рода имеет организацию Last In First Out (Последний Вошел Первый Вышел): регистр, сохраненный последней командой push, будет восстановлен первой командой pop:

Через стек очень просто можно обменять содержимое регистров местами:


Рис.10 Пример работы стека

На рис.10 приведен небольшой фрагмент кода, в котором пошагово рассмотрен процесс изменения стека при входе и выходе из подпрограммы toggle и сохранении и восстановлении регистра R17. Это типичный пример, где могут понадобиться инструкции push/pop. Подпрограмма toggle использует РОН R17 в своих нуждах, но этот — же регистр может использоваться и в ходе основной программы. Поэтому, во избежание повреждения данных, R17 перед модификацией загружается в стек и восстанавливается из него перед командой ret.

У некоторых устаревших моделей ATtiny отсутствует SRAM. Поэтому стек таких микропроцессоров имеет совсем другое устройство. Он реализован аппаратно в виде недоступной для программиста области памяти. Глубина стека – всего три уровня вложения, что, соответственно, позволяет вызвать не более трех подпрограмм. Аппаратный стек не предназначен для сохранения данных.

http://cxem. net/mc/book10.php