Ревич, Ю.В. Программирование микроконтроллеров AVR: от Arduino к ассемблеру
1 36 Часть //. Программирование микроконтроллеров АVR на ассемблере Задумаемся над вопросом : а почему обычные процедуры вызываются специальной командой call/rcall , а обработчики прерываний - простым безусловным переходом jmp/rjrnp? Если в принципе это одно и то же, то нельзя ли все привести к единой фор ме? Вы уже, наверное, сообразили , почему нельзя : переход по вектору прерывания происходит автоматически , и также автоматически перед этим адрес возврата поме щается к стек. Функциональность команд call/rcall здесь просто излишняя. И наобо рот - вызов обычной процедуры простым «прыжком» ( jmp) на метку ее начала в луч шем случае (если в стек еще ничего не писалось , и в ячейках стоят нули) по окончании процедуры приведет к перезагрузке контроллера, т. к. он по завершающей команде ret отправится по нулевому адресу. А выходы из обработчика или подпрограммы так же различаются ( reti или ret) , но по другой причине: потому что перед выходом из обработчика надо опять разрешить прерывания, установив сброшенный ранее флаг разрешения прерываний r . Если вы вдруг его уже установили программно (команда sei) , разрешив вложенные прерывания, то повторная установка с помощью reti ниче му не помешает. По этому поводу еще заметим , что команду ret можно указать в любом месте про граммы, и опытные программисты , манипулируя содержимым стека, могут выделы вать разные необычные кульбиты , для которых в ассемблере есть все условия . Но мы подобными вещами заниматься не станем, а любопытствующих я отправляю к посо бию [2] , автор которого всякие такие финты просто обожает. П роцедура RESET Теперь обратимся к процедуре RESET, т. е. к истинному началу программы - что там должно быть? Как мы уже неоднократно говорили, когда контроллер доходит до команды вызова подпрограммы, или в нем происходит прерывание, он должен сохранить состояние программного счетчика с тем, чтобы потом знать, куда вер нуться. Это, как мы уже слышали краем уха, происходит в специальной области памяти SRAM, которая называется стек (stack). Потому в любой программе на АVR-ассемблере, допускающей прерывания или просто использующей подпро граммы, как мы уже обсуждали в главе 4, первыми после метки RESET должны идти следующие строки: RESET : ldi temp , low ( RAМEND ) ; загрузка указателя стека out SPL, temp ldi temp , high ( RAМEND ) ; загрузка указателя стека out SPH, temp Этими операторами вы указываете, где компилятору расположить программный стек - а именно, в конце SRAM (что обозначается константой RAМEND, объявленной в соответствующем i nс - файле). Для моделей Tiny с аппаратным стеком (AТtiny28) эти строки следует опустить, а для тех моделей, у которых .стек программный, но объем SRAМне превышает 256 байт (AТtiny23 1 3 , ATtiny26 и др.), запись сокраща ется : RESET : ldi temp, RAМEND ; загрузка указателя стека out SPL, temp
Made with FlippingBook
RkJQdWJsaXNoZXIy MTExODQxMg==