Найти тему
Разумный мир

Микроконтроллеры для начинающих. Часть 5. Архитектура. Адресные пространства и память

Оглавление

Предыдущая статья цикла "Микроконтроллеры для начитающих. Часть 4. Очень кратко о микропрограммах" была факультативной. Однако, теперь мы еще на шаг приблизимся к практическому использованию микроконтроллеров. Пусть и упрощенно, схематически, но мы теперь представляем, как устроен процессор микроконтроллера. Пришло время подключать его к остальным узлам управляющей микроЭВМ микроконтроллера.

При слове архитектура большинство людей вспоминает о дворцах и зданиях, строительстве, возникает ассоциация со словом зодчий. Это правильно, но термин архитектура применим не только к строительству. Фактически, архитектура обозначает основные принципы использованные при проектировании и создании чего-либо.

Применительно к ЭВМ, под архитектурой обычно называют совокупность основных принципов, идей, подходов, методов, которые использовались при ее проектировании. Чаще всего входит в понятие архитектура ЭВМ входят:

  • Организация памяти. Это количество различных типов памяти, их организация, способы подключения к процессору, особенности работы памяти.
  • Система команд. Обратите внимание, я не сказал набор команд, я сказал система команд. В наборе команд ЭВМ(точнее, процессора) некоторые команды могут отсутствовать, могут включаться дополнительные команды, но подход к формированию системы команд остается неизменным. Набор команд это подмножество системы команд. Сюда входит адресность команд (количество операндов), режимы адресации операндов, тонкости выполнения (количество циклов, возможно, переменное), типы выполняемых операций, возможность расширения.
  • Подсистема ввода-вывода. Способы подключения и адресации внешних (периферийных). Сюда же относится и наличие (и организация) канала прямого доступа к памяти ЭВМ.
  • Возможность построения многопроцессорных комплексов. Одновременная работа нескольких процессоров в составе ЭВМ далеко не так проста, как может показаться. Причем и с точки зрения программиста.
  • Механические параметры. Да, как ни странным это кажется. Наверное все знают платы расширения устанавливаемые в настольные ПК или в гнезда PCMCIA. Были и определенные требования к размерам ТЭЗ (типовой элемент замены), так назывались платы устанавливаемые в стойки больших ЭВМ (ЕС, СМ). Механические параметры далеко не всегда входят в понятие архитектуры, но иногда такое встречается.

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

"Чистые архитектуры" идеального мира

Наиболее известны две архитектуры подключения памяти к процессору. Первая, знакомая всем по IBM PC совместимым ЭВМ (точнее, микропроцессорам 80x86), архитектура фон Неймана. Вторая, менее известная, но более важная для нас, как станет видно в дальнейшем, Гарвардская архитектура.

Наиболее известные архитектуры ЭВМ с точки зрения организации памяти.
Наиболее известные архитектуры ЭВМ с точки зрения организации памяти.

Как видно, основное различие здесь в использовании памяти.

Архитектура фон Неймана

Хранит и программу, и данные, в единой памяти. Это выглядит привлекательно, так как позволяет эффективно использовать память небольшого объема. У нас небольшая программа, которая обрабатывает большие объемы данных? Нет никаких проблем, главное, что бы суммарный размер программы и данных мог поместиться в память. Большая программа требующая мало данных? Тоже все просто.

Кроме того, мы можем заполнить область памяти данными и потом передать ей управление. Или использовать коды команд как данные, возможно, изменяя их.

Архитектура фон Неймана вполне естественна для универсальных ЭВМ, ведь в этом случае неизвестно, что именно потребуется программе и какое будет соотношение объема кода программы и данных. Мы можем легко загрузить новую программу и данные в память и начать выполнение.

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

Второй, менее очевидный минус, невозможность одновременного считывания очередной команды и операнда, или считывания команды и записи результата. Доступ к памяти может быть только последовательным.

Гарвардская архитектура

Используется разная память для программ и данных. Здесь у нас нет опасности исказить команды программы ошибкой с записью данных. И мы можем считывать очередную команду и записывать результат или считывать операнд одновременно, так как у нас разные блоки памяти. Минусы исчезли? Не совсем...

