Регистры микроконтроллера. Пространство ввода-вывода

Стек

Память данных

 

При первом знакомстве с описанием микроконтроллера многих удивит малый объем их оперативной памяти данных RAM, который обычно составляет де­сятки или сотни байт. Если микроконтроллер использует для хранения данных память EEPROM, то ее объем также не превышает нескольких десятков байт.

Если Вы пишите программы для персонального компьютера (PC), то у Вас, вероятно, возникнет вопрос, что можно сделать с таким маленьким объе­мом памяти. Вероятно, Ваши приложения для PC содержат переменные, объем которых измеряется в килобайтах, не считая используемых массивов данных. При использовании массивов требуемый объем памяти может составлять сот­ни килобайт. Так что же можно сделать, имея объем ОЗУ порядка 25 байт?

Дело в том, программирование для микроконтроллера выполняется по не­сколько другим правилам, чем программирование PC. Применяя некоторые несложные правила можно решать многие задачи с использованием небольшо­го объема памяти RAM. При программировании микроконтроллеров констан­ты, если возможно, не хранятся как переменные. Максимально используются аппаратные возможности микроконтроллеров (такие как таймеры, индексные регистры), чтобы по возможности ограничить размещение данных в RAM. Это означает, что при разработке прикладных программ необходимо предваритель­но позаботиться о распределении ресурсов памяти. Прикладные программы дол­жны ориентироваться на работу без использования больших массивов данных.

 

 

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

Стек - это электронная структура данных, которая функционирует ана­логично своей физической копии - стопки бумаг. Когда что-либо помещает­ся в стек, то оно остается там до тех пор, пока не будет вынуто обратно. Представьте разноцветные листы бумаги, которые укладываются в стопку один на другой. Когда листы удаляются, то происходит их перемещение в обратном порядке. По этой причине, стек часто называют очередью типа LIFO (Last In. First Out) - «последний пришел, первый ушел».

В Принстонской архитектуре RAM используется для реализации множе­ства аппаратных функций, включая функции стека. При этом снижается про­изводительность устройства, так как для доступа к различным видам памяти требуются многократные обращения, которые не могут выполняться одно­временно. По этой же причине Принстонская архитектура обычно требует большего количества тактов на выполнение команды, чем Гарвардская.

Процессоры Гарвардской архитектуры могут иметь три области памяти, которые адресуются параллельно (в одно и тоже время): память программ, память данных, включающая пространство ввода-вывода, и стек.

В Гарвардской архитектуре стековые операции могут производиться в па­мяти, специально выделенной для этой цели. Это означает, что при выпол­нении команды вызова подпрограммы «call» процессор с Гарвардской архи­тектурой выполняет несколько действий одновременно. В Принстонской архитектуре при выполнении команды «call» следующая команда выбирается после того, как в стек будет помещено содержимое программного счетчика.

Необходимо помнить, что микроконтроллеры обоих архитектур имеют ограниченную емкость памяти для хранения данных. Превышение этого пре­дела может вызвать проблемы при выполнении программы.

Если в процессоре выделен отдельный стек, и объем записанных в него данных превышает его емкость, то происходит циклическое изменение содер­жимого указателя стека, и указатель стека начинает ссылаться на ранее запол­ненную ячейку стека. Это означает, что после слишком большого количества команд «call» в стеке окажется неправильный адрес возврата, который был записан вместо правильного адреса. Если микропроцессор использует общую область памяти для размещения данных и стека, то существует опасность, что при переполнении стека произойдет запись в область данных, либо будет сде­лана попытка записи загружаемых в стек данных в область ROM.

Теперь рассмотрим возможности сохранения в стеке содержимого регис­тров. В некоторых архитектурах нет команд, выполняющих загрузку содержи­мого регистров в стек «push» и извлечения из стека «pop». Однако команды «push» и «pop» могут быть легко реализованы при помощи индексного регистра, который явно указывает на область стека. При этом вместо каждой из команд «push» и «pop» используются две команды, указанные ниже:

 

Push: ;загрузка данных в стек

move [index], А ;сохранить содержимое аккумулятора в стеке

Decrement index ;перейти к следующей ячейке стека

 

Pop: ;извлечение данных из стека

increment index ;перейти к предыдущей ячейке стека

move А, [index] ;поместить значение стека в аккумулятор

 

Конечно такое решение является менее эффективным, чем использование специальных команд «push» и «pop», а используемый индексный регистр может потребоваться для других целей. Однако это решение обеспечивает имитацию стека при использовании процессоров, у которых такие команды отсутствуют.

Существует еще одна проблема с приведенным выше примером. Что случится, если произойдет прерывание между первой и второй командой, которые имитируют операции «push» и «pop»? Если программа обработки прерывания использует стек, то записанные в нем данные будут потеряны. Для предотвращения этого можно запретить прерывания перед выполнением этих команд или переставить их в следующем порядке:

 

Push: ;загрузка данных в стек

Decrement index ;перейти к следующей ячейке стека

move [index], А ;сохранить содержимое аккумулятора в стеке

 

Pop: ;извлечение данных из стека

move А, [index] ;поместить значение стека в аккумулятор

increment index ;перейти к предыдущей ячейке стека

 

Если после первой команды программа будет прервана, то после выпол­нения обработки прерывания содержимое стека не будет потеряно.

 

 

Подобно всем компьютерным системам, микроконтроллеры имеют множество регистров, которые используются для управлением различными устройствами, подключенными к процессору. Это могут быть регистры процессора (аккумуля­тор, регистры состояния, индексные регистры), регистры управления (регист­ры управления прерываниями, регистры управления таймером) или регистры, обеспечивающие ввод-вывод данных (регистры данных и регистры управления параллельным, последовательным или аналоговым вводом-выводом). Обраще­ние к этим регистрам может производиться различными способами.

Реализуемые микроконтроллером способы обращения к регистрам оказыва­ют существенное влияние на их производительность. Поэтому очень важно по­нять, как происходит обращение к регистрам, чтобы писать эффективные при­кладные программы для микроконтроллеров. В процессорах с RISC-архитектурой все регистры (часто и аккумулятор) располагаются по явно задаваемым адресам. Это обеспечивает более высокую гибкость при работе процессора.

Используя процессор, который может непосредственно обращаться к любому регистру, можно получить преимущество при разработке простых прикладных программ. Например, в микроконтроллере PIC содержимое ак­кумулятора и регистра состояния не изменяется при передаче управления в зависимости от значения бита в регистре порта IOPort.

Одним из важных вопросов является размещение регистров в адресном про­странстве. В некоторых процессорах все регистры и RAM располагаются в од­ном адресном пространстве. Это означает, что память совмещена с регистрами. Такой подход называется «отображением устройств ввода-вывода на память».

В других процессорах адресное пространство для устройств ввода-вывода отделено от общего пространства памяти. Основное преимущество размеще­ния регистров ввода-вывода в отдельном пространстве адресов состоит в том, что при этом упрощается схема подключения памяти программ и данных к общей шине. Устройства ввода-вывода обычно занимают маленький блок ад­ресов, что делает неудобным декодирование их адреса совместно с большими блоками основной памяти. Отдельное пространство ввода-вывода дает некото­рое преимущество процессорам с Гарвардской архитектурой, обеспечивая воз­можность считывать команду во время обращения к регистру ввода-вывода.