# Кпвтт

Аноним Uirh

Соображения по поводу интерфейса точка-точка меж модулями системы А5

Настоящий протокол обмена данными, изначально предназначенный для связи

устройств УЗП и МП2, тем не менее предполагается сделать по-возможности

симметричным и универсальным. А в паре УЗП-МП2 реализовать его подмножество.

ред 1.2 от 08.06.15


Что мы имеем?


В исходном виде МП это сменное ПЗУ на 64 Кб, связанное с УЗП двумя шинами:

- адрес - 16 разрядов - вход - будем обозначать (А) или (А00..А15)

- данные - 8 разрядов - выход - будем обозначать (Д) или (Д0..Д7)

Протокол взаимодействия предельно простой: УЗП выставляет на шине (А)

очередной адрес и через некоторое время (определяемое быстродействием МП, тоесть

почти сразу) считывает с шины (Д) находящийся по этому адресу байт данных. Всё.


МП2 это микроконтроллер, имеющий флеш-память такого же в точности размера

как и МП. Но там восемь корпусов ПЗУ с УФ-стиранием и еще какая-то мелкая

логика, а тут - всего один корпус и кроме кварца больше ничего. Экономия.

Однако т.к. в ПЗУ этого контроллера должна храниться не только полезная

информация, но и его собственная программа, полезную информацию приходится

хранить в упакованном виде и распаковывать мо мере надобности. В результате

имитировать с помощью МП2 вышеописанный протокол невозможно:

- всё это будет работать на два-три порядка (!) медленнее чем ПЗУ

- возможна только последовательная распаковка данных

Однако в данной системе ни особого быстродействия, ни произвольного

доступа к хранящимся в ПЗУ данным и не требуется - последовательного доступа

вполне достаточно. Но для передачи данных требуется совершенно другой протокол,

который бы включал в себя:

- опознавание - возможность для УЗП отличить МП2 от МП

- передачу команд (каковых как минимум одна: начать с нулевого адреса)

- собственно передачу данных


Рассуждалка.


Если бы в схеме МП был предусмотрен сигнал готовности - задача решалась-бы

тривиально: обнаружив изменение значения на шине (А), МП2 сбрасывал бы этот

сигнал в ноль и держал-бы сброшенным до тех пор, пока не распакует и не

выставит на (Д) соответствующий этому адресу (как правило просто очередной)

байт. И всё.

Но к сожалению такового сигнала нет. (Ну не предусмотрели... Так ведь

дело-то давнее: никто же тогда и не предполагал, что он может хоть для чего-то

понадобиться. ПЗУшке это совершенно ни к чему - её быстродействие более чем

достаточно...) Поэтому сейчас и приходится "городить огород": выделять под

сигнал готовности один из битов выходного байта. А передачу байта данных,

соответственно, производить в два приёма (например полубайтами). Следовательно

(для контроля) требуется еще и номер полубайта...

С другой стороны, т.е. со стороны УЗП, которое в этой схеме так и остаётся

ведущим, весь адрес целиком передавать не надо. Достаточно один раз установить

счетчик полубайтов (находящийся внутри МП2) в ноль, и дальше просто передавать

сигнал перехода к следующему полубайту и ждать появления готовности.

А для опознавания МП2 можно воспользоваться его неспособностью к

произвольному доступу: выставить некоторый адрес откуда ни-будь из середины, но

такой, чтобы по нему были ненулевые данные; запомнить значение (Д);

последовательно выставить некоторое количество (десяток - другой) адресов

(сколько именно - это надо посмотреть экспериментально, т.к. зависит от

быстродействия МП2), после чего по-новой выставить исходный. На (Д) должно быть

другое значение, отличное от ранее запомненного.


Всё это хорошо, просто замечательно - осталось расписать какие биты за что

отвечают... Но получается, что если исключить фазу распознавания МП/МП2, то

- оба байта шины (А) не нужны - достаточно одного

- следовательно аппаратный интерфейс УЗП-МП получается симметричный

- а коли так, то нельзя ли сделать симметричным так же и протокол?

...ну для каких ни будь будущих применений...

Можно!

А одно из этих самых "будущих применений" (на данный момент совершенно

фантастическое) - межмодульная связь в вычислительной системе А5 с "сотовой"

