Можно выделить
три основных вида памяти, используемой в микроконтроллерах. Память программ представляет собой
постоянную память, предназначенную для хранения программного кода и констант.
Эта память не изменяет своего содержимого в процессе выполнения программы. Память данных предназначена для
хранения переменных в ходе выполнения программы. Регистры микроконтроллера -
этот вид памяти включает внутренние регистры процессора и регистры, которые
служат для управления периферийными устройствами. Вас, возможно,
удивит малый объем памяти микроконтроллеров. Далее вы увидите, что это не
является их существенным недостатком. Но при первом знакомстве данная
особенность действительно вызывает удивление, особенно, если сравнивать
микроконтроллеры с современными персональными компьютерами, которые содержат
десятки мегабайт памяти. Для хранения
программ обычно служит один из видов постоянной памяти: PROM (однократно-программируемое ПЗУ), EPROM (электрически программируемое ПЗУ
с ультрафиолетовым стиранием), EEPROM (ПЗУ с электрической записью и
стиранием, к этому виду относятся также современные микросхемы Flash-памяти) ROM
(масочно-программируемое ПЗУ). Все эти виды
памяти являются энергонезависимыми - это
означает, что содержимое памяти сохраняется после выключения питания
микроконтроллера. Такая память необходима, так как микроконтроллер не содержит
каких-либо устройств массовой памяти (магнитных дисков), с которых загружается
программа в компьютерах. Программа постоянно хранится в микроконтроллере. В процессе
выполнения программа считывается из этой памяти, а блок управления (дешифратор
команд) обеспечивает ее декодирование и выполнение необходимых операций.
Содержимое памяти программ не может меняться (перепрограммироваться) во время
выполнения программы. Поэтому функциональное назначение микроконтроллера не
может измениться, пока содержимое его памяти программ не будет стерто (если это
возможно) и перепрограммировано (заполнено новыми командами). Следует обратить
внимание, что разрядность микроконтроллера (8,
16 или 32 бит) указывается в
соответствии с разрядностью его шины данных. В Гарвардской архитектуре команды
могут иметь большую разрядность, чем данные, чтобы дать возможность считывать
за один такт целую команду. Например, микроконтроллеры PIC в зависимости от модели используют
команды с разрядностью 12, 14 или 16 бит. В микроконтроллерах AVR команда всегда имеет разрядность 16 бит. Однако все эти микроконтроллеры имеют
шину данных разрядностью 8 бит. В устройствах с
Принстонской архитектурой разрядность данных обычно определяет разрядность
(число линий) используемой шины. В микроконтроллерах Motorola 68HC05 24-разрядная команда размещается
в трех 8-разрядных ячейках памяти программ. Для полной выборки такой команды
необходимо произвести три цикла считывания этой памяти. Когда говорится,
что устройство является 8-разрядным, это означает разрядность данных, которые
способен обрабатывать микроконтроллер. Память
ROM (ПЗУ) используется тогда, когда программный
код заносится в микроконтроллер на этапе его производства. Предварительно
программа отлаживается и тестируется, после чего передается
фирме-производителю, где программа преобразуется в рисунок маски на стеклянном
фотошаблоне. Полученный фотошаблон с маской используется в процессе создания
соединений между элементами, из которых состоит память программ. Поэтому такую
память часто называют масочно-программируемой ROM. ROM является самым дешевым типом
постоянной памяти для массового производства. Однако она имеет ряд существенных
недостатков, которые привели к тому, что в последние годы этот тип памяти
почти не используется. Основными недостатками являются значительные затраты
средств и времени на создание нового комплекта фотошаблонов и их внедрение в
производство. Обычно такой процесс занимает около десяти недель и является
экономически выгодным при выпуске десятков тысяч приборов. Только при таких
объемах производства обеспечивается преимущество ROM по сравнению с E(E)PROM. Существует также ограничение,
связанное с возможностью использования таких микроконтроллеров только в
определенной сфере применения, так как его программа обеспечивает выполнение
жестко фиксированной последовательности операций, и не может быть использована
для решения каких-либо других задач. Электрически
программируемая память EPROM состоит из ячеек,
которые программируются электрическими сигналами и стираются с помощью ультрафиолетового
света. Память PROM может быть
запрограммирована только один раз. Эта память обычно содержит плавкие
перемычки, которые пережигаются во время программирования. В настоящее время
такая память используется очень редко. Ячейка памяти EPROM представляет собой МOS-транзистор с плавающим затвором, который
окружен диоксидом кремния (SiO2).
Сток транзистора соединен с «землей», а исток подключен к напряжению питания с
помощью резистора. В стертом состоянии (до записи) плавающий затвор не
содержит заряда, и МOS-транзистор закрыт.
В этом случае на истоке поддерживается высокий потенциал, и при обращении к
ячейке считывается логическая единица. Программирование памяти сводится к
записи в соответствующие ячейки логических нулей. Программирование
осуществляется путем подачи на управляющий затвор высокого напряжения (рис 1.7). Этого напряжения должно быть достаточно,
чтобы обеспечить пробой между управляющим и плавающим затвором, после чего
заряд с управляющего затвора переносится на плавающий. MOS-транзистор переключается в открытое состояние, закорачивая
исток с землей. В этом случае при обращении к ячейке считывается логический
нуль. Чтобы стереть
содержимое ячейки, она освещается ультрафиолетовым светом, который дает заряду
на плавающем затворе достаточную энергию, чтобы он мог покинуть затвор. Этот
процесс может занимать от нескольких секунд до нескольких минут. Рис 1.7 -
Ячейка памяти EPROM. Обычно,
микросхемы EPROM производятся в
керамическом корпусе с кварцевым окошком для доступа ультрафиолетового света.
Такой корпус довольно дорог, что значительно увеличивает стоимость микросхемы.
Для уменьшения цены микросхемы EPROM
заключают в корпус без окошка (версия EPROM
с однократным программированием). Сокращение стоимости при использовании таких
корпусов может быть настолько значительным, что эти версии EPROM в настоящее время часто используются
вместо масочно-программируемых ROM. Раньше
микроконтроллеры программировались только с помощью параллельных протоколов,
достаточно сложных для реализации. В настоящее время протоколы программирования
современной EPROM и EEPROM памяти существенно изменились,
что позволило выполнять программирование микроконтроллера непосредственно в
составе системе, где он работает. Такой способ программирования получил
название «in-system programming» или «ISP».
ISP-микроконтроллеры могут быть запрограммированы после того, как их
припаяли на плату. При этом сокращаются расходы на программирование, так как
нет необходимости в использовании специального оборудования - программаторов. Память
EEPROM (Electrically Erasable Programmable Memory - электрически стираемая
программируемая память) можно считать новым поколением EPROM памяти. В такой памяти ячейка стирается
не ультрафиолетовым светом, а путем электрического соединения плавающего
затвора с «землей». Использование EEPROM позволяет стирать и программировать микроконтроллер,
не снимая его с платы. Таким способом можно периодически обновлять его
программное обеспечение. Память EEPROM более дорогая, чем EPROM (в два раза дороже EPROM с однократным программированием). EEPROM работает немного медленнее, чем EPROM. Основное
преимущество использования памяти EEPROM заключается в возможности ее многократного
перепрограммирования без удаления из платы. Это дает огромный выигрыш на
начальных этапах разработки систем на базе микроконтроллеров или в процессе их
изучения, когда масса времени уходит на многократный поиск причин
неработоспособности системы и выполнение последующих циклов
стирания-программирования памяти программ. Функционально Flash-память
мало отличается от EEPROM.
Основное различие состоит в способе стирания записанной информации. В памяти EEPROM стирание производится отдельно для
каждой ячейки, а во Flash-памяти стирание
осуществляется целыми блоками. Если Вы хотите изменить содержимое одной ячейки Flash-памяти, то Вам потребуется
перепрограммировать целый блок (или всю микросхему). В микроконтроллерах с
памятью EEPROM
можно изменять отдельные участки программы без необходимости перепрограммировать
все устройство. Часто
указывается, что микроконтроллер имеет
Flash-память, хотя на самом деле он содержит EEPROM. В настоящее время между этими
типами памяти имеется мало различий, поэтому некоторые производители используют
эти термины как эквивалентные. При первом
знакомстве с описанием микроконтроллера многих удивит малый объем их оперативной
памяти данных 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 ;перейти
к предыдущей ячейке стека Если после
первой команды программа будет прервана, то после выполнения обработки
прерывания содержимое стека не будет потеряно.
|