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

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

Оглавление

Я обещал не просто писать статьи, а корректировать ход изложения с учетом комментариев читателей. Выполняю свое обещание. Эта статья является внеплановой, внеочередной. Причиной ее появления стало то, что у некоторых читателей вызвала затруднения статья "Микроконтроллеры для начинающих. Часть 5. Архитектура. Адресные пространства и память". А точнее шина ввода-вывода.

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

Адресное пространство ввода лежит ВНЕ адресного пространства памяти

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

Упрощенная функциональная схема одной из конфигураций ЕС-1022. Иллюстрация моя
Упрощенная функциональная схема одной из конфигураций ЕС-1022. Иллюстрация моя

В этой схеме нам знакомы процессор и ОЗУ (память). Эта ЭВМ архитектуры фон Неймана, так что память программ и данных общая. А вот внешние устройства, а они действительно внешние, по отношению к ЭВМ, подключались к так называемым каналам, с которыми и работал процессор. В данной модели было два селекторных канала, к которым обычно подключались внешние устройства долговременной памяти, и один мультиплексный, использовавшийся для подключения консольной пишущей машинки (да, именно так! и с такой ЭВМ я работал достаточно долго, сидел и за консолью), АЦПУ (по современному принтер), устройства чтения перфокарт (УПК) и устройства чтения перфолент (УПЛ). Были и другие устройства, на даже перечисленных для нашей цели слишком много.

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

На иллюстрации я показал, что к первому селекторному каналу подключено два устройства управления накопителями на дисках (УУ НМД). Первое имеет адрес в канале 80, а второе 90. К первому УУ НМД подключен один накопитель на магнитных дисках (НМД) с адресом, внутри УУ НМД, 0. Ко второму подключено два НМД с адресами 0 и 1. К второму селекторному каналу подключено устройство управления накопителями на магнитной ленте (УУ НМЛ) с адресом внутри канала 80. А уже к нему два накопителя на магнитной ленте (НМЛ) с адресами, внутри УУ НМЛ, 0 и 1.

Канальные программы была в ведении операционной системы, обычному программисту с ними дела иметь не приходилось. А вот обращаться к внешнему устройству требовалось. Полный адрес устройства формировался из номера канала (умноженному на 100), фактически, это адрес канала, адреса УУ и адреса внешнего устройства внутри УУ. Эти адреса, уже сформированные, я и указал для накопителей.

Так у нас есть три накопителя на дисках с адресами 180, 190 и 191. И два накопителя на лентах, с адресами 280 и 281. И эти адреса устройств ввода-вывода лежат вне адресов памяти. То есть, у нас есть два независимых адресных пространства - пространство памяти и пространство ввода-вывода.

На самом деле этот пример еще сложнее, так как каждый канал, по своей сути, формирует отдельное адресное пространство ввода-вывода. Обратите внимание, что у нас два УУ в разных каналах имеют одинаковые адреса (80). А каждое УУ формирует свое адресное пространство. Но такая детализация для нас сейчас совершенно излишня.

Поэтому зафиксируем самое важное для нас. Данный пример показывает адресное пространство ввода вывода лежащее вне адресного пространства памяти. Они полностью изолированы друг от друга.

Адресное пространство ввода-вывода лежит ВНУТРИ адресного пространства памяти

Для иллюстрации совершенного иного подхода я использую ЭВМ СМ-4. Вот ее очень упрощенная функциональная схема

Упрощенная функциональная схема одной из конфигураций СМ-4. Иллюстрация моя
Упрощенная функциональная схема одной из конфигураций СМ-4. Иллюстрация моя

Я не стал показывать накопители, это в данном случае не важно. В качестве консольного устройства тут уже использовалась не электро-механическая пишущая машинка, а алфавитно-цифровой терминал (25 строк по 80 символов, цвет - зеленый на черном). Это тоже для нас не важно, упомянул лишь для полноты картины.

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

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

В общем адресном пространстве под адреса устройств ввода-вывода отводился диапазон, если не изменяет память, с адреса 176000 по адрес 177777. Адреса ниже 176000 занимала оперативная память, причем не обязательно весь диапазон адресов. И каждое внешнее устройство было обязано иметь полный адресный дешифратор!

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

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

Что такое внешнее устройство с точки зрения процессора

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

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

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

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

Регистры внешнего устройства еще называют портами. Да я понимаю, что тут возникает неоднозначность терминологии... Порты параллельного порта... Но не я это придумал. Что бы избежать путаницы я буду использовать термин регистр, иногда делая в скобках уточнение "порт".

Реальный мир

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

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

IBM PC и Intel 8086

