Передовица » Hardware » ДЗУ » Исследование КНГМД 140 » Структура контроллера

Структура контроллера

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

Гораздо интереснее сам контроллер. Его можно условно разделить на следующие блоки:

  • Шинный интерфейс: сюда входят различные элементы, которые преобразуют запросы центрального процессора в сигналы для различных частей контроллера.
  • ПЗУ начального загрузчика.
  • Защёлки состояния: 8 бит оперативной памяти, которые драйвер может неторопливо переключать. Их значения влияют на работу различных частей дисковода и секвенсора.
  • Секвенсор: так его называет Jim Sather - автор книги "Understanding Apple ][". На эту книгу я ещё буду ссылаться. Секвенсор - здесь это что-то вроде RISC-микроэвм, выполняющей кодирование и декодирование потока данных.

Шинный интерфейс

Пока без комментариев.

ПЗУ начального загрузчика

Без комментариев

Защелки состояния

Восемь отдельных триггеров. Любая операция процессора с портами ¤C0x0..¤C0xF приводит к установке нового состояния защелки. Забудьте о том, что написано в инструкциях к Агату, по крайней мере до следующего раздела. Защёлки адресуются тремя битами адресной шины A3, A2, A1, а значение, которое они запоминают, берется с шины A0. Т.е. каждый чётный адрес выключает какую-то защелку, каждый нечётный - включает. Прочитать состояние защёлок центральный процессор не может. Защёлки влияют на следующие функции:

  • 0..3, адреса ¤C0x0..¤C0x7 - выводятся на дисковод и включают электромагниты шагового двигателя, который перемещает головку. У эпловского дисковода (именно дисковода, а не контроллера!) есть особенность: включение фазы "1" (¤C0x3) приводит к постоянной генерации сигнала "защита записи". У агатовского железа этой заморочки нет. Смысл её, по предположению Jim Sather, в том, чтобы программеры приучились выключать магниты фаз прежде чем чего нибудь читать и, тем более, записывать. Очень оригинальный воспитательный ход :))
  • 4, адреса ¤C0x8/¤C0x9 - эта защелка в выключенном состоянии вырабатывает сигнал "сброс" для секвенсора, в эпловском контроллере она также обесточивает некоторые микросхемы. Во включенном - разрешает прохождение сигнала Drive Enable - т.е. включение дисковода и разрешение работы его выходных каскадов.
  • 5, адреса ¤C0xA/¤C0xB - выбирает линию, на которую будет выводится сигнал Drive Enable. Т.е. позволяет выбрать один из двух дисководов.
  • 6, адреса ¤C0xC/¤C0xD - эту защёлку и связанный с ней сигнал, в дальнейшем, я буду называть "C/D". Он является одним из аргументов процедур, исполняемых секвенсором.
  • 7, адреса ¤C0xE/¤C0xF - эта защёлку и связанный с ней сигнал, в дальнейшем, назовём "Write". Он передаётся в инверсном виде дисководу, а также является одним из аргументов секвенсора.

Секвенсор

Это микро-микро-микроэвм (или пикоэвм - кому как нравится). Архитектурно: содержит ПЗУ с четырьми процедурами и два регистра, один из которых выполняет роль АЛУ и аккумулятора, а второй - указателя команд. Каждая процедура имеет два бита-аргумента и состоит из 16 команд. Любая команда выполняется за один такт, частота тактирования - 2 МГц. Система команд состоит из 6 операций.

Аккумулятор секвенсора доступен ЦПУ на чтение и запись. Почти в любой момент. Программа ЦПУ может попытаться обратиться к нему, прочитав любой регистр ¤C0x0..¤C0xF. И записать в него новое значение, выполнив операцию записи в любой регистр ¤C0x0..¤C0xF. Т.е. в доступе к аккумулятору не используется какого либо декодера адреса.

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

Эпловский контроллер отличается тем, что у него для чтения доступны только чётные адреса, запись же возможна только по нечётным адресам. Попытка записи по чётному адресу приведёт к аппаратному конфликту на шине: т.е. управлять шиной данных попытается и ЦПУ и контроллер. Системный сигнал R/!W он просто игнорирует.

А как же защёлки ? ;))) А вот так вот. Именно в этом и суть. Они будут переключатся. И влиять на работу секвенсора, т.е. на содержимое его аккумулятора. Сопоставив скорость работы ЦПУ - каждая команда 2-4 такта на частоте 1 МГц, т.е. около 2-4 мкс на команду и скорость работы секвенсора - команда 1 такт на частоте 2 МГц, т.е. 0.5 мкс на команду, увидим, что порядок срабатывания защелок и вообще расписание работы ЦПУ здесь становится очень важно.