Теперь мы не можем передать управление области данных или использовать команды как данные. То есть, мы не можем изменять саму программу. Но это иногда все таки требуется. Теперь мы должны по отдельности загружать в области памяти коды команд и данные перед началом выполнения программы. Для универсальных ЭВМ эта архитектура менее удобна, чем архитектура фон Неймана. Зато для микроконтроллеров она подходит хорошо. Ведь программа в микроконтроллер обычно загружается если не однократно, то надолго и изменять ее не требуется. А отдельная область данных позволяет повысить надежность работы и уменьшить объем ОЗУ (оперативная память зачастую дороже). Теперь стало немного понятнее, почему я сказал, что Гарвардская архитектура для более важна, мы же говорим как раз о микроконтроллерах.

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

Суровый реальный мир и компромиссы

Реальные ЭВМ не используют в чистом виде ни одну из описанных выше архитектур. Хотя существовали и ЭВМ полностью им соответствующие. Архитектура реальных ЭВМ это некий компромисс. Но прежде чем двигаться дальше нам нужно кратко остановиться на понятии адресного пространства.

Адресное пространство

Под адресным пространством мы будем понимать логически единую совокупность адресуемых ячеек памяти. Звучит туманно? Не волнуйтесь, сейчас все станет понятно. Давайте начнем разбираться с более знакомой всем универсальной ЭВМ (в виде ПК, например).

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

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

Пример упрощенного представления об адресном пространстве программы. Иллюстрация моя
Пример упрощенного представления об адресном пространстве программы. Иллюстрация моя

Для процессоров 80х86 области памяти обычно называют сегментами. В рамках своего адресного пространства программа может как угодно распоряжаться памятью. Но выход за пределы адресного пространства запрещен (обычно, операционной системой). Видно, что адресное пространство задачи занимает часть, в общем случае, все имеющейся памяти ЭВМ.

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

Пример отображения адресного пространства задачи на физическую память ЭВМ. Серым цветом отмечены не используемые области памяти. Иллюстрация моя
Пример отображения адресного пространства задачи на физическую память ЭВМ. Серым цветом отмечены не используемые области памяти. Иллюстрация моя

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

Команды и данные не обязательно занимают все доступное адресное пространство программы. Если реальная потребность программы меньше, чем ей выделено памяти, то часть адресов остается неиспользованной. Доступное адресное пространство задачи может быть меньше, чем ее потребности в памяти. В этом случае приходится использовать методы организации виртуальной памяти, если это возможно. Виртуальную память я так же не буду рассматривать.

Адресные пространства могут полностью изолированными, могут частично перекрываться, могут полностью совпадать, одно из пространств может быть подмножеством другого. С точки зрения математики можно рассматривать адресные пространства как некий вид множеств (множества ячеек памяти) с почти всеми применимыми к множествам операциями.

В рамках приведенного ранее примера с адресным пространством задачи можно показать пример частичного перекрытия

Пример перекрывающихся адресных пространств. Иллюстрация моя
Пример перекрывающихся адресных пространств. Иллюстрация моя

Но какое это отношение имеет к микроконтроллерам? Самое прямое! И сейчас это станет видно.

Адресные пространства ЭВМ

Да, именно так. Микроконтроллер включает в себя управляющую ЭВМ, как мы уже видели ранее. Какие области памяти могут быть в ЭВМ? Вспомним наши "чистые архитектуры". Область команд программы и область данных. Но это не все, есть еще область стека, которая может оказаться не такой простой, и область ввода-вывода.

Почему ввод-вывод относится к памяти? Все просто. Мы должны как то адресовать устройства ввода-вывода, управлять ими, передавать им данные и получать ответы. Внешние устройства обычно представлены набором управляющих регистров, каждый из которых имеет определенный адрес. Вероятно, некоторым из вас знакомы команды IN и OUT, которые иногда используются для доступа к таким регистрам. Адреса в командах IN и OUT как раз и относятся к области ввода-вывода.

Еще я назову область специальных регистров процессора, о которой вспоминают не часто. Специальные регистры процессора могут иметь свои адреса, а могут и не иметь.

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

