В продолжение моих заметок, посвященных разбору функционала процессора от фирмы Миландр 1967ВН28, рассмотрим способы общения с внешними устройствами. В данном процессоре есть возможности общения по следующим информационным каналам. Порты LINK (LVDS) и также имеется параллельный интерфейс, предназначенный для работы с внешней памятью. В данной заметке разберем работу с интерфейсом LINK. Этот интерфейс на отладочной плате выведен на разъемы DVI и процессор имеет всего 4 таких приемопередающих линий. Стоит отметить что этот интерфейс поддерживает одновременный прием и передачу (полный дуплекс). Чтобы эффективно работать с транспортировкой массива данных задействуем каналы DMA. Из одного канала DMA будем грузить данные в передающую линию интерфейса LINK и для первого опыта соединим передающий канал одного из LINKов с его же принимающей стороной, где уже другим каналом DMA организуем прием. Разъем DVI для работы с определенным LINK портом при определенной разрядности передачи выбирается исходя из представленных в паспорте отладочной платы таблиц 8 и 9. Таблички приведены ниже.

Стоит отметить что при некоторых вариантах соединения доступен только 1-битный формат приема/передачи, это связано с тем что не на все разъемы подведено по 4 линии данных.

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

Оба регистра не могут изменяться в процессе обмена. Запись в оба этих регистра возможна только при сброшенном нулевом разряде.

Так же необходимо сконфигурировать порт внешними сигналами.

На имеющейся у меня отладочной плате эти параметры устанавливаются движковыми переключателями SA14 и SA15. Я выставил TIMR0E в единицу, остальное по идее никак в данной ситуации не интересует.

Пойдем далее, было бы неплохо определиться с выбором канала LINK и каналов DMA. К сожалению, выбрать, бросив монетку у нас не получится ибо в зависимости от выбора LINKа мы можем либо иметь возможность передавать и в формате 4 бит и 1 бит, или только в формате 1го бита.

Далее DMA, в этом процессоре DMA работает не так как например в Cortex, где мы просто указываем «откуда взять и куда положить», а потом добавляем управляющее слово которое пускает процесс. Здесь управляющая структура DMA отдельно задается на приём и на передачу. Управляющей структурой для DMA  являются регистры блока управления передачей TCB.

Как пишут в документации, каждый TCB (он же DCx) регистр имеет длину 128 бит и разделен на четыре 32-битных

- регистр индекса (DI);

- регистр X количества и приращения (DX);

- регистр Y количества и приращения (DY);

- регистр управления и указателя цепочки (DP);

Эти четыре регистра образуют 128 разрядный регистр TCB, в который можно загрузить настройки как выровненное счетверенное слово из внутренней памяти посредством цепочки (о том как работает цепочка будет сказано ниже) или с помощью ядра. Для инициирования нового обмена, после завершения текущего, программа должна записать новые параметры в регистры TCB.

Теперь перейдем к выбору LINK и каналов DMA. Все в той же спецификации на микросхему есть полезная табличка.

Так как цифра два – хорошая цифра, то решено выбрать второй LINK.  Сразу по табличке видим, что для его передатчика используется канал DMA 6, а для его приемника применяется канал 10. Так же по табличкам 8 и 9 видим что нам подходят разъемы XS4, XS5.

На всякий случай еще раз поясню что DC в табличке это те же самые группы регистров TCB - DI, DX, DY, DP.

Теперь подробнее про управляющие регистры DMA:

Регистр DI

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

Регистр DX

Этот 32-разрядный регистр имеет два поля:

DXM – младшие биты (с 0-го по 15-й или с 0-го по 21-й) хранят значение модификатора адреса (DX_MODIFY), которое используется для изменения адреса после каждой транзакции;

DXC – старшие биты (с 16-го по 31-й или с 22-го по 31-й) хранят значение количества слов (DX_COUNT) в блоке данных, который необходимо передать. Например, если необходимо передать 16 слов данных, непрерывно размещенных в памяти, порциями по 4 слова в каждой передаче, то параметр DXC будет равен 16, а значение DXM будет равно 4. Длина операнда (порции данных) в регистре DP устанавливается равной счетверенному слову.

Существуют ограничения, которые следует принимать во внимание при программировании TCB:

 - указатель DI должен содержать адрес, выровненный на границе операнда, определяемого в регистре DP;

 -  Значение DXM должно быть кратно размеру операнда;

 -  Значение DXC должно быть кратным длине операнда.