структурой. Представим себе такой модуль как шестигранную "гайку", диаметром

милиметров пятьдесят - семьдесят. С контактами на боковых гранях для связи с

соседними такими-же модулями. Расстояние до которых не более 1..3 мм. (Там надо

еще будет предусмотреть средства для обеспечения надёжного контакта, в т.ч. в

условиях запредельных вибраций, т.к. всё это предназначено отнюдь не для стояния

на столе...) Много контактов на грани длинной 25..35 мм не разместишь, но уж

штук двадцать-то всяко поместится. При этом - когда для стыковки с соседом мы

развернём сей модуль на 180 градусов - порядок следования этих контактов

изменится на противоположный, что для описываемого здесь симметричного

интерфейса как раз и надо!

Поскольку системы А5 в настоящий момент нету даже в виде проекта (и не

предвидится), то нафантазировать про её межмодульный интерфейс можно что угодно:

пожаловаться на перекос битов и заявить что последовательные интерфейсы быстрее,

проще и надёжнее, благо десятки (а то и сотни) гигагерц на таких совершенно

смешных расстояниях совсем не предел. И вообще к этому делу вполне можно

привлечь оптику... Однако то, что здесь описано - самое простое и

легкореализуемое.


Собственно протокол


Линии шин (А) и (Д) распределены одинаково:

- 4 бита - для передачи полезной информации (И)

- 3 бита - код синхронизации (С), включающий в себя:

- 1 бит - младший бит адреса (i)

- 1 бит - номер полубайта (j)

- 1 бит - команда/данные (k)

Изменением своего кода (С) ведущее устройство указывает ведомому на

необходимость выставить на (И) очередной полубайт полезной информации

в соответствии с кодом команды, находящемся на (И) ведущего; изменение

кода (С) ведомого устройства, так чтобы он стал равен коду (С)

ведущего, указывает ему на готовность ведомого - т.е. что очередной

полубайт выставлен.

- 1 бит - признак готовности (Г), указывающий, что значение (И) и (С) имеет

смысл: если (Г) ноль, значит либо (для ведущего) интерфейс неактивен,

т.е. он не требует от ведомого выполнения каких-либо действий; а для

ведомого - что он передал последний полубайт запрошенного у него

ведущим информационного слова, и больше данных для передачи у него

нет.


Так как интерфейс - точка-точка, то кто именно ведомый, а кто ведущий, оба

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

принципу КПВТТ: "кто первый встал, того и тапки"!

<<< вопрос: а не назвать ли этой забавной абревиатурой весь интерфейс? >>>

Т.е. всё время работы интерфейса делится на активные и пассивные интервалы

времени. Пассивным является интервал, когда признаки (Г) обоих устройств

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

выставит свой признак (Г) в единицу, тот и будет в следующем, начинающемся с

этого момента, активном интервале ведущим.

Ведущее устройство "убегает" от ведомого - всегда выставляет свой код (С)

отличным от кода (С) ведомого, а ведомое соответственно пытается его "догнать".


Типичный акт обмена происходит следующим образом:

1. ведущее устройство, удерживая ранее установленный (в процессе получения

статуса ведущего) (Г)=1, выставляет (на шину А):

(k)=1, (И)=код команды, (ij) не совпадающие с текущими (ij) на шине Д

2. ведомое устройство выставляет на шину Д то же самое, что видит на А;

или-же - если команда отвергнута - всё то же самое, но (Г)=0

3. ведущее устройство убеждается, что ведомое приняло команду, причем

правильно после чего, продолжая удерживать (Г)=1, выставляет (k)=0,

(ij)=00, (И)= младший полубайт первого байта передаваемых данных - если

ранее поданная команда предусматривает передачу данных с его стороны (или

оставляет на (И) код команды - если нет)

4. в ответ на это ведомое выставляет всё то же самое, что видит на шине А,

но, если предусматривается передача данных с его стороны - на

(И) - соответствующий полубайт

5. далее, удерживая (Г)=1 и (k)=0, ведущее выставляет (ij)=01, (И) = старший

полубайт... В дальнейшем, для каждого следующего байта значение (i) будет

меняться на противоположное, но всё остальное - повторяется

