Домашняя телеметрия
Система домашней телеметрии
Сбор и анализ информации с датчиков
Главная › Описание › Реализация КД и ЦК


IX. Реализация КД и ЦК.*

КД выполнен на МК Atmel ATmega8, тактовая частота 8 МГц. ЦК соединяется с Сервером с помощью USB и получает от него питание. Для того, чтобы не писать свой драйвер, в ЦК реализован стандартный USB-профиль последовательного порта. Применен МК AT90USB162 как наиболее простой и знакомый.

Примечание*:
В процессе реализации ЦК обнаружились следующие особенности.
  1. Отличия драйверов cdc в Windows и Linux.
    Драйвер Windows читает данные из конечной точки независимо от того, открыт порт или нет. Если порт не открыт, данные уходят в пустоту. Драйвер Linux читает данные из конечной точки только в том случае, если порт открыт. Поэтому ожидать готовности хоста в бесконечном цикле НЕЛЬЗЯ. Зависание в ожидании готовности приводит к невозможности обрабатывать текущие запросы USB и устройство зависает, даже если драйвер начнет пытаться читать из конечной точки.
  2. Зависание обмена на виртуальной машине.
    Linux сервер дома, проектом занимаюсь еще и на работе в свободное время. На работе Linux запускаю из виртуальной машины Oracle VM VirtualBox (версия 4.2.12r84980). В пробной программе при чтении данных из порта обнаружилась неприятная особенность - с вероятностью 50% после получения первых 100-400 байт дальнейшее получение данных блокируется до повторного закрытия/открытия порта. На поиск причины потратил 3 дня. Для поиска использовал:
    1. Перекомпилированный исходник cdc-acm с включенными опциями DEBUG и VERBOSE_DEBUG.
      Для контроля драйвера ядра cdc-acm.
    2. usbmon + wireshark
      Для контроля usb-транзакций внутри виртуальной машины.
    3. USBTrace
      Для контроля usb-транзакций между ЦК и виртуальной машиной.
    В результате выяснилось:
    1. CDC-ACM.
      В нормальном режиме работы драйвер cdc-acm так сообщает о своих действиях:
           15:36:27 cdc-acm.c: acm_rx_tasklet: sending urb 0xdeb00000, rcv 0xde765a18, buf 0xde765b58
           15:36:27 cdc-acm.c: Entering acm_read_bulk with status 0
           15:36:27 cdc-acm.c: Entering acm_rx_tasklet
           15:36:27 cdc-acm.c: acm_rx_tasklet: procesing buf 0xde765b44, size = 9
      	 
      Т.е. он отправляет драйверу шины USB запрос и ждет ответа, получает ответ, обрабатывает ответ, отправляет новый запрос. Во время зависания он пишет только одну строчку:
           15:36:27 cdc-acm.c: acm_rx_tasklet: sending urb 0xdeb00b00, rcv 0xde765a04, buf 0xde765b44
      	 
      Т.е. он отправил запрос и ждет ответа. После завершения программы пишет:
           15:37:03 cdc-acm.c: acm_control_msg: rq: 0x22 val: 0x0 len: 0x0 result: 0
           15:37:03 cdc-acm.c: acm_ctrl_irq - urb shutting down with status: -2
      	 
      Как видим, ответ так и не пришел. Вывод: драйвер CDC-ACM работает нормально, теряется ответ.
    2. USBMON.
      usbmon подтверждает действия драйвера. Получается, что виновато устройство ЦК? Но устройство ясно показывает, что из него не хотят читать.
    3. USBTrace.
      Чтобы выяснить все до конца, на машине-хосте тоже был установлен USB-анализатор - программа USBTrace. Программа платная, пришлось использовать crack. USBTrace позволяет отслеживать USB-транзакции, инициированные не только драйвером устройства, но и драйвером контроллера. Дело в том, что если захватить устройство в VirtualBox, то оно пропадает из списка устройств, вместо него виден только драйвер контроллера VBoxUSB.
      Здесь начинается самое интересное:
           Seq  Type            Time       Request                     I/O  EP  Status          Len
           #70  URB             14.862351  BULK_OR_INTERRUPT_TRANSFER  IN   81  STATUS_PENDING   0
           #71  URB             14.862713  BULK_OR_INTERRUPT_TRANSFER  IN   81  STATUS_SUCCESS   9
           #72  DEVICE_CONTROL  50.768658  -                           OUT   0  STATUS_SUCCESS  96
      	 
      Видно, что ответ от устройства на последний запрос все же пришел. Значит ответ теряется в драйвере VBoxUSB или в драйвере шины Linux.
    Для окончательного выяснения причины зависания устройство было подключено к реальному серверу Linux - работает нормально, сбоев при многочисленных перезапусках программы вызвать не удалось.
    Вывод: драйвер VBoxUSB в начале работы иногда теряет ответ на USB-транзакцию. Дальнейшее выяснение решено не проводить, т.к. устройство будет работать на реальной машине, а во время отладки на виртуальной можно смирится с тем, что иногда будут зависания.
  3. Проблема со стеком в ЦК.
    Проблема была из-за невнимательности, её опишем как напоминание. МК ЦК имеет небольшой объем ОЗУ - 512 байт, поэтому его легко израсходовать. Было занято 80% памяти, устройство в целом работало нормально, не зависало но:
    1. На объемых ответах устроство переставало что-либо выводить до перезагрузки, при этом продолжая работать.
    2. Происходили выпадания телеметрических данных.
    Тщательная проверка кода и отладка не выявила каких-либо ошибок. Через несколько часов появилась мысль, что плохая работа устройства может быть вызвана из-за недостатка памяти. Стек начинается с самых верхних адресов ОЗУ и растет вниз. При большой вложенности функций возможно израсходовывание стеком оставшихся 20% и повреждение им статических переменных.
    Было увеличено количество свободной памяти за счет уменьшения буфера команд. Вышеперечисленные дефекты исчезли.