Выбор длины полей модификатора и количества определяется типом обмена, задаваемым полем TY в регистре DP.

Регистр DY – применяется при реализации двумерной передачи но он нам сейчас не понадобится, потому опустим.

Регистр DP – Это настроечный регистр задающий режим работы передатчика\приемника канала. На табличке ниже описание его разрядов.

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

Если же есть необходимость передать не один блок данных, или принимать непрерывный поток данных, то стоит разрешить загрузку следующей цепочки настроек для TCB. Это реализуется установлением бита CHEN в единицу, также необходимо записать в первые 18 битов регистра DP указатель на область памяти в которой хранятся настройки для следующей цепочки. При таком раскладе по завершению работы канал DMA будет сразу получать новые настройки и продолжать работу.

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

Применим все это дело теперь на практике. Сначала реализуем однократную передачу блока данных от процессора к самому себе.

Сначала выделим память под буфер приема и буфер передачи

.SECTION /DOUBLE64 /CHAR32 .data;
.ALIGN 4;
.var arrt[8]={1,2,3,4,5,6,7,8};//массив передачи
.var arrr[8]={0,0,0,0,0,0,0,0};//массив приема

Далее выключим все LVDS порты и каналы DMA

.SECTION .program;
.ALIGN_CODE 4;
.GLOBAL _main;
_main:
SQCTL = 0x1200;;//переход в режим супервизора 
//выключим для начала линки
j0=0;;
LRCTL0=j0;;
LRCTL1=j0;;
LRCTL2=j0;;
LRCTL3=j0;;
LtCTL2=j0;;
//и их dma каналы
xr0=0;xr1=0;;
xr2=0;xr3=0;;
dc11=xr3:0;;
dc10=xr3:0;;
dc9 =xr3:0;;
dc8 =xr3:0;;
dc7=xr3:0;;

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

j0=(1<<4)+(4<<5);;//формат 4 бит
LtCTL2=j0;;
j0=(1<<4);;//формат 4 бит
LRCTL2=j0;;
lc0 = 10;;
dly_p1: if nlc0e, jump dly_p1;; // подождем
//включим передатчик
j0=1+(1<<4)+(4<<5);;
LtCTL2=j0;;
lc0 = 100;;
dly_p2: if nlc0e, jump dly_p2;; 
//Включим приемник
j0=1+(1<<4);;
LRCTL2=j0;;

Настраиваем и включаем DMA приемника и передатчика. Бит CHEN остается в нуле, т.к. нас сейчас интересует однократный прием/передача. Первые 18 битов регистра DP (xr3) так же оставляем нулевыми, так как указатель на следующую цепочку нам сейчас не нужен.

//Настраиваем и включаем DMA приемника
xr0 = arrr;;//указатель на массив данных
xr1=0x80004;;//сообщаем что будет 8 слов по 4 байта
xr2=0;;
xr3=0x40000000/*выбираем внутреннюю память*/+(3<<19)/*выбираем номер порта линк и направление
*/ +(3<<25);;/*ставим длину данных*/
dc10=xr3:0;;
//Настраиваем и включаем DMA передатчика
xr0=arrt;;//указатель на массив данных
xr1=0x80004;;//сообщаем что будет 8 слов по 4 байта
xr2=0;;
xr3=0x40000000/*выбираем внутреннюю память*/+ (7<<19)/*выбираем номер порта линк и направление
*/ + (3<<25);;/*ставим длину данных*/
dc6=xr3:0;;

Далее останавливаемся в бесконечном цикле

_main_loop:
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
nop;nop;nop;;
jump _main_loop;nop;;
_main.end:

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

В массиве передачи лежат данные.

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

Когда же мы доходим до пустых операторов то там появляются передаваемые данные

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