Я не буду рассматривать микропроцессор 8080 (Z80), но кратко остановлюсь на 8086, на котором был построен ПК IBM PC (да, я знаю про Mac), архитектура которого стала "де-факто" стандартом и самой популярной.

Очень упрощенная иллюстрация построения системной шины 8086
Очень упрощенная иллюстрация построения системной шины 8086

Этот микропроцессор был построен по архитектуре фон Неймана, а значит, имел единое пространство памяти программ и данных. Но он так же имел и отдельное пространство ввода вывода. Системная шина этого микроконтроллера была мультиплексной, то есть, в разные моменты времени, по одним и тем же линиям, передавались адреса памяти, данные, адреса ввода вывода (регистров, портов). Как именно работает мультиплексная магистраль (шина) сейчас объяснять не буду, это тема отдельной статьи. Но обращу ваше внимание на сигнал М/IO. Если этот сигнал равен 1, то магистраль работает с памятью. Это может быть чтение команды или данных, подробнее показывать не буду, нет необходимости. А вот если сигнал M/IO равен 0, то магистраль работает с внешними устройствами, с их регистрами (портами). То есть, с пространством ввода-вывода.

А нулевой уровень этого сигнала устанавливался только при выполнении машинных инструкций IN и OUT. Именно эти инструкции и использовались для обращения к регистрам внешних устройств. Тот, кто писал программы на ассемблере во времена MS-DOS помнит, что именно эти команды использовались для работы с регистрами оборудования.

Нужно заметить, что ЕС ЭВМ были копиями машин IBM 360/370. Возможно именно поэтому (одна фирма разработчик) для IBM PC работа с регистрами внешних устройств осуществлялась через пространство ввода-вывода. Хотя микропроцессор 8086 позволял использовать и адресное пространство памяти.

ОЗУ первых IBM PC было гораздо меньше, чем мог адресовать микропроцессор. Поэтому использовать подход фирмы DEC (разработчик PDP-11, с которой и копировалась СМ-4) возможность была. Но возможно, что кто то оказался очень предусмотрительным и вынес регистры внешних устройств в пространство ввода-вывода в расчете когда-нибудь установить память максимальной емкости. В конечном итоге, причине столь важна.

Однако, существуют и ЭВМ построенные на микропроцессорах 80х86, в которых используется комбинированная схема адресации внешних устройств.

Микроконтроллеры

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

Абстрактный микроконтроллер с изолированным адресным пространством ввода вывода

Поэтому более подробное описание я начну с некоего абстрактного микроконтроллера построенного по Гарвардской архитектуре.

Упрощенная функциональная схема абстрактного микроконтроллера. Иллюстрация моя
Упрощенная функциональная схема абстрактного микроконтроллера. Иллюстрация моя

Наш микроконтроллер имеет встроенную ЭВМ, состоящую из процессора, памяти команд и памяти данных. И одно внешнее устройство - порт-ввода вывода имеющий два регистра (порта). RDAT, в который записывается информация выставляемая на внешних выводах, и из которого считывается состояние внешних выводов. RDIR, который задает направление передачи каждой линии порта (внешний вывод вход или выход).

Как видно, в данном случае у нас адресное пространство ввода-вывода, в котором расположение регистры RDAT и RDIR, изолировано от адресных пространств памяти. А значит, для работы с ними нужно использовать команды IN port и OUT port. Первая считывает данные из порта port и сохраняет их в аккумуляторе, а вторая выводит в порт port содержимое аккумулятора.

Предположим так же, что процессор микроконтроллера имеет инструкции LD addr и ST addr. Первая загружает в аккумулятор содержимое ячейки памяти с адресом addr. Вторая сохраняет содержимое аккумулятора в ячейке памяти с адресом addr.

Предположим, что у нас есть необходимость задать направления работы выводов порта (нужное значение хранится в ячейке памяти с адресом 20), считать состояние внешних выводов и сохранить его в ячейке памяти с адресом 10. При этом регистр RDAT имеет адрес 10, а регистр RDIR адрес 20.

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

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

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

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

Считывание информации из памяти данных. Иллюстрация моя
Считывание информации из памяти данных. Иллюстрация моя

Теперь нам надо записать эту информацию в регистр RDIR порта. В нашем случае для этого придется использовать команду OUT 20, которая сделает все необходимое через шину ввода-вывода.

Запись информации в регистр внешнего (по отношению встроенной ЭВМ) устройства. Иллюстрация моя
Запись информации в регистр внешнего (по отношению встроенной ЭВМ) устройства. Иллюстрация моя