6. ведомое устройство действует либо как в п.4, либо, если данные у него

закончились - выставляет (Г)=0

7. чтобы завершить обмен данными - либо в ответ на (Г)=0 со стороны ведомого,

либо по своей инициативе, ведущее либо выставляет (k)=1 и тем самым подаёт

следующую команду, либо (если пока ему ничего больше не надо) выставляет

(Г)=0 и тем самым даёт возможность партнеру стать ведущим.


Проверка достоверности передачи данных находится за пределами протокола

(предполагается реализовать это на уровне системы команд), кроме п.3 где

ведомое устройство дублирует полученную команду. При ошибке, или при истечении

времени таймаута Т, в течении которого ведомое устройство обязано среагировать,

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

выставить (Г)=0, освобождая интерфейс, и по истечении еще одного периода

таймаута повторить процедуру получения статуса ведущего. Заметим, что ведомое

устройство обязано среагировать максимально быстро только при получении

команды: в п.4 или 6 задержки обуславливаются процессом подготовки очередной

порции данных и могут быть значительно больше.


С интерфейсом связано характерное время t, определяемое перекосом битов -

неодновременностью их прихода на одно из взаимодействующи устройств при условии

что другое устройство выставило эти биты строго одновременно. Второе характерное

время Т - интервал таймаута, вообще-то определяется быстродействием более

медленного из двух взаимодействующих устройств, но может быть установлен как

несколько периодов t (например четыре).


Система команд сильно зависит от назначения взаимодействующих устройств.

Распишем её пока только для случая УЗП -> МП2, предполагающего во-первых

наличие текущего адреса, а во-вторых при котором ведущим всегда является УЗП.


0 - пустая команда (выдача некоторого "идентификатора")

1 - сбросить адрес в ноль - своего рода инициализация

2 - передать текущий адрес - исключительно для контроля

3 - установить новый адрес - УЗП передаёт произвольный адрес, какой хочет

4 - передача данных - она-же - сброс контрольной суммы

5 - передача контрольной суммы всех байтов, переданных по предыдущей команде

Больше команд вроде как не требуется.


Следует заметить, что наличие двух битов синхронизации (i) и (j) вообще

говоря излишество - одного вполне достаточно. Второй можно присоединить

например к (И) или вообще исключить, сократив количество контактов. Однако в

системе УП-МП2 делать это нерационально: передавать по 5 бит - неудобно

(вызывает излишние сложности с переупаковкой битов в байты); использовать

для контроля четности... тоже не фонтан: четность хорошо считать аппаратно -

программно (если в системе команд нет специализированной операции) слишком

накладно. Так что пусть (как и было изначально задумано) один служит номером

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

Так-же разрядность (И) не обязательно четыре бита. Её вообще говоря можно

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

процедура определения разрядности, и вообще проверки наличия связи. Например

такая:


- в начале (т.е. сразу после включения питания, после сброса и.т.п) на ту

шину, которым данное устройство управляет (например Д) выставляются все нули

и удерживаются в течении времени Т0 (специального особо длинного таймаута).

При этом проверяется состояние (А).

- если на (А) тоже все нули - по истечении Т0 выставляется "1" -> (k) (или

даже, для пущей надёжности, сразу на (i), (j) и (k)) и в течении следующего Т0

ожидается появление "1" на (Г). Если появилась - данное устройство будет

ведущим. И наоборот: если в течении таймаута на (k) появилась единичка (при

всех прочих разрядах в состоянии "0") - необходимо выставить "1" на (Г) и

признать себя ведомым. Ежели по истечении Т0 шина А осталось =0 - партнёр

отсутствует.)


Примечание: комбинацию (Г)=0,(k)=1 - следует объявить запрещенной,

предназначенной исключительно для определения "лидерства". (Т.е. в п.2, если

ведомое устройство желает отвергнуть команду, то должно выставить в ноль оба

бита (Г,k).) Изначально предполагалось захват лидерства (из состояния, когда

оба (Г)=0) производить просто установкой этого сигнала в единицу. Но вполне

может сложиться ситуация, когда оба устройства выставят этот сиглал почти

одновременно - с разрывом не более t и в результате оба будут считать себя

ведущими. Так что внесём уточнение: если интерфейс неактивен - оба устройства