Комментарии (8)


  1. Pyhesty
    10.10.2021 01:34
    +1

    спасибо за интересную статью, конкретно этот процессор обсматривал несколько дней, что бы понять, можно ли принять видео поток по очень распространенному интерфейсу sub-lvds

    собственно сам формат представляет собой 8, 12 или 16 бит DDR, внутри потока есть синхрометки начала кадра и начала строки (SAV, EAV), более подробно есть в любой документации на сенсор IMX Sony

    я не смог для себя решить, возможно ли организовать приём и такого распространенного формата, может быть вы можете подсказать, возможен ли приём таких видеоданных, типа sub-lvds sony?


    1. mikrizh Автор
      12.10.2021 20:05

      Признаюсь, еще несколько зелен во всей этой кухне, так что дабы не ввести в заблуждение оставлю советы при себе:)


    1. byman
      18.10.2021 08:09
      +2

      Временная диаграмма вроде бы подходит - lvds-клок обеспечивает setup-hold для входных lvds-данных. Но вопрос в скорости потока и обьеме данных. Если рассматривать 4 линии данных и 288 МГц частоты клока, то это 288 Мбайт поток. Его без проблем можно принять во внутреннюю память. Но её обьем только 3 М байта. А если во внешнюю, то это уже 36 МГц 64-разрядная внешняя SDRAM шина. Тоже реально (шина до 100 МГц). Но еще проблема - поток данных будет непрерывным, т.к. линк не понимает где начало фрейма. Придется процессором фильтровать поток и находить нужные данные. Еще мне непонятна цель приема. информации :)


      1. Pyhesty
        18.10.2021 10:44

        спасибо за ответ

        1. цель приёма очень простая, есть с аналогичным протоколом детекторы меньшего разрешения 800х600 или 1280х1024, нужно принимать отдельные кадры и их обрабатывать. То есть целый поток не нужен, а только отдельные кадры. Один кадр 1280х1024 помещается во внутреннюю память. Так как наша промышленность ещё не освоила SDRAM большого объёма (поправьте, я был бы рад ошибиться), то идея состояла работать с этим кадром во внутренней памяти. По идее нужно достичь частоты приёма и обработки 10кадров в секунду по 1Мбайту каждый...

        2. можно признак начала кадра завести на прерывание и запускать DMA размером в один кадр по признаку начала кадра, но будет смещение

        3. мне конкретно не очевидно как собрать байт, кажется что шина собирает байт из 4 бит по 4м линиям lvds за два такта, а в sub-lvds передаётся байт по одной линии LVDS...

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


        1. byman
          18.10.2021 12:38
          +1

          Протокол LInk порта соответствует аналогу TS201. Правда, если было бы желание, то нет проблем добавить возможность поддержки указанного sub-lvds протокола. К тому же Link имеет и две обычные линии, с их помощью можно было бы обрабатывать информацию о начале кадра или строки. В данном случае , когда по 4-м линиям идут 4 различные потока, байты информации будут перемешаны. Link предполагает, что один байт просто передается двумя частями по 4 бита, по обоим фронтам клока. Так что добавится работа по деинтерливингу информации. Если использовать внешние сигналы начала кадра, то можно сформировать прерывание и включить приемник линка по прерыванию. Это уменьшит объем мусора, но все равно начало кадра придется определять по синхрослову, а затем еще и распаковывать данные.


          1. Pyhesty
            18.10.2021 12:52
            +1

            с сайта производителя "аналога": TS201 - модели данной серии продукции больше не производятся (((

            уффф... то есть получается, что процессоры изначально проектировались с целью стыковаться между собой и с аналогом, я не знаю высокоскоростных устройств, которые бы передавали по данному стандарту данные, а вот sub-lvds (это сони продвигала, но дальше сони ориентируется на mipi и стандарт вымрет) и mipi - востребованы... надеемся, что в будущих сигнальниках эти стандарты будут поддержаны...

            ps: именно множество битовых операций для определения начала кадра в куче и отпугнуло... возможно это решаемо, но слабо эффективно...


            1. byman
              18.10.2021 14:52
              +2

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


              1. Pyhesty
                18.10.2021 15:36

                к сожалению, отечественные производители не предлагают достаточной номенклатуры ПЛИС и стойкости к СВВФ(

                на текущий момент мне видится следующая ситуация:

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

                1. процессоры и микроконтроллеры

                2. память ОЗУ статическая (не очень быстрая и небольшого объема)

                3. память ПЗУ однократная

                4. интерфейсы (о! хотя бы это есть)

                5. питание

                нет:

                1. ПЛИС для предобработки и конвертации (Воронеж с псевдо flex?)

                2. Динамической памяти (быстрой и ёмкой)

                3. Приёмников MIPI (для прямой стыковки с сенсорами)

                4. ПЗУ типа NAND достаточной ёмкости

                буду рад, если поправят или подскажут у кого можно посмотреть ПЛИС и DDR =)