Конечно, шина ввода-вывода едина, просто я показал путь к конкретному регистру, для наглядности. Обратите внимание, что у нас в командах LD и OUT используется один и тот же адрес! При этом работают совершенно разные внутренние магистрали, так как эти адреса лежат в разных адресных пространствах.

Теперь считаем состояние внешних выводом порта. Для этого потребуется команда IN 10, которая считает состояние и поместит его в аккумулятор. При этом опять будет использована шина ввода-вывода.

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

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

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

Абстрактный микроконтроллер с адресным пространством ввода-вывода объединенным с адресным пространством памяти данных

Немного изменим наш микроконтроллер и совместим пространство ввода вывода с пространством памяти данных. Как это делается я показывал в статье "Микроконтроллеры для начинающих. Часть 5. Архитектура. Адресные пространства и память". Пусть у нас адреса единого пространства от 0 до FFF занимают ячейки памяти данных. А адреса от 1000 до 1FFF регистры (порты) внешних устройств.

Пример формирования раздельных шин памяти данных и ввода-вывода из общей шины объединенного адресного пространства. Иллюстрация моя
Пример формирования раздельных шин памяти данных и ввода-вывода из общей шины объединенного адресного пространства. Иллюстрация моя

Я не стал показывать границы микроконтроллера, что бы не загромождать рисунок. Различные шины выделены цветом и подписаны. Блоки с двойным знаком равенства (==) это цифровые компараторы, которые определяют попадание выставленного на шину адреса в заданный диапазон. Диапазон указан внутри блоков компараторов. Выходные сигналы компараторов управляю мультиплексорами (MUX), которые и определяют, какая шина будет работать дальше.

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

Теперь нам не нужны команды IN и OUT, достаточно использовать LD и ST. Только теперь адреса регистров изменятся. Так регистр RDAT будет иметь адрес не 10, а 1010. А регистр RDIR адрес 1020. Адреса ячеек памяти, для нашего примера, не изменятся.

Но зачем так сложно? Пусть регистры внешних устройств имеют полный адрес, как это сделано в СМ-4. Да, так тоже делается. Но представьте, что нам надо скрыть от программы тонкости работы с EEPROM или Flash памятью программ для записи каких то настроечных констант. Такая реализация разделения шин может облегчить построение блока долговременной памяти.

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

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

Абстрактный микроконтроллер с полностью совпадающими адресными пространствами памяти данных и ввода-вывода

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

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

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

Реальные микроконтроллеры

А теперь давайте кратко окинем взглядом реально существующие микроконтроллеры.

PIC Microchip

8-битные микроконтроллеры PIC не имеют команд ввода-вывода, то есть, команд IN и OUT. Забегая вперед скажу, что все регистры, включая регистры процессора, и все ячейки памяти данных лежат в едином адресном пространстве, которое называется регистровый файл. Ячейки памяти называются регистрами общего назначения (GPR), а регистры процессора и внешних устройств регистрами специальных функций (SFR). Из этого правила есть несколько исключения для BaseLine, где не все регистры процессора имеют адреса.

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

STM8

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

AVR Atmel (Microchip)

Самый хитрый микроконтроллер, так как часть регистров имеет и адреса в пространстве памяти данных, и адреса в пространстве ввода-вывода. При этом часть регистров доступны только в адресном пространстве памяти данных. Подробнее сейчас не буду углубляться, тема отдельной статьи. Эти микроконтроллеры имеют команды IN и OUT.

Заключение

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

Еще раз обращу внимание, все рассмотренные шины и адресные пространства располагаются ВНУТРИ микроконтроллера. При этом для микропроцессора эти шины выведены во внешний мир.

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

Устройства, внешние по отношению к микроконтроллеру, в большинстве случаев подключаются через специальные шины и интерфейсы (например, SPI, I2C,1-Wire, UART) или через порты ввода-вывода микроконтроллера (которые сами являются внешними, но расположенными внутри микроконтроллера, устройствами). Но об этом будут отдельные статьи.

Если честно, я не планировал так глубоко рассматривать адресное пространство ввода-вывода. Единственная причина, по которой я его упомянул в 5 части цикла, это наличие команд IN и OUT в микроконтроллерах Atmel. И особенности адресации некоторых регистров в этих микроконтроллерах. Ну и для полноты картины. Но как оказалось, эта тема вызвала неожиданный интерес у читателей.

На сегодня, пожалуй, достаточно. Надеюсь, теперь вам стало понятнее, как все устроено. Если что то остается не понятным, не стесняйтесь спрашивать.

Ну а в следующей статье, как и обещал ранее, рассмотрим режимы адресации операндов.

До новых встреч!