В общем случае мы не можем сказать, что именно хранится в ячейке с некоторым адресом, если не указано, к какому адресному пространству она относится. Например, ячейка с адресом 10 может хранить команду, если она в адресном пространстве команд (программ), или являться, например, регистром управления внешнего устройства, если она в адресном пространстве ввода-вывода, или быть просто некоторой переменной, если она в адресном пространстве данных.

Если еще раз вспомнить "чистые архитектуры", то станет видно, что в архитектуре фон Неймана адресные пространства программ и данных полностью совпадают. А в Гарвардской архитектуре они полностью изолированы.

А вот со стеком все немного интереснее. Стек хранит адреса возвратов и временные данные. С архитектурой фон Неймана все понятно, там адресные пространства совпадают. А как быть с Гарвардской? Мы не можем поместить стек в память программ, так он может содержать и данные. А в микроконтроллерах память программ еще и обычно представлена ПЗУ. Мы не можем поместить стек в память данных, так это позволит изменять адреса возвратов, которые относятся к памяти программ.

Мы можем решить проблемы поместив стек в специальную, изолированную, область памяти. Или сделать два различных стека, один для адресов возвратов, второй для временных данных. Теперь понятно, почему я выделил стек как отдельную область памяти, отдельное адресное пространство?

Подробнее описывать стек я сейчас не буду, это тема отдельной статьи. Забегая далеко вперед скажу лишь, что в Microchip нашли оригинальное решение проблемы стека для своих 8-разрядных микроконтроллеров. Там стек находится в отдельном адресном пространстве, причем фиксированного размера. Для моделей BaseLine и Mid-range стек хранит только адреса возврата и недоступен программно. Для моделей Extended Mid-range и PIC18 стек так же лежит в отдельном адресном пространстве, но уже доступен программно и может, с большой осторожностью использоваться для хранения крайне ограниченного объема временных данных, а вот для адресов возврата по прежнему используется аппаратная поддержка. Если вам стало интересно, можете почитать мою статью Организация памяти 8 битных микроконтроллеров Microchip PIC.

Но вернемся к нашей теме. Даже в Гарвардской архитектуре иногда требуется доступ к памяти программ, как к данным. Это можно сделать несколькими способами, я кратко расскажу о двух.

Пример организации доступа к памяти программ как к внешнему устройству. Иллюстрация моя
Пример организации доступа к памяти программ как к внешнему устройству. Иллюстрация моя

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

А вот второй способ гораздо хитрее и, на первый взгляд, нарушает все различия между архитектурами. Мы можем построить виртуальное адресное пространство, которое и будет использовать процессор, и которое будет являться объединением адресных пространств данных и программ. Вот так

Пример объединения адресных пространств программ и данных в единое виртуальное адресное пространство. Иллюстрация моя
Пример объединения адресных пространств программ и данных в единое виртуальное адресное пространство. Иллюстрация моя

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

Пример единого виртуального адресного пространства программ и данных. Иллюстрация моя
Пример единого виртуального адресного пространства программ и данных. Иллюстрация моя

Кто то может сказать, а чем это вообще отличается от архитектуры фон Неймана? А действительно, чем? Особенно с учетом того, что я сказал, что адресное пространство не обязательно должно отображаться на непрерывные области физической памяти.

Все просто, на самом деле. В архитектуре фон Неймана у нас адресные пространства программ и данных полностью совпадают. Фактически, там можно говорить о едином адресном пространстве программ/данных. В данном же случае, у нас адресные пространства программ и данных по прежнему изолированны, а виртуальное пространство строится как их объединение, но без нарушения изоляции.

Таким образом, для Гарвардской архитектуры мы можем строить виртуальные адресные пространства по разному комбинируя отдельные адресные пространства не нарушая их изолированности. А можно и включать одно пространство в другое, без изоляции. Например, мы можем включить адресное пространство регистров процессора в адресное пространство данных. Так сделано, например, в микроконтроллерах PIC Microchip и AVR Atmel. При этом туда же входит и адресное пространство ввода-вывода (для Atmel это не совсем так, но разница нам сейчас не принципиальна). Подробнее обо всем этом поговорим в следующих статьях.

