\documentclass[a4paper,10pt, titlepage]{article}
%\documentclass[a4paper,10pt]{scrartcl}
\usepackage[utf8x]{inputenc}
\usepackage[english, russian ]{babel}
\usepackage{indentfirst} %для отступа в первом абзаце
\usepackage{cmap}
\usepackage[pdftex, unicode, final, colorlinks, linkcolor=blue, bookmarksnumbered]{hyperref}


\oddsidemargin=5.0mm     % +10mm -25.4mm
\evensidemargin=-10mm   % -10mm
\textwidth=150mm
\topmargin=-10mm
\textheight=250mm

\emergencystretch=50pt
%задаем сколько минимально букв можно переносить
\righthyphenmin=2


\begin{document}
%\maketitle

\section{Работа по Ethernet}
Для работы по Ethernet используются два TCP соединения с крейтом: одно для передачи команд крейту (порт 11113)  и одно для передачи данных  (порт 11110).

Формат команд описан в документе ltr\_tcp\_commands.txt.

Инициализация крейта по Ethernet выполняется следующим образом:
\begin{enumerate}
 \item Передается команда INIT без данных, запрашивается 510 байт. В ответе крейт высылает в этих 510 байт информацию от FPGA, в которой каждый чётный байт равен 0xE0, а нечётный - собственно информация. Анализируется реально только первые 500 байт!
 В новых прошивках начиная с 504 байта может быть передана дополнительная информация. В этом случае байты с 504 по 507 содержат спец. слово LTR\_PROTOCOL\_VERSION\_MAGIC (0xD91D3B45) в little-endian. Тогда байт 508 содержит старшую верию протокола, а байт 509 - младшую.
 
 \item  Для версий проткола > 0.0 крейт поддерживает вторичное управляющее подключение. В этом случае проверяем, является ли текущее подключение вторичным посылкой GET\_ARRAY на 1 байт по адресу LTR\_CRATE\_ADDR\_CONNECTION\_PRIMARY. Возвращается 0, если вторичное соединение, 1 - первичное. 
 \item  Если соединение вторичное, то уже есть у крейта соединение данных. В этом случае, если требуется полная инициализация (не только управляющие запросы), необходимо перевести текущее подключение в состояние первичного, попутно сбросив первичное подключение. Это делается с помощью PUT\_ARRAY с нулевым размером по адресу LTR\_CRATE\_ADDR\_CONNECTION\_FORCE.
 \item Для версий проткола > 0.0 получаем версию сохранения конфигурации слотов через GET\_ARRAY по адресу LTR\_CRATE\_ADDR\_SLOT\_CONFIG\_VER на 2 байта. 
  \item Передается команда GET\_NAME с запрашиваемым размером, равным 16
  \item Для LTR032 получение количества слотов по статусному регистру FPGA: GET\_ARRAY по адресу LTR\_CRATE\_ADDR\_FPGA\_STATE на 2 байта. Бит (1 << 6) определяет 8-ми местный крейт (0) или 16-местный (1)
  \item Чтение дескриптора с помощью команды GET\_ARRAY:
    \begin{itemize}
     \item Чтение описателя модуля типа t\_RawDevDescr (t\_ltr\_eth\_raw\_descr) по адресу LTR010\_MODULE\_DESCRIPTOR\_ADDRESS (LTR\_CRATE\_\-ADDR\_MODULE\_DESCR) c информацией о серийном номере + ещё какое-то имя, тип ЦПУ и частота (в новой версии использую только серийный номер и тип ЦПУ)
     \item Чтение версии загрузчика по адресу LTR010\_BOOT\_LOADER\_VERSION\_\-ADDRESS (LTR\_CRATE\_ADDR\_BOOTLOADER\_VER).
      В старом сервере читалось 16 байт, а используется только 4 (4-ый байт старшая версия, 1-ый младшая). В новом читаю 4.
     \item Для поддерживающих крейтов (LTR-EU с прошивки 2.0.0.0 и в любой в LTR-CEU/CU) чтение версии прошивки по адресу LTR010\_FIRMWARE\_VERSION\_ADDRESS (LTR\_CRATE\_ADDR\_FIRMWARE\_VER). С размером то же самое что и с версией загрузчика.
    \end{itemize}
  \item Чтение ревизии платы через GET\_ARRAY по адресу 0x90008001 (LTR\_CRATE\_\-ADDR\_BOARD\_REV) ревизии платы - 1 байт.
  \item Открытие сокета для приёма данных
  \item Установка маски скорости на медленную скорость.
\end{enumerate}

\section{Работа по USB}
Используется 0-ая управляющая контрольная точка для передачи управляющих пользовательских запросов (для всех запросов тип VENDOR в соответствии со спецификацией USB) и две конечные точки типа BULK --- одна на прием и одна на передачу. Номера конечных точке следует определить по стандартному дескриптору конфигурации USB --- как первые найденные типа BULK в нужных направлений (в разных крейтах используются разные адреса конечных точек. Плюс в некоторых объявлены реально не используемые точки типа interrupt).

