Чтобы подключиться к локальной сети обычно используют интерфейс Ethernet. Но не всегда удобно размещать его на своей плате. Интерфейс USB может дать больше возможностей и обходится гораздо дешевле. Здесь расскажу как к микроконтроллеру с USB подключить недорогой USB-Ethernet адаптер и получить выход в локальную сеть. Для примера использован полифункциональный зарядник.

Надо сказать, что выход в сеть и в интернет через USB для предыдущей версии нашего зарядника уже был продемонстрирован в этой статье. Но там требовался в качестве посредника компьютер, к которому подключался дивайс. В Azure RTOS для этого использовался класс USB device RNDIS.

Но вот хоста RNDIS в Azure RTOS нет, поскольку это проприетарный протокол, и скорее всего не будет. В свою очередь он нужен чтобы подключать мобильные телефоны и мобильные модемы. Отсутствие RNDIS хоста для подключения к мобильным гаджетам печально, но не критично. Мы выбираем host класс CDC-ECM и USB-Ethernet адаптеры.

Адаптеры USB-Ethernet строятся по одно-чиповой схеме. Такими чипами могут быть: ASIX AX88772A , ASIX AX88179, RTL8152, RTL8153, RTL8156... Эти чипсеты поддерживают классы устройств CDC-ECM с теми или иными особенностями. В Azure RTOS есть host классы для работы с CDC-ECM и ASIX.

Внутренности одного из адаптеров
Внутренности одного из адаптеров

Как видно по фотографии, дополнительным преимуществом USB-Ethernet адаптеров является некоторая гальвано-изоляция USB и Ethernet интерфейсов друг от друга с помощью трансформатора. Гальвано-изолированные домены соединяет лишь конденсатор ёмкостью 1000 пФ и максимальным напряжением 2 кВ.

Я приобрёл один из недорогих USB-Ethernet адаптеров NIC-mU2-01 на чипсете Realtek RTL8152B.

При подключении к компьютеру выяснилось, что адаптер имеет две конфигурации в дескрипторе USB дивайса. И первая конфигурация оказалась полностью проприетарной. К сожалению её-то и использует драйвер на компьютере под управлением Windows. Из-за наличия под первым номером проприетарной конфигурации Azure RTOS тоже отказалась работать с адаптером.

Проблема обнаружилась в функции _ux_host_stack_class_interface_scan стека USBX. Там обрабатывается только первая конфигурация устройства.

Вот такое простое изменение функции решает проблему:

UINT  _ux_host_stack_class_interface_scan(UX_DEVICE *device)
{

UX_CONFIGURATION        *configuration;
UINT                    status;


    /* Get the 1st and only configuration.  If the device has multiple
       configurations, we simply use the first one as default. */
    configuration =  device -> ux_device_first_configuration;
    if (configuration == UX_NULL)
        return(UX_ERROR);

    /* Scan interfaces for this configuration.  */
    status = _ux_host_stack_configuration_interface_scan(configuration);

    if (status != UX_SUCCESS)
    {
      configuration =  device -> ux_device_first_configuration->ux_configuration_next_configuration;
      if (configuration == UX_NULL) return(status);
      status = _ux_host_stack_configuration_interface_scan(configuration);
    }
    /* Return operation result.  */
    return(status);
}

Кроме того нашлась проблема в HAL поставляемом для STM32H7. В функциях USB_WritePacket и USB_ReadPacket не выровненные запись и чтение слов происходили со сбоями и пришлось переписать их реализацию.

Весь демонстрационный проект находится на Github.

Плата выполняет все те же функции как и в предыдущем демо проекте. Также включается и регулируется напряжение на выходе платы. Но теперь на экран выводится только информация о текущем сетевом подключении и интерфейс USB по умолчанию работает в режиме хоста. Причём хост реагирует только на подключение USB устройств содержащих класс CDC ECM.

Как только микроконтроллер на плате обнаруживает подключение дивайса с CDC ECM он запускает работу DHCP клиента и получает от сервера в локальной сети свой IP адрес.
После этого включается задача сервера Telnet и поверх Telnet начинает работать задача интерактивного управления по протоколу эмулятора терминала VT100.

Достаточно включить на PC какую либо терминальную программу и можно подключиться к плате по IP адресу указанному на её дисплее. Будет доступен просмотр лога платы, установка параметров и прочие команды.

Дополнительно в демо проекте можно выполнить и другие действия. Например отключить DHCP клиента и установить статические адреса. Можно переключить USB интерфейс с режима host в режим device, и снова сделать композитный интерфейс с классами RNDIS и CDC ACM (виртуальный COM порт), как в прошлом проекте.

По прежнему будет работать протокол FreeMaster поверх VCOM.

Некоторые замечания по организации работы со стеками:

  • Инициализация сетевого стека должна производится до инициализации USB стека. Это видно здесь. Дело в том что класс CDC ECM в Azure RTOS имеет жёсткие связи с сетевым драйвером. И если USB начнёт работать первым и сразу обнаружит Ethernet адаптер, он тут же попытается вызвать сетевой драйвер для передачи пакетов. Но поскольку сетевой стек ещё не инициализирован пакеты пойдут в пустоту и потом сетевой стек уже не подхватит интерфейс через USB.

  • При инициализации стека USB в режиме хоста нужно выделить как кэшируемую память так и некэшируемую память и достаточного объёма. Не меньше 27 КБайт на каждую.

  • Вектора прерываний USB находятся во Flash памяти и реализованы в файле App_ISRs.c. По прерыванию вызываются функции HAL. На некоторых отладочных платах от ST можно найти иную реализацию драйверов для хоста USB. Этот вариант не тестировался и там необходимо вызывать другую функцию обработчика прерываний из файла ux_hcd_stm32_interrupt_handler.c.

  • Работа DHCP клиента не быстрая и может занять до десятка секунд.

  • Нельзя конфигурировать через MPU регион памяти выделяемой стеку USB, иначе возникнут ошибки записи в память данных типа uint32_t по адресу невыровненному по границе 4 байт. По умолчанию в Cortex-M7 позволяется запись по невыровненному адресу и директива вроде __UNALIGNED_UINT32_WRITE(pDest, USBx_DFIFO(0U)); компилятором будет преобразована к простой записи одного слова в память.

Стек USB во Flash памяти микроконтроллера занял около 42 кбайт. В RAM пришлось отдать на USB около 100 кбайт. Но при этом не выполнялись никакие оптимизации.

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