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

Микроконтроллеры для начинающих. Часть 2. Процессор микроконтроллера

Оглавление

Это вторая статья цикла посвященного работе с микроконтроллерами. Первую часть можно найти по этой ссылке.

Если Вы помните, микроконтроллеры являются потомками управляющих ЭВМ. И сами являются ЭВМ, но специализированными. А какая составляющая ЭВМ является основной и главной? Конечно процессор. Вот с него и начнем изучать микроконтроллеры.

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

Процессор

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

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

Основным блоком процессора, его ядром, который и выполняет все операции является Арифметико-Логическое Устройство или, сокращенно, АЛУ. С него и начнем наше знакомство с устройством и работой процессора.

АЛУ

Давайте вспомним, какие основные арифметические и логические операции нам известны:

  • Сложение
  • Вычитание
  • Деление
  • Умножение
  • И
  • ИЛИ
  • ИСКЛЮЧАЮЩЕЕ ИЛИ
  • НЕ
  • Сдвиги

Это не полный список. Его можно дополнить, например, циклическим сдвигом. А можно и сократить, исключив умножение и деление, во всяком случае, для простых процессоров. Эти операции гораздо сложнее остальных и могут быть разложены на комбинации сдвигов и сложений/вычитаний. Основные операции я подробно описывал в статье "Простые типы данных. Машинное представление простых типов. Операции с простыми типами.", написанной в далеком 1999 году, поэтому здесь повторяться не буду, просто прочитайте, если это Вам интересно.

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

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

РЕЗУЛЬТАТ ← ОПЕРАНД_1 ОПЕРАЦИЯ ОПЕРАНД_2

Кстати, обратите внимание, что ← это тоже операция, операция присваивания (пересылки), если быть точным. Операции с одним операндом можно записать так

РЕЗУЛЬТАТ ← ОПЕРАЦИЯ ОПЕРАНД

Что вполне логично. Эта форма записи очень похожа на обычную математическую. Можно встретить и такой вид записи

РЕЗУЛЬТАТ ← ОПЕРАЦИЯ(ОПЕРАНД_1, ОПЕРАНД_2)

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

Условное обозначение АЛУ
Условное обозначение АЛУ

Однако, это обозначение не совсем удобно. Поэтому я отступлю от канонического обозначения и буду использовать такое

Такое обозначение АЛУ я буду использовать в статье
Такое обозначение АЛУ я буду использовать в статье

Этой иллюстрации требуются некоторые пояснения. Стрелки обозначают направление передачи информации. Косая черточка с цифрой на стрелках обозначает разрядность, количество передаваемых разрядов. В данном случае это 8, так как мы говорим о 8-разрядных микроконтроллерах. Если ничего не указано, то нам не важна разрядность данного сигнала. OP_1 и OP_2, как и следовало ожидать, операнды. CMD это код операции. RES - результат операции.

А вот на FLG_I и FLG_O остановлюсь немного подробнее. Это так называемые флаги (флажки), или признаки. И они участвуют в выполнении операции точно так же, как и операнды. Я назову три основных флага. ZF - признак нулевого результата. NF - признак отрицательного результата. CF - признак переноса. В разных процессорах названия флагов могут быть иными, но смысл сохраняется. В реальных микроконтроллерах флагов может быть как меньше, например, нет флага NF, так и больше, например, может присутствовать флаг DF обозначающий перенос между тетрадами в байте. Я предполагаю, что вы знаете, что такое тетрада. Если нет, все таки прочитайте статью о простых типах данных, ссылку на которую я давал.

FLG_I это флаги на входе АЛУ, а FLG_O это флаги после выполнения операции. Флаг может быть сброшен, если соответствующее ему условие не выполнено, или установлен, если выполнено. Так флаг ZF будет установлен, если результат операции равен нулю.

Флаги на входе АЛУ, или входящие флаги, используются для работы с данными, разрядность которых превышает разрядность АЛУ. Флаг CF, кроме того, используется в операциях сдвигов. Нужно отметить, что в качестве входящего флага полезен, в общем случае, только флаг CF (и DF, если он есть) из приведенного списка.

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

Вы можете сказать, позвольте, а откуда берутся операнды и код операции? Это ведь не похоже на полноценный процессор. Все верно, АЛУ это лишь часть процессора. Давайте посмотрим, откуда берутся операнды и куда потом девается результат.

Включаем АЛУ в схему процессора

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

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

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

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

ОПЕРАНД_2 ← ОПЕРАНД_1 ОПЕРАЦИЯ ОПЕРАНД_2

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

В результате мы можем получить примерно такую функциональную схему

Пример функциональной схемы включения АЛУ в состав процессора. Иллюстрация моя
Пример функциональной схемы включения АЛУ в состав процессора. Иллюстрация моя

Здесь ACC это регистр-аккумулятор, а FLAGS регистр флажков (пока будем называть его так). MUX это мультиплексоры, позволяющие передавать на свой выход один из своих входных сигналов, на выбор. DMUX это демультиплексор, который позволяет передать свой входной сигнал на один из выходов, на выбор. "1" и "0" это логические 0 и 1, то есть, константы, которые тоже могут быть операндами. Например, операция инкремента это увеличение на 1 значения операнда, то есть, операция сложения с единицей.

Шина памяти условно показывает подключение внешней, по отношению к процессору, памяти. Более подробно это будет рассмотрено дальше. Я не показал связь регистра флагов с шиной памяти не случайно. Флаги отражают состояние АЛУ и процессора и используются, за очень редким исключением, только самим процессором.

Добавляем работу с машинными командами

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

Пример почти полной функциональной схемы процессора. Иллюстрация моя
Пример почти полной функциональной схемы процессора. Иллюстрация моя

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

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

Я показал на рисунке и поле константы, хотя оно для микроконтроллеров редко соседствует с полем адреса операнда. В поле константы содержится некоторое число, указанное программистом. Например, в команде загрузки константы в регистр-аккумулятор.

Добавляем получение команды из памяти

У нас получилась упрощенная функциональная схема процессора? Не совсем. Пока остается открытым вопрос, а откуда, и как, берется та самая команда? Вот так, примерно, это устроено

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

CMD это регистр хранящий полученную из памяти команду. PC это регистр-счетчик команд. "+1" показывает, что регистр PC увеличивается для перехода к следующей команде. Но ведь есть и команды переходов, включая вызов подпрограмм, поэтому в регистр адреса команды может быть загружен и результат выполнения операции с выхода АЛУ.

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

Заключение

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

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

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

Рекомендуем почитать