32-битный параметр управляющего запроса представляет передается следующем образом: старшие 16 байт в поле index, младшие --- в поле value.

Инициализация крейта по USB выполняется в следующем порядке:
\begin{enumerate}
 \item Получение имени устройства для определения типа крейта с помощью управляющего запроса LTR\_USB\_CMD\_GET\_MODULE\_NAME (11) на 16 байт.
 \item LTR010: попытка перевода в режим загрузчика через управляющий запрос LTR\_USB\_CMD\_CALL\_APPLICATION (15) с параметром LTR\_CRATE\_ADDR\_\-BOOTLOADER\_START (0x83003C00)
 \item LTR010: попытка перевода в режим приложения через управляющий запрос LTR\_USB\_CMD\_CALL\_APPLICATION (15) с параметром LTR\_CRATE\_ADDR\_\-FIRMWARE\_START (0x83000000). Неудача выполнения запроса означает, что находимся в загрузчике. В этом случае завершаем сразу инициализацию.
 \item получение описателя модуля с помощью запроса LTR\_USB\_CMD\_GET\_ARRAY (2) (аналогично Ethernet)
 \item чтение версии загрузчика модуля (аналогично Ethernet)
 \item чтение версии прошивки модуля (аналогично Ethernet)
 \item LTR030, LTR031: чтение ревизии платы (аналогично Ethernet). При нахождении в загрузчике чтение ревизии не проходит (это единственный признак, который для LTR030/LTR031 отличает загрузчик от основной прошивки)
 \item инициализация DMA через запрос LTR\_USB\_CMD\_SET\_DMA\_PARAMETRS (4). index = 3, value = 0
 \item сброс ПЛИС через запрос LTR\_USB\_CMD\_RESET\_FPGA (3)
 \item LTR010, не в загрузчике: загрузка ПЛИС (с разбором текстового .ttf файла прошивки, где каждый байт представлен в виде трех ASCII символов и разделены запятой) по 4096 байт с помощью запроса LTR\_USB\_CMD\_PUT\_ARRAY начиная с адреса LTR\_CRATE\_ADDR\_FPGA\_FIRMWARE (0x86000000).
 \item инициализация ПЛИС с помощью запроса LTR\_USB\_CMD\_INIT\_FPGA (3)
 \item инициализация DMA через запрос LTR\_USB\_CMD\_SET\_DMA\_PARAMETRS (4). index = 3, value = 0x0700
 \item если не в загрузчике, то ждем по BULK начальный блок данных от ПЛИС (формат аналогичен ответу на INIT по Ethernet):
  \begin{itemize}
   \item LTR010: передается 500 байт данных
   \item LTR021: передается 500 байт, но в них после нужной информации идут нули, т.е. формат не совпадает с нужным. В некоторых прошивках ответ может вообще не прийти (это может также зависеть от наличия вставленного модуля), эту ситуацию приходится считать нормальной
   \item LTR030/LTR031: 
      \begin{itemize}
       \item крейт настроен по USB, сбор данных был остановлен: передается 510 байт
       \item крейт настроен по USB, сбор данных был запущен и не остановлен при передергивании кабеля или перезапуске сервера: данные могут прийти до нужных 510 байт! кроме того 510 байт могут и не прийти (но придет хотя бы мусор).  Кроме того, исключение о изменении состава модулей может прийти до 510 байт или после, а если 510 байт нет, то может не прийти вообще.
       \item крейт настроен по Ethernet: нет данных по BULK (т.к. BULK вообще не включен в этом режиме). Отчасти это может служить косвенным признаком того, что крейт настроен на Ethernet. По USB доступно только изменение настроек (интерфейс/адрес)
       \item крейт находится в загрузчике: нет данных по BULK (отличие от предыдущего варианта только в отсутствии обработки команды получения ревизии...)
      \end{itemize}
  \end{itemize}

\end{enumerate}



\section{Разбор потока данных от крейта}
  Данные делятся на 4 типа:
  \begin{itemize}
   \item Данные от модуля - передаются клиенту без обработки
   \item Команды от модуля - так же передаются модулю за исключением синхрометок и статуса для LTR34
   \item Команды от крейта - обрабатываются сервером. Это синхрометки и исключительные ситуации. Последние передаются в виде двух слов - 0xFFFFFFFF, 0xFFFFAAXX (второе слово нарушает правило признака от кого данные и требует отдельной обработки), где XX - номер исключения:
      \begin{itemize}
       \item 0 --- системная ошибка крейта (по ней просто читаются системные регистры крейта)
       \item 1 --- признак, что изменился состав модулей. По этому исключению необходимо прочитать из системного регистра новый состав
       \item 2 --- признак переполнения внутреннего буфера для  LTR021
       \item 3 --- признак, высылаемый на каждый пропущенный буфер при длительном переполнении
       \item 4 --- какой-то признак от LTR021, названный unknown sync --- что значит непонятно
      \end{itemize}
  \item Пользовательские данные - складываются в отдельный виртуальный канал (в ветке 2.0. эта возможность сейчас не поддерживается)
  \end{itemize}
  
  
