\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 соединения с крейтом: одно для передачи команд крейту (порт 11110) и одно для передачи данных.

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

Инициализация крейта по Ethernet выполняется следующим образом:
\begin{enumerate}
 \item Передается команда INIT без данных, запрашивается 510 байт. В ответе крейт высылает в этих 510 байт информацию от FPGA, в которой каждый чётный байт равен 0xE0, а нечётный - собственно информация. Анализируется реально только первые 500 байт!
 В новых прошивках последние 10 байт могут использоваться для иного назначения.
  \item Передается команда GET\_NAME с запрашиваемым размером, равным 16
  \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 Чтение версии прошивки по адресу 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.


\section{Баги текущей прошивки крейта}
\begin{itemize}
 \item Не работает горячее подключение модулей по Ethernet - крейтом не высылается исключение о изменении состава модулей
 \item После того как соединение по сокету установлено, крейт все равно продолжает прослушивать порт, в результате чего можно установить новые соединения по TCP, но на команды на них крейт отвечать не будет, пока не закроется первое.
\item Если закрытие управляющего сокета идет до полного закрытия сокета данных, то при следующем подключении крейт автоматически закрывает соединение по данным сразу после посылке слова о изменении состава крейтов
\item При потоке данных на передачу крейт помирает при работе по TCP
\item При работе по USB, если поток не был завершен по какому-либо модулю, то эти данные идут раньше информации о FPGA и крейт уже не опознается сервером...
\end{itemize}



\end{document}