держат свои сигналы (Г) в нуле, то из них, которое хочет чтобы "тапки были

его" - выставляет единицу не на (Г), a на (k)! И только после того, как

получит адекватный ответ (единицу на (Г), означающую что мол "я вас слушаю,

сэ-эр") - уже только тогда выставляет её на (Г)... Ну и ещё что полагается по

вышеописанному протоколу.


- далее устройство, ставшее ведущим, производит "прозвонку" интерфейса:

сначала выдаёт на все разряды единички - получается команда с самым большим

номером, каковую надо бы зарезервировать как раз вот под эти "тестовые" цели.

Ведомое устройство должно всё это повторить (как впрочем и при получении любой

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

дефектных разрядов, а во-вторых - оценить быстродействие интерфейса - времена

t и Т.

Возможно этого уже достаточно - можно переходить к нормальной работе, или

выставить всю шину Д в ноль и дать партнёру побыть ведущим и прозвонить

интерфейс с его стороны. Но возможна вторая фаза - тестирование интерфейса

"бегущей единицей", дабы выявить межпроводные замыкания.

Если все разряды работают нормально - интерфейс используется "штатным"

образом. Если-же нет... Тут всё зависит от того на сколько интерфейсное

устройство "умное": побывавши сначала ведущим а потом ведомым, каждое из

устройств способно определить неработоспособные разряды обоих шин и выбрать

для работы исправное подмножество. (Алгоритм этого, в виду его очевидности,

описывать пока не буду. Наверно можно даже придумать способ замены неисправных

линий (i) и (k). А вот подменить неисправную линию (Г) скорее всего не

представляется возможным...) Впрочем ситуация отсутствия старших разрядов (И)

должна считаться "штатной" - означающей всего лишь разную разрядность

взаимодействующих устройств.


Процедура опознавания устройством УЗП типа модуля (МП или МП2) куда проще:

1. УЗП выставляет на шину А нулевой адрес и смотрит, что на шине Д. Если

не-0 - то мы имеем обоснованные подозрения, что модуль - МП. Потому как МП2

должен воспринять это как "пассивный" режим работы интерфейса и буде сам

инициативы никогда не проявляет - обязательно выставить ноль на шину Д.

2. подождав некоторое время Т00 (достаточно значительное, чтобы модуль МП2

заведомо успел среагировать) - опять проверяет состояние шины Д.

* если Д не ноль и совпадает со значением в начале интервала Т00 - модуль

точно МП - на этом проверку можно закончить.

* если Д равно нулю или за время Т00 изменилось - продолжаем проверку

3. УЗП выставляет на А какой либо другой адрес (для определённости обозначим

его Аа), по которому (теоретически) должна быть какая-то осмысленная

(ненулевая) информация) но такой, чтобы младший его байт (А00-А07) выглядел для

МП2 как команда 0 (чтение идентификатора).

4. далее УЗП ожидает ответа в течении следующего Т00. Если за это время

состояние шины Д изменилось и стало совпадать с (А00-А07) - фиксирует

характерный интервал Т2 - раза в полтора-два больший, чем для этого

понадобилось. (Иначе Т2 так и остаётся равным Т00.)

- далее УЗП выставляет адрес Аб, такой, чтобы он выглядел для МП2 как команда

чтения первого полубайта и по истечении Т2 считывает и запоминает то что на

шине Д.

- Далее выставляются адрес Ав, выглядящий как команда чтения второго

полубайта, и тоже производится ожидание в течении времени Т2. При этом

допускается перебирать адреса Ав1, Ав2, Ав3..., такие чтобы все они отличались

только значениями (А08-А15) - с тем, чтобы считанное по этому адресу значение

отличалось от запомненного.

- И вот наконец - опять выставляется адрес Аб и по истечении Т2 проверяется

совпадение значения на шине (Д) с запомненным. Если не совпадает

(а идентификатор устройства должен быть таким, чтобы два первых байта заведомо

различались) - значит точно МП2; если совпадают и при этом на предыдущем шаге

удалось найти такой АвХ, чтобы значение по этому адресу отличалось от значения

по адресу Аб - значит точно МП. Если нет - то неизвестно. (Впрочем для решаемой

задачи это несущественно.)