Из схемы шинного интерфейса следует, что защёлки срабатывают в первой полуволне тактовой частоты ЦПУ (на подъём уровня ф1, когда ЦПУ уже установил значения на шине адреса), а буферные усилители включаются во второй полуволне (на спад ф1, здесь ЦПУ выполняет чтение шины данных). Также именно спад ф1 является тактовым сигналом секвенсора. Отсюда первый важный, но неочевдный вывод: защелки меняют состояние до того, как очередную команду выполнит секвенсор. Но секвенсор может выполнить несколько команд до того, как ЦПУ захватит данные из его аккумулятора.

Процедуры секвенсора

В качестве входных данных секвенсор получает четрые бита. Два бита от защёлок 6 и 7, один бит - читаемые данные, один бит - старший разряд аккумулятора.

Сразу разберёмся с читаемыми данными: они проходят цифровую дифференцирующую (я правильно слово выбрал?) цепочку. Её задача: выделить спадающий фронт сигнала, который поступает от дисковода. Т.е. эта цепочка всегда возвращает последовательность вида 111101111 (выход цепочки - инвертирующий), независимо от того, какая реальная длительность "1" получена от дисковода (важно лишь, чтобы она была не короче 500 нс или хотя бы имелась в момент прохождения сигнала синхронизации секвенсора).

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

Процедура чтения бита "Защита записи"

Эта процедура самая простая, поэтому начнём с неё. Она полностью состоит из команд сдвига аккумулятора вправо, при этом старший разряд заполняется значением сигнала "защита записи", поступающего на контроллер от дисковода.

Процедура адресуется комбинацией "C/D = 1" & "Write = 0". Вспоминаем мануал:
lda ¤C0xD
lda ¤C0xE
bmi WrPr

На самом деле, в свете вышеизложенного, становится понятно, что многие другие комбинации тоже могут оказаться работающими: lda ¤C0xE
lda ¤C0xD
bmi WrPr

Какая разница, в каком порядке переключать защёлки, если важно только их конечное состояние ? А вот на эпле этот фокус уже может не пройти: lda ¤C0xD - чтение нечётного адреса - даст мусор.

Более экзотичная комбинация:
sta ¤C0xD
bit ¤C0xE
lda ¤C0x2
bmi WrPr

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

Процедура захвата данных с шины ЦПУ

Процедура вроде бы не сложная, но в ней имеется одна тонкость, которая неопытному программисту может испортить нервы. А опытный программист, однажды столкнувшись с нею, вообще с досады волосы себе выдерет :) и с воплями "кто ж так строит ?!" кинется из окна.

Эта процедура активируется комбинацией защёлок "C/D = 1" & "Write = 1".

Т.е. после того, как вы проверили состояние защиты записи, просто выполняем запись байта по адресу
sta ¤C0xF
Это приводит к переключению защёлки Write. Секвенсор начинает выполнять новую процедуру и на третьем от начала такте захватывает в аккумулятор значение, выставленное на шину данных.

А в чём хитрость ? А в том, что ЦПУ выставляет значение на шину данных в третьем такте только при исполнении команды "sta ¤C08F, x" (при условии непересечения границы страниц в результирующем адресе!). Например, команда "sta ¤C0xF" выполняется чуть быстрее, и к третьему такту на шине данных уже будут совсем другие цифры.

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

Активируется комбинацией "C/D = 0" & "Write = 1".

Как выглядит полная процедура записи байта ?
sta ¤C0xF, x
ora ¤C0xC, x

Официальный мануал говорит нам о том, что команда "ora ¤C0xC, x" нужна, чтобы начать запись данных из регистра, где байт, якобы, сохраняется и может быть затем записан повторно. Негде ему там сохраняться - аккумулятор у секвенсора всего один ! И именно он используется для сдвига бит. Но ora действительно нужна для переключения процедуры секвенсора с захвата на сдвиг. Если её не выполнить - секвенсор, через 8 своих тактов после захвата данных от sta, вновь начнёт слушать шину данных и ему не важно - пригласили его туда или нет :).

Сдвиг бита происходит на каждый восьмой такт секвенсора, т.е. каждые 4 мкс.

Что важно: во время последовательной записи нескольких байт драйвер должен заботится о двух вещах: 1) каждые 32 мкс прикармливать секвенсор новым байтом, 2) после каждой прикормки, не позднее 4 мкс, переключить секвенсор в режим сдвига. Как именно он это будет делать - дело его личное. Поэтому, даже в одном и том же драйвере, можно встретить различные комбинации команд:
STA ¤C08F,X / ORA ¤C08C,X
или
STA ¤C08D,X / LDA ¤C08C,X

Первая комбинация включает режим записи и сразу начинает скидывать первый байт (но защелка C/D уже должна быть включена в "1", например, процедурой проверки защиты записи), вторая же интересна тем, что не портит содержимое аккумулятора ЦПУ, выполняя переключение защёлки C/D (LDA просто читает из аккумулятора секвенсора только что записанное туда значение).