\section{Протокол работы между клиентом и LTR-сервером}
Обмен выполняется по сокетам с использованием протокола TCP (порт 11111).
Соединения делятся на 2 типа:
\begin{itemize}
 \item Управляющие (с сервером в целом или с крейтом) --- по ним передаются только команды в виде запрос-ответе
 \item Потоковые (с модулем) --- по ним передается только команда инициализации, после чего сервер просто передает все принятые от клиента данные в крейт и наоборот, вставляя только номер слота при передаче (разбор самих данных идет только для LTR34 для контроля его внутренней очереди).

\end{itemize}

\subsection{Управляющие команды}
Каждая команда состоит из следующих слов:
\begin{itemize}
 \item 4 байта --- признак начала команды --- CONTROL\_COMMAND\_START (0xFFFFFFFF)
 \item 4 байта --- код команды --- CONTROL\_COMMAND\_BASE\_ (0xABCDEF00)  + N, где N --- от 0 до 0xFF
 \item произвольное количество данных (зависит от команды)
\end{itemize}

На команду возвращается ответ:
\begin{itemize}
 \item 4 байта --- код ответа:
    \begin{itemize}
     \item LTR\_CLIENT\_ACK\_GOOD (0xABCDEFEE) - команда выполнена успешно
     \item LTR\_CLIENT\_ACK\_MODULE\_IN\_USE (0xABCDEFEE) - модуль используется (при попытке соединится с модулем, с которым уже установлено соединение)
     \item LTR\_CLIENT\_ACK\_BAD (0xABCDEFFF) - ошибка (до версии 2.0.0.0 --- возвращался при любой ошибке при выполнении команды)
     \item 0xABCDEF00 + код ошибки (не совпадающий ни с одним из вышеперечисленных) - команда завершена с ошибкой, код которой указан в младшем байте (введен в версии сервера 2.0.0.0)
    \end{itemize}
 \item произвольное количество данных (зависит от команды и кода ответа)
\end{itemize}

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

Чтобы решить эту проблему, все новые команды, которые вводятся в версии сервера 2.0.0.0 и выше, представлены в следующем формате:

Команда:
\begin{itemize}
 \item 4 байта --- признак начала команды --- CONTROL\_COMMAND\_START (0xFFFFFFFF)
 \item 4 байта --- код команды --- LTR\_CLIENT\_CMD\_EX\_HDR\_SIZE (0xAС000000)  + N, где N --- от 0 до 0xFFFF 
 \item 4 байта --- количество данных на передачу в байтах
 \item 4 байта --- запрашиваемый размер на прием в байтах
 \item указанное количество байт данных на передачу
\end{itemize}

Ответ:
\begin{itemize}
 \item 4 байта --- код ответа
 \item 4 байта --- количество данных в ответе (не должно быть больше запрашиваемого)
 \item указанное количество данных
\end{itemize}

Таким образом, если код команды начинается с 0xAС00, то сервер знает что размер команды и размер ответа должны быть включены в заголовок команды и может обработать нужным образом неизвестные команды.


\subsection{Инициализация соединения}
Каждое соединение начинается с посылки команды CONTROL\_COMMAND\_INIT\_CONNECTION (0). Команда передается в следующем формате:

\begin{itemize}
 \item 4 байта --- признак начала команды --- CONTROL\_COMMAND\_START (0xFFFFFFFF)
 \item 4 байта --- код команды --- 0xABCDEF00 
 \item 16 байт --- серийный номер крейта, с которым устанавливается соединение. Если первый байт 0 => с первым найденным, при этом в ответе это поле будет заполнено серийный номером крейта, с которым реально установлено соединение.
 \item 2 байта  --- номер слота - младший байт --- сам номер, старший байт - флаги: DR00 0III:
    \begin{itemize}
     \item D - флаг отладки (в ветке 2.0.0.0 --- не поддерживается)
     \item R - raw data (в ветке 2.0.0.0 --- не поддерживается)
     \item I - Если не ноль, то явно задает интерфейс крейта, с которым нужно соединится. Может использоваться в случае если крейт подключен и по Ethernet и по USB (для настройки). Введен только с версии сервера 2.0.1.1.
    \end{itemize}          
 \item 4 байта --- В запросе не имеет значения. В ответе возвращается текущее значение меток tmark для крейта, с которым установлено соединение.
\end{itemize}

В ответ приходит подтверждение. Если код подтверждения LTR\_CLIENT\_ACK\_GOOD или LTR\_CLIENT\_ACK\_MODULE\_IN\_USE, то после подтверждения приходит копия запроса, с вставленным реальным серийным номером крейта и значением tmark.


\end{document}