Остается кратко упомянуть, как можно обеспечить изоляцию адресных пространств программ и данных для архитектуры фон Неймана. Тут тоже используются отдельные блоки управления памятью. Поскольку эта темя далеко от микроконтроллеров особенно углубляться в нее не буду. Скажу лишь, что обычно используется запрет передачи управления на области памяти, которые должны считаться памятью данных. При этом можно и читать, и записывать эти области, а вот передавать управление туда нельзя. И, разумеется, никто не отменял включения защиты от записи в определенные области памяти.

Архитектура и адресные пространства микроконтроллеров

Ну вот мы и добрались до микроконтроллеров. Путь был длинным и не простым, зато сейчас будет гораздо легче.

Во первых, с точки зрения организации работы с памятью все 8-разрядные микроконтроллеры, которые я буду, так или иначе, рассматривать и упоминать построены по Гарвардской архитектуре. И это понятно, так все они имеют память программ выполненную на основе ПЗУ (Flash память тоже можно рассматривать некий вариант ПЗУ).

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

В большинстве микроконтроллеров адресное пространство регистров процессора объединено (включено) в адресное пространство данных. Так же, во многих контроллерах с отдельным адресным пространством ввода-вывода оно частично, или полностью, может включаться в пространство данных. Более подробно я это буду рассматривать когда доберемся до организации памяти (не архитектуры).

Стек в микроконтроллерах AVR Atmel и STM8 размещается в области памяти данных. В 8-разрядных микроконтроллерах PIC Microchip стек располагается в собственном, изолированном, адресном пространстве, которое иногда доступно не только аппаратно, но и программно. В микроконтроллерах семейства MCS-51 стек так же размещается в области памяти данных, но там есть ряд дополнительных тонкостей. Кроме того, в микроконтроллерах этого семейства есть переключаемые регистровые банки, которые иногда позволяют минимизировать использование стека.

Некоторые микроконтроллеры позволяют организовывать виртуальное адресное пространство. Как это выглядит для микроконтроллеров PIC Microchip можно посмотреть в статье, ссылку на которую я давал выше. А вот для STM8 я приведу упрощенный вид виртуального адресного пространства

Упрощенный вид виртуального адресного пространства микроконтроллеров STM8. Серым цветом показаны не используемые участки адресного пространства. Иллюстрация моя
Упрощенный вид виртуального адресного пространства микроконтроллеров STM8. Серым цветом показаны не используемые участки адресного пространства. Иллюстрация моя

STM8 я выбрал из-за возможности показать, как может выглядеть полное (виртуальное) адресное пространство микроконтроллера в самом общем случае, который однако реализован на практике.

Практически все микроконтроллеры позволяют адресовать памяти больше, чем ее физически реализовано в микросхеме. В некоторых случаях, например, для MCS-51, имеется возможность подключать к микроконтроллеру внешнюю память программ и/или данных. Это усложняет применение микроконтроллера, так как появляется мультиплексирование, о чем я кратко расскажу отдельно. Зато появляется возможность снять некоторые ограничения по доступному объему памяти.

Сразу скажу, что вряд ли многие из вас (если вообще кто либо) столкнется с микроконтроллерами семейства MCS-51, да еще и с внешней памятью. Поэтому MCS-51 я буду уделять мало внимания, а про мультиплексирование упомяну только в данной статье, да еще при рассмотрении, что такое шины и какие они бывают.

Для нас, во всяком случае, на данном этапе, не имеет значения, как именно физически реализована память и внешняя она, или внутренняя. Особенности страничной, банковой, и прочих видов памяти я буду рассматривать отдельно, когда для этого придет время.

Заключение

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

Все изложенное в статье имеет самое непосредственное отношение к разработке программ для микроконтроллеров. Этого еще не достаточно, что бы начать разработку программ, но обойтись без понимания архитектуры памяти ЭВМ невозможно.

Возможно, что то осталось для вас не совсем понятным, несколько туманным, возможно даже не нужным. Не совсем понятное станет проясняться в дальнейших статьях. А не нужного в статьях нет. И это тоже станет понятно в дальнейшем. Есть не обязательное, но такие статьи я сразу помечаю как факультативные.

В следующей статье мы продолжим знакомиться с архитектурой памяти, точнее, с тонкостями ее реализации. До новых встреч.