Кодирование битиков секвенсором (напомнию: "1" должна вызывать смену уровня, "0" - не менять линию записи) реализовано хитро: линия записи подключена к старшему биту указателя адреса команд секвенсора. Процедура секвенсора разделена на две три части: первая содержит 16 шагов и выполняется если старший бит аккумулятора = 1, вторая и третья части - 8 шагов и выполняются если старший бит аккумулятора = 0. Понятно, что когда исполняется длинная часть, старший бит адреса периодически меняет своё значение (как раз однажды за время записи одного бита), а две короткие части расположены таким образом, что во время их исполнения старший бит остаётся неизменным.

Чтобы следующая команда записи в аккумулятор попала в нужный такт секвенсора, ЦПУ должен выполнять её в момент, кратный 4-м своим тактам (т.е. 8 такта секвенсора - время записи одного бита). Так как байт, пока ещё, содержит 8 бит, очевидно, что в нормальном режиме ЦПУ должен засылать цифры раз в 32 своих такта. Если это время удлиннить (до 36 или 40 тактов), секвенсор, покончив с последним битом, начнёт генерировать нули (т.е. постоянный уровень на линии записи). Эти нули могут использоваться для того, чтобы во время чтения синхронизовать контроллер. Или можно использовать их и для чего нибудь ещё. Но помните: больше двух нулей подряд во время записи = мусор во время чтения.

Процедура чтения данных

Активируется комбинацией "C/D = 0" & "Write = 0". В этом режиме секвенсор выполняет довольно сложную программу, которая отличается у разных версий агатовского и эпловского железа. Но важно следующее:

  • Версии программ секвенсора Apple Disk ][ 3.2 и 3.3 отличаются тем, что 3.2 хуже работает с двумя, идущими подряд, нулями. В то время как 3.3 обрабатывает это несколько точнее. Агатовская версия программы секвенсора ближе к версии Disk ][ 3.2, но как раз работа с двумя нулями у неё вроде бы исправлена.
  • Байт считается полученным, когда старший бит (он читается первым), в процессе сдвига дополз до старшего разряда аккумулятора (используется сдвиг влево, так же как и в режиме записи).
  • Байт будет хранится в аккумуляторе до тех пор, пока контроллер не прочитает два старших бита следующего байта. При получении второго из них он очищает аккумулятор, бодро заталкивает туда два бита и переходит в основной цикл чтения. Это всё занимает, как не трудно догадаться, примерно 8 мкс, т.е. 2-4 команды ЦПУ (либо 16 мкс, если читаются байты синхронизации, дополненные нулями). Поэтому если попытаться читать аккумулятор быстрее, можно словить один и тот же байт несколько раз.
  • Как обычно, не особенно важно, какой именно адрес читать: в Агате любой кроме ¤C0xD и ¤C0xF (но помните и о влиянии других защёлок), в эппле - тоже самое, кроме нечётных адресов.

Как это работает ?

Да, вот, собственно, именно так. Т.е. в точном соответствии с процедурами, выполняемыми секвенсором. Что важно:

  • Помнить про особенность записи в аккумулятор секвенсора: вид команды и необходимость предварительного сброса чтением "защиты записи".
  • Аккумулятор секвенсора доступен по любому адресу, но любой адрес также влияет на состояние защёлок (кубик Рубика такой).
  • Аккумулятор в режиме чтения сбрасывается не после чтения ЦПУ, а совсем в другой момент.
  • Чтобы записать один и тот же байт дважды нужно всё таки дважды его закинуть в аккумулятор секвенсора, что бы про это не говорила документация.
  • Кто бы что не говорил о совместимости контроллеров Агата и Эпла - они всё таки отличаются даже с точки зрения программиста. Хотя да, агатовский контроллер будет дружить со стандартной эпловской программой.
  • Синхронизация (выделение старшего бита среди потока) основана на том, что контроллер ожидает, что любой байт имеет первым (старшим) битом единицу и будет пропускать все нули в её ожидании. Поэтому, подсунув ему последовательность 1111 1111 00 1111 1111 00 1111 1111 00 1111 1111 00 1111 1111 00, можно быть уверенным, что к её окончанию он будет в состоянии ожидания очередного байта, а не в какой либо иной фазе (независимо от того, что предшествовало этой последовательности !). Неточность в документации: там говорится о том, что эта последовательность формируется путём записи байтов ¤FF, к которым контроллер автоматически добавляет два нуля. Это не совсем так: просто драйвер после записи очередного ¤FF не передаёт контроллеру новых данных и контроллер вынужден писать нули, ни имея ничего другого. Через некоторое время драйвер вновь выдаёт очередной ¤FF и т.д. Мне просто не понравилось слово "автоматически".

Использование материалов проекта agatcomp без получения предварительного письменного разрешения agatcomp запрещено.


Почта для обратной связи: mail@agatcomp.ru


Живое общение по теме Агата: Telegram группа Agatcomp.


Накопленные знания и проекты: тематический ФОРУМ.


© 2004-2024 agatcomp.su / agatcomp.ru

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *