Jump to content

    
Sign in to follow this  
AleksBak

Пример кода USBX CDC ACM для ThreadX

Recommended Posts

Здравствуйте!

Пожалуйста, очень прошу, если у кого есть готовый пример работы ThreadX и ее стека USBX для класса Device CDC ACM, то не могли бы поделиться. Не важно для какого-то МК. Очень хочется завести этот CDC ACM (вирт. ком-порт). Уже какое-то маниакальное желание, но все-таки. Коммерческого использования тут не планирую никакого фактически. Со своей стороны мог бы помочь как-то в программировании/консультации виртуальных очков Окулус под DirectX т.к. много этим занимался в последнее время. Спасибо.

Share this post


Link to post
Share on other sites
4 hours ago, AleksBak said:

Здравствуйте!

Пожалуйста, очень прошу, если у кого есть готовый пример работы ThreadX и ее стека USBX для класса Device CDC ACM, то не могли бы поделиться. Не важно для какого-то МК. Очень хочется завести этот CDC ACM (вирт. ком-порт). Уже какое-то маниакальное желание, но все-таки. Коммерческого использования тут не планирую никакого фактически. Со своей стороны мог бы помочь как-то в программировании/консультации виртуальных очков Окулус под DirectX т.к. много этим занимался в последнее время. Спасибо.

USB стек не такая вещь для кoторой можно кинуть простенький пример.
Нужно правильно сделать массу вещей: настроить тактировние, настроить DMA, настроить прерывания и события, выделить пул памяти правильного размера и стеки, настроить дескрипторы для FS и HS отдельно, вызывать инициализацию в правильном порядке, реализовать потоковый драйвер для уровня приложения.
Эт получается большой проект c кучей файлов и сильной привязкой к аппаратной архитектуре (и без особых объяснений) разобрать в котором будет не легче чем в мануале от   Express Logic (теперь правда уже Microsoft)
Как вы себе представляете готовый пример? Может вам просто мануал сгодится? 

Share this post


Link to post
Share on other sites
34 минуты назад, AlexandrY сказал:

USB стек не такая вещь для кoторой можно кинуть простенький пример.
Нужно правильно сделать массу вещей: настроить тактировние, настроить DMA, настроить прерывания и события, выделить пул памяти правильного размера и стеки, настроить дескрипторы для FS и HS отдельно, вызывать инициализацию в правильном порядке, реализовать потоковый драйвер для уровня приложения.
Эт получается большой проект c кучей файлов и сильной привязкой к аппаратной архитектуре (и без особых объяснений) разобрать в котором будет не легче чем в мануале от   Express Logic (теперь правда уже Microsoft)
Как вы себе представляете готовый пример? Может вам просто мануал сгодится? 

Расскажу тогда какая у меня ситуация (спасибо огромное за ответ). У меня есть 2 платы. Дома они обе. И сейчас у нас карантин продолжается (!). Уже затихает, но все равно нет программатора к одной из плат. И не понятно когда приобрету программатор. Одна плата - это 746Discovery и как Вы заметили для нее имеются примеры Azure RTOS от MS. А другая плата на STM32H743 у которого только есть разъем microUSB и могу перемычку сделать чтобы переводить его в режим DFU. Очень хочется на этой плате что-то запустить и поэтому решил именно бутлоадер на ней организовать пока что. На 746Discovery есть примеры под Device Mass Storage и Host Mass Storage. Всю возможную документацию скачал и в т.ч. на ThreadX от expresslogic . Очень понравилось качество кода (!), документация (!) и сама ОС (может это ошибочное мнение, но пока так). Даже не верится, что такое можно попробовать и использовать. MS все-таки великая компания и делает великие дела! Стал пробовать самостоятельно реализовать USB CDC тут. Но пока не получается и поэтому решил спросить. У меня на плате инициализируется 746Discovery встроенный USB PHY и т.п. Т.е. аппаратная часть имеет готовый BSP. Осталось запустить USBX правильно. Вот приведу кусок кода (извините он немного длинный):

/**************************************************************************/
/**                                                                       */
/** USBX Device Mass Storage Example for STM32F746-DISCO Board            */
/**                                                                       */
/** This example illustrates USBX working on a STM32F7xx processor        */
/**                                                                       */
/** This demo will show the device side of USBX. It will make the device  */
/** appear as a small mass storage device to a host.                      */
/**                                                                       */
/**************************************************************************/

/* Include necessary system files.  */
#include "fx_api.h"
#include "ux_api.h"
#include "ux_system.h"
#include "ux_utility.h"
#include "ux_dcd_stm32.h"
#include "ux_device_class_storage.h"
#include "ux_device_class_dfu.h"
#include "ux_device_stack.h"
#include "stm32f7xx.h"
#include "stm32f7xx_hal.h"

/* -------------------------------------- Define constants -------------------------------------- */

#define DEMO_STACK_SIZE            4096
#define USBX_MEMORY_SIZE        (32 * 1024)
#define RAM_DISK_SIZE            (8 * 1024 * 1024 - 512)
#define RAM_DISK_LAST_LBA        ((RAM_DISK_SIZE / 512) -1)

#define HOST_POWERSW_PORT        GPIOH
#define HOST_POWERSW_VBUS        GPIO_Pin_5

/* ------------------------------ Define local function prototypes ------------------------------ */

UINT demo_device_state_change(ULONG event);
VOID demo_thread_dfu_activate(VOID* dfu);
VOID demo_thread_dfu_deactivate(VOID* dfu);
UINT demo_thread_dfu_read(VOID* dfu, ULONG block_number, UCHAR* data_pointer, ULONG length,
        ULONG* media_status);
UINT demo_thread_dfu_write(VOID* dfu, ULONG block_number, UCHAR* data_pointer, ULONG length,
        ULONG* media_status);
UINT demo_thread_dfu_get_status(VOID* dfu, ULONG* media_status);
UINT demo_thread_dfu_notify(VOID* dfu, ULONG notification);

/*------------------------------------------------------------------------------------------------*/

VOID demo_thread_entry(ULONG arg);
UINT demo_thread_media_read(VOID* storage, ULONG lun, UCHAR* data_pointer, ULONG number_blocks,
        ULONG lba, ULONG* media_status);
UINT demo_thread_media_write(VOID* storage, ULONG lun, UCHAR* data_pointer, ULONG number_blocks,
        ULONG lba, ULONG* media_status);
UINT demo_thread_media_status(VOID* storage, ULONG lun, ULONG media_id, ULONG* media_status);

VOID _fx_ram_driver(FX_MEDIA* media_ptr);

void USB_OTG_BSP_HS_Init(void);
uint8_t BSP_SDRAM_Init(void);

/* ------------------------------- Define global data structures. ------------------------------- */
TX_THREAD demo_thread;
FX_MEDIA ram_disk;
CHAR* ram_disk_memory;
UX_SLAVE_CLASS_STORAGE_PARAMETER storage_parameter;
UX_SLAVE_CLASS_DFU_PARAMETER dfu_parameter;

/* Buffer for FileX RAM media initialization.  */
unsigned char buffer[512];

/*------------------------------------------------------------------------------------------------*/

#ifdef UX_API_H

#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED        50

UCHAR device_framework_full_speed[] =
{
    /* Device descriptor 18 bytes
     * 0x02 bDeviceClass: CDC class code
     * 0x00 bDeviceSubclass: CDC class sub code
     * 0x00 bDeviceProtocol: CDC Device protocol
     * idVendor & idProduct - https://www.linux-usb.org/usb.ids */
    0x12, 0x01, 0x10, 0x01,
    0xEF, 0x02, 0x01, 0x08,
    0x84, 0x84, 0x00, 0x00,
    0x00, 0x01, 0x01, 0x02,
    0x03, 0x01,

    /* Configuration 1 descriptor 9 bytes */
    0x09, 0x02, 0x4b, 0x00, 0x02, 0x01, 0x00, 0x40, 0x00,

    /* Interface association descriptor. 8 bytes. */
    0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,

    /* Communication Class Interface Descriptor Requirement. 9 bytes. */
    0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,

    /* Header Functional Descriptor 5 bytes */
    0x05, 0x24, 0x00, 0x10, 0x01,

    /* ACM Functional Descriptor 4 bytes */
    0x04, 0x24, 0x02, 0x0f,

    /* Union Functional Descriptor 5 bytes */
    0x05, 0x24, 0x06, 0x00,

    /* Master interface */
    0x01, /* Slave interface */

    /* Call Management Functional Descriptor 5 bytes */
    0x05, 0x24, 0x01, 0x03, 0x01, /* Data interface */

    /* Endpoint 1 descriptor 7 bytes */
    0x07, 0x05, 0x83, 0x03, 0x08, 0x00, 0xFF,

    /* Data Class Interface Descriptor Requirement 9 bytes */
    0x09, 0x04, 0x01, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00,

    /* First alternate setting Endpoint 1 descriptor 7 bytes*/
    0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00,

    /* Endpoint 2 descriptor 7 bytes */
    0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
};

#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED        60

UCHAR device_framework_high_speed[] =
{
    /* Device descriptor */
    0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
    0x81, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02,
    0x03, 0x01,

    /* Device qualifier descriptor */
    0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
    0x01, 0x00,

    /* Configuration descriptor */
    0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
    0x32,

    /* Interface descriptor */
    0x09, 0x04, 0x00, 0x00, 0x02, 0x08, 0x06, 0x50,
    0x00,

    /* Endpoint descriptor (Bulk In) */
    0x07, 0x05, 0x81, 0x02, 0x00, 0x01, 0x00,

    /* Endpoint descriptor (Bulk Out) */
    0x07, 0x05, 0x02, 0x02, 0x00, 0x01, 0x00
};

/* String Device Framework :
 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
 Byte 2       : Byte containing the index of the descriptor
 Byte 3       : Byte containing the length of the descriptor string
 */
#define STRING_FRAMEWORK_LENGTH                    38

UCHAR string_framework[] =
{
    /* Manufacturer string descriptor : Index 1 */
    0x09, 0x04, 0x01, 0x0c,
    0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
    0x6f, 0x67, 0x69, 0x63,

    /* Product string descriptor : Index 2 */
    0x09, 0x04, 0x02, 0x0a,
    0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x44, 0x69,
    0x73, 0x6b,

    /* Serial Number string descriptor : Index 3 */
    0x09, 0x04, 0x03, 0x04,
    0x30, 0x30, 0x30, 0x31
};

/* Multiple languages are supported on the device, to add
 a language besides english, the unicode language code must
 be appended to the language_id_framework array and the length
 adjusted accordingly. */
#define LANGUAGE_ID_FRAMEWORK_LENGTH            2

UCHAR language_id_framework[] =
        {
            /* English. */
            0x09, 0x04
        };

#endif

/*------------------------------------------------------------------------------------------------*/

VOID hardware_setup(void);

int main(int argc, char** argv)
{
    /* Setup the hardware. */
    hardware_setup();

    /* Enter the ThreadX kernel.  */
    tx_kernel_enter();
}

void tx_application_define(void* first_unused_memory)
{
    CHAR* stack_pointer;
    CHAR* memory_pointer;
    UINT status;

    /* Initialize the free memory pointer.  */
    stack_pointer = (CHAR*)first_unused_memory;

    /* Initialize the RAM disk memory. */
    memory_pointer = stack_pointer + DEMO_STACK_SIZE;

    /* Initialize USBX Memory */
    ux_system_initialize(memory_pointer, USBX_MEMORY_SIZE, UX_NULL, 0);

    /* Initialize memory address for USBX.  */
    ram_disk_memory = (CHAR*)0xC0000000;

    /* Reset it.  */
    _ux_utility_memory_set(ram_disk_memory, 0, RAM_DISK_SIZE);

    /* Initialize FileX.  */
    fx_system_initialize();

    /* The code below is required for installing the device portion of USBX.
     * In this demo, DFU is possible and we have a call back for state change.
     *
     * device_framework_high_speed           Pointer to high speed FW
     * device_framework_length_high_speed    Length of high speed FW
     * device_framework_full_speed           Pointer to full speed FW
     * device_framework_length_full_speed    Length of full speed FW
     * string_framework                      Pointer to string FW
     * string_framework_length               Length of string FW
     * language_id_framework                 Pointer to language ID FW
     * language_id_framework_length          Length of language ID FW
     * (ux_system_slave_change_function)     Pointer to callback function for device changes
     */
    status = _ux_device_stack_initialize(device_framework_high_speed,
    DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED, device_framework_full_speed,
    DEVICE_FRAMEWORK_LENGTH_FULL_SPEED, string_framework, STRING_FRAMEWORK_LENGTH,
            language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
    if (status != UX_SUCCESS)
        return;

    /* Store the number of LUN in this device storage instance.  */
    storage_parameter.ux_slave_class_storage_parameter_number_lun = 1;

    /* Initialize the storage class parameters for reading/writing to the Flash Disk.  */
    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_last_lba =
    RAM_DISK_LAST_LBA;

    storage_parameter.ux_slave_class_storage_parameter_lun[0]
            .ux_slave_class_storage_media_block_length = 512;

    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_type = 0;

    storage_parameter.ux_slave_class_storage_parameter_lun[0]
            .ux_slave_class_storage_media_removable_flag = 0x80;

    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read =
            demo_thread_media_read;
    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write =
            demo_thread_media_write;
    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =
            demo_thread_media_status;

    /* Initialize the device storage class. The class is connected with interface 0 on configuration 1. */
    status = _ux_device_stack_class_register(_ux_system_slave_class_storage_name,
            _ux_device_class_storage_entry, 1, 0, (VOID*)&storage_parameter);
    if (status != UX_SUCCESS)
        return;

    /* Create the main demo thread.  */
    tx_thread_create(&demo_thread, "tx demo", demo_thread_entry, 0, stack_pointer, DEMO_STACK_SIZE,
            20, 20, 1, TX_AUTO_START);

    return;
}

void demo_thread_entry(ULONG arg)
{
    ULONG status;

    /* Format the ram drive. */
    status = fx_media_format(&ram_disk, _fx_ram_driver, ram_disk_memory, buffer, 512, "RAM DISK", 2,
            512, 0, RAM_DISK_SIZE / 512, 512, 4, 1, 1);

    /* Check the media format status.  */
    if (status != FX_SUCCESS)
    {
        /* Error opening media.  Return to caller.  */
        return;
    }

    /* Open the ram_disk.  */
    status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, buffer, 512);

    /* Check the media open status.  */
    if (status != FX_SUCCESS)
    {
        /* Error opening media.  Return to caller.  */
        return;
    }

    /* Initialize the bsp layer of the USB OTG HS Controller.  */
    USB_OTG_BSP_HS_Init();

    tx_thread_sleep(10);

    /* Register the STM32  USB device controllers available in this system */
    status = _ux_dcd_stm32_initialize(0x40040000, 0);
}

UINT demo_thread_media_status(VOID* storage, ULONG lun, ULONG media_id, ULONG* media_status)
{
    /* The ATA drive never fails. This is just for demo only !!!! */
    return (UX_SUCCESS);
}

UINT demo_thread_media_read(VOID* storage, ULONG lun, UCHAR* data_pointer, ULONG number_blocks,
        ULONG lba, ULONG* media_status)
{
    UINT status = 0;

    while (number_blocks--)
    {
        status = fx_media_read(&ram_disk, lba, data_pointer);
        data_pointer += 512;
        lba++;
    }

    return (status);
}

UINT demo_thread_media_write(VOID* storage, ULONG lun, UCHAR* data_pointer, ULONG number_blocks,
        ULONG lba, ULONG* media_status)
{
    UINT status = 0;

    while (number_blocks--)
    {
        status = fx_media_write(&ram_disk, lba, data_pointer);
        data_pointer += 512;
        lba++;
    }

    return (status);
}

void USB_OTG_BSP_HS_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /* Configure USB FS GPIOs */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOH_CLK_ENABLE();

    /* CLK */
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* D0 */
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* D1 D2 D3 D4 D5 D6 D7 */
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11
            | GPIO_PIN_12 | GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* STP */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* NXT */
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

    /* DIR */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* Enable USB HS Clocks */
    __HAL_RCC_USB_OTG_HS_CLK_ENABLE();
    __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();

    /* Set USBHS Interrupt to the lowest priority */
    HAL_NVIC_SetPriority(OTG_HS_IRQn, 4, 0);

    /* Enable USBHS Interrupt */
    HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
}


Я стал менять тут массив UCHAR device_framework_full_speed[] чтобы он соответствовал USB CDC. А дальше уже затормозился.... Я пока отвечу т.к. по-моему слишком длинный пост уже получился и уже опасаюсь.

Edited by AleksBak

Share this post


Link to post
Share on other sites
20 minutes ago, AleksBak said:

Я стал менять тут массив UCHAR device_framework_full_speed[] чтобы он соответствовал USB CDC. А дальше уже затормозился.... Я пока отвечу т.к. по-моему слишком длинный пост уже получился и уже опасаюсь.

Да у вас проблема.
В функции tx_application_define вы зарегистрировали  класс Mass Storage ,  а вызываете функции CDC.
Функцию tx_application_define надо переделать. 

А сама ThreadX у вас в исходниках?  

Share this post


Link to post
Share on other sites

Я продолжу если можно. Выше я выложил фактически весь код основного модуля для USB Device Mass Storage. Здесь в ф. main происходит вызов такого:

int main(int argc, char** argv)
{
    /* Setup the hardware. */
    hardware_setup();

    /* Enter the ThreadX kernel.  */
    tx_kernel_enter();
}

В ф. hardware_setup() настраиваются только: MPU, CACHE, HAL_Init, Clock, SDRAM, USART1 и RNG. Далее запускается код с sheduller-ом и там и продолжается работа ОС через вызов tx_kernel_enter(). В этом цикле sheduller-а также вызывается "пользовательский" callback 

void tx_application_define(void* first_unused_memory)

из выше приведенного кода тут. Здесь уже создаем задачу работы USB устройства используя стек USBX. Вот я и хотел сделать теперь тут USB CDC Device, но пока не знаю как сделать. Документацию читаю, но не совсем понятно (не понятно совсем пока что). Если у кого есть что-то по этой теме, то очень прошу поделитесь если можно. Потом, если получится, я выложу код на гитхабе. Использую стек USBX как писал и поэтому прямо можно в его вызовах код привести (если можно и он есть). Спасибо.

1 минуту назад, AlexandrY сказал:

Да у вас проблема.
В функции tx_application_define вы зарегистрировали  класс Mass Storage ,  а вызываете функции CDC.
Функцию tx_application_define надо переделать. 

А сама ThreadX у вас в исходниках?  

Да. Как писал. MS - это величайшая компания все-таки (не устану это повторять).

5 минут назад, AlexandrY сказал:

...
В функции tx_application_define вы зарегистрировали  класс Mass Storage ,  а вызываете функции CDC.
Функцию tx_application_define надо переделать. 
...

Я этот кусок кода же взял от работающего примера USB Mass Storage и поэтому так такое.

7 минут назад, AlexandrY сказал:

...

А сама ThreadX у вас в исходниках?  

Да. Спасибо MS ! (тут версия 6.0)

Если можете - приведите кусок инициализации под USB CDC. Мне кажется Вы используете эту RTOS (ThreadX). Часть кода при чтении CDC буфера Вы приводили тут на этом отличном (не сглазить бы) форуме. И я смотрел его.

Share this post


Link to post
Share on other sites
6 hours ago, AleksBak said:

Да. Спасибо MS ! (тут версия 6.0)

Ого! Это все таки свершилось. Они выложили исходники всего ThreadX и всего промежуточного софта.
Грандиозно!

Значит инициализируется у меня так:

Spoiler

#include   "App.h"
#include   "USB_descriptors.h"
#include   "ux_device_class_rndis.h"

extern void ux_dcd_initialize(void);




#define                                          USB_POOL_MEMORY_SIZE 64000
static CHAR                                      usb_pool_memory [USB_POOL_MEMORY_SIZE];

static UX_SLAVE_CLASS_STORAGE_PARAMETER          storage_parms;
static UX_SLAVE_CLASS_CDC_ACM_PARAMETER          cdc0_parms;
static UX_SLAVE_CLASS_CDC_ACM_PARAMETER          cdc1_parms;
static UX_SLAVE_CLASS_RNDIS_PARAMETER            rndis_parms;

static uint8_t *usbd_hs_framework;
static uint8_t *usbd_fs_framework;


SSP_VECTOR_DEFINE_CHAN(dmac_int_isr, DMAC, INT, 1);
SSP_VECTOR_DEFINE_CHAN(dmac_int_isr, DMAC, INT, 0);
SSP_VECTOR_DEFINE_UNIT(usbhs_usb_int_resume_isr, USB, HS, USB_INT_RESUME, 0);
SSP_VECTOR_DEFINE_UNIT(usbfs_int_isr, USB, FS, INT, 0);


static dmac_instance_ctrl_t usb_transfer_rx_ctrl;

static transfer_info_t usb_transfer_rx_info =
{
  .dest_addr_mode      = TRANSFER_ADDR_MODE_INCREMENTED,
  .repeat_area         = TRANSFER_REPEAT_AREA_DESTINATION,
  .irq                 = TRANSFER_IRQ_EACH,
  .chain_mode          = TRANSFER_CHAIN_MODE_DISABLED,
  .src_addr_mode       = TRANSFER_ADDR_MODE_FIXED,
  .size                = TRANSFER_SIZE_1_BYTE,
  .mode                = TRANSFER_MODE_BLOCK,
  .p_dest              = (void *)NULL,
  .p_src               = (void const *)NULL,
  .num_blocks          = 0,
  .length              = 0,
};

static const transfer_on_dmac_cfg_t usb_transfer_rx_extend =
{
  .channel             = 1,
};

extern const transfer_instance_t usb_transfer_rx;

static  transfer_cfg_t usb_transfer_rx_cfg =
{
  .p_info              =&usb_transfer_rx_info,
  .activation_source   = ELC_EVENT_USBHS_FIFO_1,
  .auto_enable         = false,
  .p_callback          = NULL,
  .p_context           =&usb_transfer_rx,
  .irq_ipl             =(3),
  .p_extend            =&usb_transfer_rx_extend,
};

static const transfer_instance_t usb_transfer_rx =
{
  .p_ctrl        =&usb_transfer_rx_ctrl,
  .p_cfg         =&usb_transfer_rx_cfg,
  .p_api         =&g_transfer_on_dmac
};



static dmac_instance_ctrl_t usb_transfer_tx_ctrl;

static transfer_info_t usb_transfer_tx_info =
{
  .dest_addr_mode      = TRANSFER_ADDR_MODE_FIXED,
  .repeat_area         = TRANSFER_REPEAT_AREA_SOURCE,
  .irq                 = TRANSFER_IRQ_EACH,
  .chain_mode          = TRANSFER_CHAIN_MODE_DISABLED,
  .src_addr_mode       = TRANSFER_ADDR_MODE_INCREMENTED,
  .size                = TRANSFER_SIZE_1_BYTE,
  .mode                = TRANSFER_MODE_BLOCK,
  .p_dest              = (void *)NULL,
  .p_src               = (void const *)NULL,
  .num_blocks          = 0,
  .length              = 0,
};

static const transfer_on_dmac_cfg_t usb_transfer_tx_extend =
{
  .channel             = 0,
};

extern const transfer_instance_t usb_transfer_tx;

static  transfer_cfg_t usb_transfer_tx_cfg =
{
  .p_info              =&usb_transfer_tx_info,
  .activation_source   = ELC_EVENT_USBHS_FIFO_0,
  .auto_enable         = false,
  .p_callback          = NULL,
  .p_context           =&usb_transfer_tx,
  .irq_ipl             =(3),
  .p_extend            =&usb_transfer_tx_extend,
};

static const transfer_instance_t usb_transfer_tx =
{
  .p_ctrl        =&usb_transfer_tx_ctrl,
  .p_cfg         =&usb_transfer_tx_cfg,
  .p_api         =&g_transfer_on_dmac
};




/*-----------------------------------------------------------------------------------------------------
  
  
  \param p_instance  
  \param p_data  
-----------------------------------------------------------------------------------------------------*/
static void _USB_err_callback(void *p_instance, void *p_data)
{

}


/*-----------------------------------------------------------------------------------------------------
  Initialization function that the user can choose to have called automatically during thread entry.     
  The user can call this function at a later time if desired using the prototype below.                  
-----------------------------------------------------------------------------------------------------*/
static void _USB_common_init(void)
{
  UINT status_ux_init;

  /** Initialize the USBX system. */
  status_ux_init = ux_system_initialize((CHAR *)usb_pool_memory, USB_POOL_MEMORY_SIZE, UX_NULL, 0);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }

#ifdef UX_HOST_INITIALIZE
  /** Initialize the USBX Host stack. */
  status_ux_init =  ux_host_stack_initialize(ux_system_host_change_function);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }

  /** Register USB Host classes. */
#ifdef USB_HOST_HUB_CLASS_REGISTER
  status_ux_init =  ux_host_stack_class_register(_ux_system_host_class_hub_name, ux_host_class_hub_entry);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }
#endif

#ifdef USB_HOST_CDC_ACM_CLASS_REGISTER
  status_ux_init =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }
#endif

#ifdef USB_HOST_HID_CLASS_REGISTER
  status_ux_init =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }

  ux_host_class_hid_clients_register();
#endif

#ifdef USB_HOST_STORAGE_CLASS_REGISTER
  ux_host_stack_class_register_storage();
#endif

#ifdef USB_HOST_VIDEO_CLASS_REGISTER
  status_ux_init =  ux_host_stack_class_register(_ux_system_host_class_video_name, ux_host_class_video_entry);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }
#endif

#ifdef USB_HOST_AUDIO_CLASS_REGISTER
  status_ux_init =  ux_host_stack_class_register(_ux_system_host_class_audio_name, ux_host_class_audio_entry);
  if (UX_SUCCESS != status_ux_init)
  {
    _USB_err_callback(NULL,&status_ux_init);
  }
#endif
#endif /* UX_HOST_INITIALIZE */
}


/*-----------------------------------------------------------------------------------------------------
  
  
  
  \return ULONG 
-----------------------------------------------------------------------------------------------------*/
static ULONG _Get_string_descriptor_size(void)
{
  ULONG  size = 0;
  UCHAR   *ptr = (UCHAR *)usb_strings;
  if (NULL != ptr)
  {
    for (INT i = 0; i < 3; i++)
    {
      ptr = ptr + 3;      /* bLength at byte offset 3 */
      /* Counts bLength + Language code(2bytes) + bLength(1byte) */
      size = size +*ptr + 4;
      ptr = ptr +(*ptr)+ 1;
    }
  }
  return size;
}

/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
  
  \return uint32_t 
-----------------------------------------------------------------------------------------------------*/
uint32_t _USB_get_hs_descr_sz(void)
{
  uint32_t sz = 0;

  sz += sizeof(device_hs_descriptor);
  sz += sizeof(config_hs_descriptor);

  switch (wvar.sel_first_intf)
  {
  case FIRST_INTF_NONE:
    break;
  case FIRST_INTF_VCOM0:
    sz += sizeof(interface_cdc0_hs_descriptor);
    break;
  case FIRST_INTF_RNDIS:
    sz += sizeof(interface_rndis_hs_descriptor);
    break;
  }

  switch (wvar.sel_second_intf)
  {
  case SECOND_INTF_NONE:
    break;
  case SECOND_INTF_VCOM1:
    sz += sizeof(interface_cdc1_hs_descriptor);
    break;
  case SECOND_INTF_MSD:
    sz += sizeof(interface_msd_hs_descriptor);
    break;
  }
  return sz;
}

/*-----------------------------------------------------------------------------------------------------
  
  
  
  \return uint32_t 
-----------------------------------------------------------------------------------------------------*/
uint32_t _USB_get_fs_descr_sz(void)
{
  uint32_t sz = 0;

  sz += sizeof(device_fs_descriptor);
  sz += sizeof(config_fs_descriptor);

  switch (wvar.sel_first_intf)
  {
  case FIRST_INTF_NONE:
    break;
  case FIRST_INTF_VCOM0:
    sz += sizeof(interface_cdc0_fs_descriptor);
    break;
  case FIRST_INTF_RNDIS:
    sz += sizeof(interface_rndis_fs_descriptor);
    break;
  }


  switch (wvar.sel_second_intf)
  {
  case SECOND_INTF_NONE:
    break;
  case SECOND_INTF_VCOM1:
    sz += sizeof(interface_cdc1_fs_descriptor);
    break;
  case SECOND_INTF_MSD:
    sz += sizeof(interface_msd_fs_descriptor);
    break;
  }
  return sz;
}

/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
-----------------------------------------------------------------------------------------------------*/
void _USB_prepare_config_hs_descriptor(void)
{
  uint32_t  sz = 0;
  uint32_t  icnt = 0;


  switch (wvar.sel_first_intf)
  {
  case FIRST_INTF_NONE:
    break;
  case FIRST_INTF_VCOM0:
    sz += sizeof(interface_cdc0_hs_descriptor);
    icnt += 2;
    break;
  case FIRST_INTF_RNDIS:
    sz += sizeof(interface_rndis_hs_descriptor);
    icnt += 2;
    break;
  }

  switch (wvar.sel_second_intf)
  {
  case SECOND_INTF_NONE:
    break;
  case SECOND_INTF_VCOM1:
    sz += sizeof(interface_cdc1_hs_descriptor);
    icnt += 2;
    break;
  case SECOND_INTF_MSD:
    sz += sizeof(interface_msd_hs_descriptor);
    icnt += 1;
    break;
  }

  config_hs_descriptor.wTotalLength = sizeof(config_hs_descriptor)+ sz;
  config_hs_descriptor.bNumInterfaces = icnt;
}

/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
-----------------------------------------------------------------------------------------------------*/
void _USB_prepare_config_fs_descriptor(void)
{
  uint32_t  sz = 0;
  uint32_t  icnt = 0;

  switch (wvar.sel_first_intf)
  {
  case FIRST_INTF_NONE:
    break;
  case FIRST_INTF_VCOM0:
    sz += sizeof(interface_cdc0_fs_descriptor);
    icnt += 2;
    break;
  case FIRST_INTF_RNDIS:
    sz += sizeof(interface_rndis_fs_descriptor);
    icnt += 2;
    break;
  }


  switch (wvar.sel_second_intf)
  {
  case SECOND_INTF_NONE:
    break;
  case SECOND_INTF_VCOM1:
    sz += sizeof(interface_cdc1_fs_descriptor);
    icnt += 2;
    break;
  case SECOND_INTF_MSD:
    sz += sizeof(interface_msd_fs_descriptor);
    icnt += 1;
    break;
  }

  config_fs_descriptor.wTotalLength = sizeof(config_fs_descriptor)+ sz;
  config_fs_descriptor.bNumInterfaces = icnt;
}


/*-----------------------------------------------------------------------------------------------------
   Initialization function that the user can choose to have called automatically during thread entry.  
   The user can call this function at a later time if desired using the prototype below.               
 
-----------------------------------------------------------------------------------------------------*/
static void _USB_dev_init(void)
{

  UINT status_ux_device_init;

  /** Calculate the size of USBX String Framework. */
  ULONG string_descr_sz;
  UCHAR *p_string_descr;

  {
    p_string_descr    = (UCHAR *)usb_strings;
    string_descr_sz = _Get_string_descriptor_size();
  }

  /** Calculate the size of USB Language Framework. */
  ULONG lang_descr_sz;
  UCHAR *p_lang_descr;

  p_lang_descr  = (UCHAR *)usb_lang_descr;
  lang_descr_sz = 2;

  /** Initialize the USB Device stack. */

  uint8_t *pmem;
  uint32_t hs_descr_sz = _USB_get_hs_descr_sz();
  uint32_t fs_descr_sz = _USB_get_fs_descr_sz();


  if (wvar.en_usb_hs)
  {
    usbd_hs_framework = App_malloc_pending(hs_descr_sz, 10);
    if (usbd_hs_framework != NULL)
    {
      pmem = usbd_hs_framework;

      switch (wvar.sel_first_intf)
      {
      case FIRST_INTF_VCOM0:
        memcpy(pmem, device_hs_descriptor, sizeof(device_hs_descriptor));
        pmem = pmem + sizeof(device_hs_descriptor);
        break;
      case FIRST_INTF_RNDIS:
        memcpy(pmem, rndis_device_hs_descriptor, sizeof(rndis_device_hs_descriptor));
        pmem = pmem + sizeof(rndis_device_hs_descriptor);
        break;
      }

      _USB_prepare_config_hs_descriptor();
      memcpy(pmem,&config_hs_descriptor, sizeof(config_hs_descriptor));
      pmem = pmem + sizeof(config_hs_descriptor);


      switch (wvar.sel_first_intf)
      {
      case FIRST_INTF_NONE:
        break;
      case FIRST_INTF_VCOM0:
        memcpy(pmem, interface_cdc0_hs_descriptor, sizeof(interface_cdc0_hs_descriptor));
        pmem = pmem + sizeof(interface_cdc0_hs_descriptor);
        break;
      case FIRST_INTF_RNDIS:
        memcpy(pmem, interface_rndis_hs_descriptor, sizeof(interface_rndis_hs_descriptor));
        pmem = pmem + sizeof(interface_rndis_hs_descriptor);
        break;
      }

      switch (wvar.sel_second_intf)
      {
      case SECOND_INTF_NONE:
        break;
      case SECOND_INTF_VCOM1:
        memcpy(pmem, interface_cdc1_hs_descriptor, sizeof(interface_cdc1_hs_descriptor));
        pmem = pmem + sizeof(interface_cdc1_hs_descriptor);
        break;
      case SECOND_INTF_MSD:
        memcpy(pmem, interface_msd_hs_descriptor, sizeof(interface_msd_hs_descriptor));
        pmem = pmem + sizeof(interface_msd_hs_descriptor);
        break;
      }
    }
  }

  usbd_fs_framework = App_malloc_pending(fs_descr_sz, 10);
  if (usbd_fs_framework != NULL)
  {
    pmem = usbd_fs_framework;

    switch (wvar.sel_first_intf)
    {
    case FIRST_INTF_VCOM0:
      memcpy(pmem, device_fs_descriptor, sizeof(device_fs_descriptor));
      pmem = pmem + sizeof(device_fs_descriptor);
      break;
    case FIRST_INTF_RNDIS:
      memcpy(pmem, rndis_device_fs_descriptor, sizeof(rndis_device_fs_descriptor));
      pmem = pmem + sizeof(rndis_device_fs_descriptor);
      break;
    }

    _USB_prepare_config_fs_descriptor();
    memcpy(pmem,&config_fs_descriptor, sizeof(config_fs_descriptor));
    pmem = pmem + sizeof(config_fs_descriptor);

    switch (wvar.sel_first_intf)
    {
    case FIRST_INTF_NONE:
      break;
    case FIRST_INTF_VCOM0:
      memcpy(pmem, interface_cdc0_fs_descriptor, sizeof(interface_cdc0_fs_descriptor));
      pmem = pmem + sizeof(interface_cdc0_fs_descriptor);
      break;
    case FIRST_INTF_RNDIS:
      memcpy(pmem, interface_rndis_fs_descriptor, sizeof(interface_rndis_fs_descriptor));
      pmem = pmem + sizeof(interface_rndis_fs_descriptor);
      break;
    }

    switch (wvar.sel_second_intf)
    {
    case SECOND_INTF_NONE:
      break;
    case SECOND_INTF_VCOM1:
      memcpy(pmem, interface_cdc1_fs_descriptor, sizeof(interface_cdc1_fs_descriptor));
      pmem = pmem + sizeof(interface_cdc1_fs_descriptor);
      break;
    case SECOND_INTF_MSD:
      memcpy(pmem, interface_msd_fs_descriptor, sizeof(interface_msd_fs_descriptor));
      pmem = pmem + sizeof(interface_msd_fs_descriptor);
      break;
    }
  }

  if (wvar.en_usb_hs)
  {
    status_ux_device_init = ux_device_stack_initialize((UCHAR *)usbd_hs_framework,hs_descr_sz,
                           (UCHAR *)usbd_fs_framework,fs_descr_sz,
                           p_string_descr, string_descr_sz,
                           p_lang_descr, lang_descr_sz, UX_NULL);

  }
  else
  {
    status_ux_device_init = ux_device_stack_initialize(NULL, 0,
                           (UCHAR *)usbd_fs_framework,fs_descr_sz,
                           p_string_descr, string_descr_sz,
                           p_lang_descr, lang_descr_sz, UX_NULL);

  }

  if (UX_SUCCESS != status_ux_device_init)
  {
    _USB_err_callback(NULL,&status_ux_device_init);
  }

}


/*-----------------------------------------------------------------------------------------------------
  
  
-----------------------------------------------------------------------------------------------------*/
static void _USB_storage_setup(void)
{
  UINT status;

  /* Auto setup for a simple media storage configuration with single Logical Unit Number (LUN). */
  /* Stores the number of LUN in this device storage instance.  */
  storage_parms.ux_slave_class_storage_parameter_number_lun = 1;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_last_lba       = fat_fs_media.fx_media_total_sectors;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_block_length   = fat_fs_media.fx_media_bytes_per_sector;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_type           = 0;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_removable_flag = 0x80;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read           = ux_device_msc_media_read;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write          = ux_device_msc_media_write;
  storage_parms.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status         = ux_device_msc_media_status;

  /* Register user callback functions.  */
  storage_parms.ux_slave_class_storage_instance_activate         = NULL;
  storage_parms.ux_slave_class_storage_instance_deactivate       = NULL;
  storage_parms.ux_slave_class_storage_parameter_vendor_id       = (UCHAR *)"NULL";
  storage_parms.ux_slave_class_storage_parameter_product_id      = (UCHAR *)"NULL";
  storage_parms.ux_slave_class_storage_parameter_product_rev     = (UCHAR *)"NULL";
  storage_parms.ux_slave_class_storage_parameter_product_serial  = (UCHAR *)"NULL";

  /* Initializes the device storage class. The class is connected with interface 0 on configuration 1. */
  status =  _ux_device_stack_class_register(_ux_system_slave_class_storage_name, ux_device_class_storage_entry, 1, 0x05, (VOID *)&storage_parms);
  assert(status == UX_SUCCESS);
}

/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
-----------------------------------------------------------------------------------------------------*/
static void _USB_cdc0_setup(void)
{
  cdc0_parms.ux_slave_class_cdc_acm_instance_activate   = ux_cdc_device0_instance_activate;
  cdc0_parms.ux_slave_class_cdc_acm_instance_deactivate = ux_cdc_device0_instance_deactivate;
  /* Initializes the device cdc class. */
  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry, 1, 0x00, (VOID *)&cdc0_parms);
}

/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
-----------------------------------------------------------------------------------------------------*/
void _USB_cdc1_setup(void)
{
  cdc1_parms.ux_slave_class_cdc_acm_instance_activate   = ux_cdc_device1_instance_activate;
  cdc1_parms.ux_slave_class_cdc_acm_instance_deactivate = ux_cdc_device1_instance_deactivate;
  /* Initializes the device cdc class. */
  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry, 1, 0x02, (VOID *)&cdc1_parms);
}

/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
-----------------------------------------------------------------------------------------------------*/
void _USB_rndis_setup(void)
{
  rndis_parms.ux_slave_class_rndis_instance_activate = UX_NULL;
  rndis_parms.ux_slave_class_rndis_instance_deactivate = UX_NULL;

  rndis_parms.ux_slave_class_rndis_parameter_local_node_id[0] = 0x00;
  rndis_parms.ux_slave_class_rndis_parameter_local_node_id[1] = 0x1e;
  rndis_parms.ux_slave_class_rndis_parameter_local_node_id[2] = 0x58;
  rndis_parms.ux_slave_class_rndis_parameter_local_node_id[3] = 0x41;
  rndis_parms.ux_slave_class_rndis_parameter_local_node_id[4] = 0xb8;
  rndis_parms.ux_slave_class_rndis_parameter_local_node_id[5] = 0x78;

  rndis_parms.ux_slave_class_rndis_parameter_remote_node_id[0] = 0x00;
  rndis_parms.ux_slave_class_rndis_parameter_remote_node_id[1] = 0x1e;
  rndis_parms.ux_slave_class_rndis_parameter_remote_node_id[2] = 0x58;
  rndis_parms.ux_slave_class_rndis_parameter_remote_node_id[3] = 0x41;
  rndis_parms.ux_slave_class_rndis_parameter_remote_node_id[4] = 0xb8;
  rndis_parms.ux_slave_class_rndis_parameter_remote_node_id[5] = 0x79;

  rndis_parms.ux_slave_class_rndis_parameter_vendor_id      = 0x045B;
  rndis_parms.ux_slave_class_rndis_parameter_driver_version = 0x0003;

  ux_utility_memory_copy(rndis_parms.ux_slave_class_rndis_parameter_vendor_description,"ELOGIC RNDIS", 12);

  ux_device_stack_class_register(_ux_system_slave_class_rndis_name, ux_device_class_rndis_entry, 1, 0x00, &rndis_parms);
}
/*-----------------------------------------------------------------------------------------------------
  The definition of wrapper interface for USBX Synergy Port DCD Driver to get a transfer module instance
  
  \param dcd_io  
  
  \return UINT 
-----------------------------------------------------------------------------------------------------*/
static UINT _USB_initialize_transfer_support(ULONG dcd_io)
{
  UX_DCD_SYNERGY_TRANSFER dcd_transfer;
  dcd_transfer.ux_synergy_transfer_tx = NULL;//  (transfer_instance_t *)&usb_transfer_tx;   
  dcd_transfer.ux_synergy_transfer_rx = NULL;//  (transfer_instance_t *)&usb_transfer_rx;   
  return (UINT)ux_dcd_synergy_initialize_transfer_support(dcd_io, (UX_DCD_SYNERGY_TRANSFER *)&dcd_transfer);
}


/*-----------------------------------------------------------------------------------------------------
  Initializes the USB device controller, enabling DMA transfer if transfer module instances are given.
  
-----------------------------------------------------------------------------------------------------*/
static void ux_dcd_initialize(void)
{
  UINT status;

  if (wvar.en_usb_hs)
  {
    usb_transfer_tx_cfg.activation_source   = ELC_EVENT_USBHS_FIFO_0;
    usb_transfer_rx_cfg.activation_source  = ELC_EVENT_USBHS_FIFO_1;
    status = _USB_initialize_transfer_support(R_USBHS_BASE);
  }
  else
  {
    usb_transfer_tx_cfg.activation_source   = ELC_EVENT_USBFS_FIFO_0;
    usb_transfer_rx_cfg.activation_source  = ELC_EVENT_USBFS_FIFO_1;
    status = _USB_initialize_transfer_support(R_USBFS_BASE);
  }

  if (UX_SUCCESS != status)
  {
    _USB_err_callback(NULL,&status);
  }
}


/*-----------------------------------------------------------------------------------------------------
  
  
  \param void  
-----------------------------------------------------------------------------------------------------*/
void Init_USB_stack(void)
{

  _USB_common_init();
  _USB_dev_init();


  switch (wvar.sel_first_intf)
  {
  case FIRST_INTF_NONE:
    break;
  case FIRST_INTF_VCOM0:
    _USB_cdc0_setup();
    break;
  case FIRST_INTF_RNDIS:
    _USB_rndis_setup();
    break;
  }


  switch (wvar.sel_second_intf)
  {
  case SECOND_INTF_NONE:
    break;
  case SECOND_INTF_VCOM1:
    _USB_cdc1_setup();
    break;
  case SECOND_INTF_MSD:
    _USB_storage_setup();
    break;
  }


  /* Initializes USBX Device Control Driver */
  ux_dcd_initialize();
}

 

Для проведения всей инициализации надо вызвать функцию Init_USB_stack из первой задачи созданной в ThreadX.

Тут у меня как видите два USB интерфейса и на них я динамически меняю их назначение между CDC, RNDIS и MSD в зависимости от состояния рабочих переменных sel_first_intf и sel_second_intf

Дескрипторы объявлены так:

Spoiler

#pragma pack(1)
/*-----------------------------------------------------------------------------------------------------
  USB Device Descriptor for FS mode
-----------------------------------------------------------------------------------------------------*/
static const unsigned char rndis_device_fs_descriptor[]
= {
  0x12,                           /* 0 bLength */
  UX_DEVICE_DESCRIPTOR_ITEM,      /* 1 bDescriptorType */
  0x10,                           /* 2 bcdUSB BCD(2.0) */
  0x01,                           /* 3 bcdUSB */
  0xEF,                           /* 4 bDeviceClass    : Device Class */
  0x04,                           /* 5 bDeviceSubClass : Common Class(0x02) */
  0x01,                           /* 6 bDeviceProtocol :Interface Association Descriptor(IAD) */
  0x40,                           /* 7 bMaxPacketSize0 */
  (uint8_t)(0x045B),              /* 8 idVendor */
  (uint8_t)(0x045B >> 8),         /* 9 idVendor */
  (uint8_t)(0x0003),              /* 10 idProduct */
  (uint8_t)(0x0003 >> 8),         /* 11 idProduct */
  (uint8_t)(0x0001),              /* 12 bcdDevice */
  (uint8_t)(0x0001 >> 8),         /* 13 bcdDevice */
  1,                              /* 14 iManufacturer */
  2,                              /* 15 iProduct */
  3,                              /* 16 iSerialNumber */
  0x01,                           /* 17 bNumConfigurations */
};


typedef struct 
{
  uint8_t  bLength;
  uint8_t  bDescriptorType;
  uint16_t wTotalLength;
  uint8_t  bNumInterfaces;
  uint8_t  bConfigurationValue;
  uint8_t  iConfiguration;
  uint8_t  bmAttributes;
  uint8_t  bMaxPower;

} T_USB_config_descriptor;

/*-----------------------------------------------------------------------------------------------------
  USB Configuration Descriptor for HS mode
-----------------------------------------------------------------------------------------------------*/
static T_USB_config_descriptor config_hs_descriptor
= {
  0x09,                                            /* 0 bLength */
  UX_CONFIGURATION_DESCRIPTOR_ITEM,                /* 1 bDescriptorType */
  0,                                               /* 2 wTotalLength : This will be calculated at run-time. */
  0,                                               /* 4 bNumInterfaces */
  0x01,                                            /* 5 bConfigurationValue : Fixed to 1 since only one configuration is supported. */
  0x00,                                            /* 6 iConfiguration */
  0x80 | (0 << 6) | (0 << 5),                      /* 7 bmAttributes */
  250,                                             /* 8 bMaxPower */
};

/*-----------------------------------------------------------------------------------------------------
  USB Configuration Descriptor for FS mode
-----------------------------------------------------------------------------------------------------*/
static T_USB_config_descriptor config_fs_descriptor
= {
  0x09,                                            /* 0 bLength */
  UX_CONFIGURATION_DESCRIPTOR_ITEM,                /* 1 bDescriptorType */
  0,                                               /* 2 wTotalLength : This will be calculated at run-time. */
  0,                                               /* 4 bNumInterfaces */
  0x01,                                            /* 5 bConfigurationValue : Fixed to 1 since only one configuration is supported. */
  0x00,                                            /* 6 iConfiguration */
  0x80 | (0 << 6) | (0 << 5),                      /* 7 bmAttributes */
  250,                                             /* 8 bMaxPower */
};


/*-----------------------------------------------------------------------------------------------------
  USB Mass Storage Class Interface Descriptor for HS mode g_usb_interface_descriptor_storage_0
-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_msd_hs_descriptor[]
= {
  //.................................
  // Mass Storage Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x05, /* 2 bInterfaceNumber */ 
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#1 */
  0x08, /* 5 bInterfaceClass    : Mass Storage Class(0x8) */
  0x06, /* 6 bInterfaceSubClass : SCSI transparent command set(0x6) */
  0x50, /* 7 bInterfaceProtocol : BBB(0x50) */
  0x00, /* 8 iInterface Index */
  //.................................
  // Mass Storage Class Endpoint Descriptor (Bulk-Out)  for Interface#0x05
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 7), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize : 512bytes */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // Mass Storage Class Endpoint Descriptor (Bulk-In) for Interface#0x05
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 8), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize : 512bytes */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};


/*-----------------------------------------------------------------------------------------------------
  USB Mass Storage Class Interface Descriptor  for FS mode g_usb_interface_descriptor_storage_0
-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_msd_fs_descriptor[]
= {
  //.................................
  // Mass Storage Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x05, /* 2 bInterfaceNumber */  
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#1 */
  0x08, /* 5 bInterfaceClass    : Mass Storage Class(0x8) */
  0x06, /* 6 bInterfaceSubClass : SCSI transparent command set(0x6) */
  0x50, /* 7 bInterfaceProtocol : BBB(0x50) */
  0x00, /* 8 iInterface Index */
  //.................................
  // Mass Storage Class Endpoint Descriptor (Bulk-Out)  for Interface#0x05
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 7), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize 64bytes */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // Mass Storage Class Endpoint Descriptor (Bulk-In) for Interface#0x05
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 8), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize 64bytes */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};


/*-----------------------------------------------------------------------------------------------------
  USB CDC-ACM Interface Descriptor for HS mode g_usb_interface_desc_cdcacm_0
-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_cdc0_hs_descriptor[]
= {
  //.................................
  // Interface Association Descriptor(IAD)
  //.................................
  0x08, /* 0 bLength */
  UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bFirstInterface */
  0x02, /* 3 bInterfaceCount */
  0x02, /* 4 bFunctionClass : Communication */
  0x02, /* 5 bFunctionSubClass : Abstract Control Model */
  0x00, /* 6 bFunctionProtocol : Standard or enhanced AT Command set protocol */
  0x00, /* 7 iFunction : String descriptor index */
  //.................................
  // Communication Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x01, /* 4 bNumEndpoints      : 1 Endpoint for Interface#1 */
  0x02, /* 5 bInterfaceClass    : Communications Interface Class(0x2) */
  0x02, /* 6 bInterfaceSubClass : Abstract Control Model(0x2) */
  0x01, /* 7 bInterfaceProtocol : Common AT command(0x01) */
  0x00, /* 8 iInterface Index */
  //.................................
  // Header Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x00, /* 2 bDescriptorSubtype : Header Functional Descriptor(0x0) */
  0x10, /* 3 bcdCDC Number  0x0110 == 1.10 */
  0x01, /* 4 bcdCDC */
  //.................................
  // Abstract Control Management Functional Functional Descriptor
  //.................................
  0x04, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x02, /* 2 bDescriptorSubtype : Abstract Control Management Functional Descriptor(0x2) */
  0x06, /* 3 bmCapabilities (Supports SendBreak, GetLineCoding, SetControlLineState, GetLineCoding) */
  //.................................
  // Union Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x06, /* 2 bDescriptorSubtype : Union Functional Descriptor(0x6) */
  0x00, /* 3 bMasterInterface */
  0x01, /* 4 bSubordinateInterface0 */
  //.................................
  // Call Management Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType */
  0x01, /* 2 bDescriptorSubtype : Call Management Functional Descriptor(0x1) */
  0x03, /* 3 bmCapabilities */
  0x01, /* 4 bDataInterface */
  //.................................
  // CDC-ACM Endpoint descriptor (Interrupt) for Interface#0
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 3), /* 2 bEndpointAddress */
  UX_INTERRUPT_ENDPOINT, /* 3 bmAttributes  */
  0x08, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x0F, /* 6 bInterval */
  //.................................
  // CDC-ACM Data Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  0x01, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#0 */
  0x0A, /* 5 bInterfaceClass    : Data Interface Class(0xA) */
  0x00, /* 6 bInterfaceSubClass : Abstract Control Model */
  0x00, /* 7 bInterfaceProtocol : No class specific protocol required */
  0x00, /* 8 iInterface Index   : String descriptor index */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-Out)  for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 1), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-In) for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 2), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};

/*-----------------------------------------------------------------------------------------------------
  USB CDC-ACM Interface Descriptor for FS mode g_usb_interface_desc_cdcacm_0
-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_cdc0_fs_descriptor[]
= {
  //.................................
  // Interface Association Descriptor(IAD)                        *
  //.................................
  0x08, /* 0 bLength */
  UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bFirstInterface */
  0x02, /* 3 bInterfaceCount */
  0x02, /* 4 bFunctionClass : Communication */
  0x02, /* 5 bFunctionSubClass : Abstract Control Model */
  0x00, /* 6 bFunctionProtocol : Standard or enhanced AT Command set protocol */
  0x00, /* 7 iFunction : String descriptor index */
  //.................................
  // Communication Class Interface Descriptor                     *
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x01, /* 4 bNumEndpoints      : 1 Endpoint for Interface#1 */
  0x02, /* 5 bInterfaceClass    : Communications Interface Class(0x2) */
  0x02, /* 6 bInterfaceSubClass : Abstract Control Model(0x2) */
  0x01, /* 7 bInterfaceProtocol : Common AT command(0x01) */
  0x00, /* 8 iInterface Index */
  //.................................
  // Header Functional Descriptor                                 *
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x00, /* 2 bDescriptorSubtype : Header Functional Descriptor(0x0) */
  0x10, /* 3 bcdCDC Number  0x0110 == 1.10 */
  0x01, /* 4 bcdCDC */
  //.................................
  // Abstract Control Management Functional Functional Descriptor *
  //.................................
  0x04, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x02, /* 2 bDescriptorSubtype : Abstract Control Management Functional Descriptor(0x2) */
  0x06, /* 3 bmCapabilities (Supports SendBreak, GetLineCoding, SetControlLineState, GetLineCoding) */
  //.................................
  // Union Functional Descriptor                                  *
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x06, /* 2 bDescriptorSubtype : Union Functional Descriptor(0x6) */
  0x00, /* 3 bMasterInterface */
  0x01, /* 4 bSubordinateInterface0 */
  //.................................
  // Call Management Functional Descriptor                        *
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType */
  0x01, /* 2 bDescriptorSubtype : Call Management Functional Descriptor(0x1) */
  0x03, /* 3 bmCapabilities */
  0x01, /* 4 bDataInterface */
  //.................................
  // CDC-ACM Endpoint descriptor (Interrupt) for Interface#0      *
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 3), /* 2 bEndpointAddress */
  UX_INTERRUPT_ENDPOINT, /* 3 bmAttributes  */
  0x08, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x0F, /* 6 bInterval */
  //.................................
  // CDC-ACM Data Class Interface Descriptor                      *
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  0x01, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#0 */
  0x0A, /* 5 bInterfaceClass    : Data Interface Class(0xA) */
  0x00, /* 6 bInterfaceSubClass : Abstract Control Model */
  0x00, /* 7 bInterfaceProtocol : No class specific protocol required */
  0x00, /* 8 iInterface Index   : String descriptor index */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-Out)  for Interface#1      *
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 1), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-In) for Interface#1        *
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 2), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};


/*-----------------------------------------------------------------------------------------------------
  USB CDC-ACM Interface Descriptor for HS mode g_usb_interface_desc_cdcacm_1
-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_cdc1_hs_descriptor[]
= {
  //.................................
  // Interface Association Descriptor(IAD)
  //.................................
  0x08, /* 0 bLength */
  UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x02, /* 2 bFirstInterface */
  0x02, /* 3 bInterfaceCount */
  0x02, /* 4 bFunctionClass : Communication */
  0x02, /* 5 bFunctionSubClass : Abstract Control Model */
  0x00, /* 6 bFunctionProtocol : Standard or enhanced AT Command set protocol */
  0x00, /* 7 iFunction : String descriptor index */
  //.................................
  // Communication Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x02, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x01, /* 4 bNumEndpoints      : 1 Endpoint for Interface#1 */
  0x02, /* 5 bInterfaceClass    : Communications Interface Class(0x2) */
  0x02, /* 6 bInterfaceSubClass : Abstract Control Model(0x2) */
  0x01, /* 7 bInterfaceProtocol : Common AT command(0x01) */
  0x00, /* 8 iInterface Index */
  //.................................
  // Header Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x00, /* 2 bDescriptorSubtype : Header Functional Descriptor(0x0) */
  0x10, /* 3 bcdCDC Number  0x0110 == 1.10 */
  0x01, /* 4 bcdCDC */
  //.................................
  // Abstract Control Management Functional Functional Descriptor
  //.................................
  0x04, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x02, /* 2 bDescriptorSubtype : Abstract Control Management Functional Descriptor(0x2) */
  0x06, /* 3 bmCapabilities (Supports SendBreak, GetLineCoding, SetControlLineState, GetLineCoding) */
  //.................................
  // Union Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x06, /* 2 bDescriptorSubtype : Union Functional Descriptor(0x6) */
  0x02, /* 3 bMasterInterface */
  0x03, /* 4 bSubordinateInterface0 */
  //.................................
  // Call Management Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType */
  0x01, /* 2 bDescriptorSubtype : Call Management Functional Descriptor(0x1) */
  0x03, /* 3 bmCapabilities */
  0x03, /* 4 bDataInterface */
  //.................................
  // CDC-ACM Endpoint descriptor (Interrupt) for Interface#0
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 6), /* 2 bEndpointAddress */
  UX_INTERRUPT_ENDPOINT, /* 3 bmAttributes  */
  0x08, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x0F, /* 6 bInterval */
  //.................................
  // CDC-ACM Data Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  0x03, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#0 */
  0x0A, /* 5 bInterfaceClass    : Data Interface Class(0xA) */
  0x00, /* 6 bInterfaceSubClass : Abstract Control Model */
  0x00, /* 7 bInterfaceProtocol : No class specific protocol required */
  0x00, /* 8 iInterface Index   : String descriptor index */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-Out)  for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 4), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-In) for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 5), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};

/*-----------------------------------------------------------------------------------------------------
  USB CDC-ACM Interface Descriptor for FS mode g_usb_interface_desc_cdcacm_1
-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_cdc1_fs_descriptor[]
= {
  //.................................
  // Interface Association Descriptor(IAD)
  //.................................
  0x08, /* 0 bLength */
  UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x02, /* 2 bFirstInterface */
  0x02, /* 3 bInterfaceCount */
  0x02, /* 4 bFunctionClass : Communication */
  0x02, /* 5 bFunctionSubClass : Abstract Control Model */
  0x00, /* 6 bFunctionProtocol : Standard or enhanced AT Command set protocol */
  0x00, /* 7 iFunction : String descriptor index */
  //.................................
  // Communication Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x02, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x01, /* 4 bNumEndpoints      : 1 Endpoint for Interface#1 */
  0x02, /* 5 bInterfaceClass    : Communications Interface Class(0x2) */
  0x02, /* 6 bInterfaceSubClass : Abstract Control Model(0x2) */
  0x01, /* 7 bInterfaceProtocol : Common AT command(0x01) */
  0x00, /* 8 iInterface Index */
  //.................................
  // Header Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x00, /* 2 bDescriptorSubtype : Header Functional Descriptor(0x0) */
  0x10, /* 3 bcdCDC Number  0x0110 == 1.10 */
  0x01, /* 4 bcdCDC */
  //.................................
  // Abstract Control Management Functional Functional Descriptor *
  //.................................
  0x04, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x02, /* 2 bDescriptorSubtype : Abstract Control Management Functional Descriptor(0x2) */
  0x06, /* 3 bmCapabilities (Supports SendBreak, GetLineCoding, SetControlLineState, GetLineCoding) */
  //.................................
  // Union Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x06, /* 2 bDescriptorSubtype : Union Functional Descriptor(0x6) */
  0x02, /* 3 bMasterInterface */
  0x03, /* 4 bSubordinateInterface0 */
  //.................................
  // Call Management Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType */
  0x01, /* 2 bDescriptorSubtype : Call Management Functional Descriptor(0x1) */
  0x03, /* 3 bmCapabilities */
  0x03, /* 4 bDataInterface */
  //.................................
  // CDC-ACM Endpoint descriptor (Interrupt) for Interface#0
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 6), /* 2 bEndpointAddress */
  UX_INTERRUPT_ENDPOINT, /* 3 bmAttributes  */
  0x08, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x0F, /* 6 bInterval */
  //.................................
  // CDC-ACM Data Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  0x03, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#0 */
  0x0A, /* 5 bInterfaceClass    : Data Interface Class(0xA) */
  0x00, /* 6 bInterfaceSubClass : Abstract Control Model */
  0x00, /* 7 bInterfaceProtocol : No class specific protocol required */
  0x00, /* 8 iInterface Index   : String descriptor index */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-Out)  for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 4), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-In) for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 5), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};


/*-----------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_rndis_hs_descriptor[]
= {
  //.................................
  // Interface Association Descriptor(IAD)
  //.................................
  0x08, /* 0 bLength */
  UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bFirstInterface */
  0x02, /* 3 bInterfaceCount */
  0x02, /* 4 bFunctionClass : Communication */
  0x02, /* 5 bFunctionSubClass : Abstract Control Model */
  0x00, /* 6 bFunctionProtocol :  */
  0x00, /* 7 iFunction : String descriptor index */
  //.................................
  // Communication Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x01, /* 4 bNumEndpoints      : 1 Endpoint for Interface#1 */
  0x02, /* 5 bInterfaceClass    : Communications Interface Class(0x2) */
  0x02, /* 6 bInterfaceSubClass : Abstract Control Model(0x2) */
  0x00, /* 7 bInterfaceProtocol :  */
  0x00, /* 8 iInterface Index */
  //.................................
  // Header Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x00, /* 2 bDescriptorSubtype : Header Functional Descriptor(0x0) */
  0x10, /* 3 bcdCDC Number  0x0110 == 1.10 */
  0x01, /* 4 bcdCDC */
  //.................................
  // Abstract Control Management Functional Functional Descriptor
  //.................................
  0x04, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x02, /* 2 bDescriptorSubtype : Abstract Control Management Functional Descriptor(0x2) */
  0x00, /* 3 bmCapabilities */
  //.................................
  // Union Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x06, /* 2 bDescriptorSubtype : Union Functional Descriptor(0x6) */
  0x00, /* 3 bMasterInterface */
  0x01, /* 4 bSubordinateInterface0 */
  //.................................
  // Call Management Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType */
  0x01, /* 2 bDescriptorSubtype : Call Management Functional Descriptor(0x1) */
  0x00, /* 3 bmCapabilities */
  0x01, /* 4 bDataInterface */
  //.................................
  // CDC-ACM Endpoint descriptor (Interrupt) for Interface#0
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 3), /* 2 bEndpointAddress */
  UX_INTERRUPT_ENDPOINT, /* 3 bmAttributes  */
  0x08, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x0F, /* 6 bInterval */
  //.................................
  // CDC-ACM Data Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  0x01, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#0 */
  0x0A, /* 5 bInterfaceClass    : Data Interface Class(0xA) */
  0x00, /* 6 bInterfaceSubClass : Abstract Control Model */
  0x00, /* 7 bInterfaceProtocol : No class specific protocol required */
  0x00, /* 8 iInterface Index   : String descriptor index */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-Out)  for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 1), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-In) for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 2), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x00, /* 4 wMaxPacketSize */
  0x02, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};

/*-----------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------*/
static const unsigned char interface_rndis_fs_descriptor[]
= {
  //.................................
  // Interface Association Descriptor(IAD)
  //.................................
  0x08, /* 0 bLength */ 
  UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bFirstInterface */
  0x02, /* 3 bInterfaceCount */
  0x02, /* 4 bFunctionClass : Communication */
  0x02, /* 5 bFunctionSubClass : Abstract Control Model */
  0x00, /* 6 bFunctionProtocol : Standard or enhanced AT Command set protocol */
  0x00, /* 7 iFunction : String descriptor index */
  //.................................
  // Communication Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  0x00, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x01, /* 4 bNumEndpoints      : 1 Endpoint for Interface#1 */
  0x02, /* 5 bInterfaceClass    : Communications Interface Class(0x2) */
  0x02, /* 6 bInterfaceSubClass : Abstract Control Model(0x2) */
  0x00, /* 7 bInterfaceProtocol :  */
  0x00, /* 8 iInterface Index */
  //.................................
  // Header Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x00, /* 2 bDescriptorSubtype : Header Functional Descriptor(0x0) */
  0x10, /* 3 bcdCDC Number  0x0110 == 1.10 */
  0x01, /* 4 bcdCDC */
  //.................................
  // Abstract Control Management Functional Functional Descriptor
  //.................................
  0x04, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x02, /* 2 bDescriptorSubtype : Abstract Control Management Functional Descriptor(0x2) */
  0x00, /* 3 bmCapabilities */
  //.................................
  // Union Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType : CS_INTERFACE(24h) */
  0x06, /* 2 bDescriptorSubtype : Union Functional Descriptor(0x6) */
  0x00, /* 3 bMasterInterface */
  0x01, /* 4 bSubordinateInterface0 */
  //.................................
  // Call Management Functional Descriptor
  //.................................
  0x05, /* 0 bFunctionLength */
  0x24, /* 1 bDescriptorType */
  0x01, /* 2 bDescriptorSubtype : Call Management Functional Descriptor(0x1) */
  0x00, /* 3 bmCapabilities */
  0x01, /* 4 bDataInterface */
  //.................................
  // CDC-ACM Endpoint descriptor (Interrupt) for Interface#0
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 3), /* 2 bEndpointAddress */
  UX_INTERRUPT_ENDPOINT, /* 3 bmAttributes  */
  0x08, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x0F, /* 6 bInterval */
  //.................................
  // CDC-ACM Data Class Interface Descriptor
  //.................................
  0x09, /* 0 bLength */
  UX_INTERFACE_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  0x01, /* 2 bInterfaceNumber */
  0x00, /* 3 bAlternateSetting  : Alternate for SetInterface Request */
  0x02, /* 4 bNumEndpoints      : 2 Endpoints for Interface#0 */
  0x0A, /* 5 bInterfaceClass    : Data Interface Class(0xA) */
  0x00, /* 6 bInterfaceSubClass : Abstract Control Model */
  0x00, /* 7 bInterfaceProtocol : No class specific protocol required */
  0x00, /* 8 iInterface Index   : String descriptor index */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-Out)  for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM,  /* 1 bDescriptorType */
  (UX_ENDPOINT_OUT | 1), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
  //.................................
  // CDC-ACM Endpoint Descriptor (Bulk-In) for Interface#1
  //.................................
  0x07, /* 0 bLength */
  UX_ENDPOINT_DESCRIPTOR_ITEM, /* 1 bDescriptorType */
  (UX_ENDPOINT_IN | 2), /* 2 bEndpointAddress */
  UX_BULK_ENDPOINT, /* 3 bmAttributes  */
  0x40, /* 4 wMaxPacketSize */
  0x00, /* 5 wMaxPacketSize */
  0x00, /* 6 bInterval */
};

/*-----------------------------------------------------------------------------------------------------


-----------------------------------------------------------------------------------------------------*/
static volatile const UCHAR usb_lang_descr[] =
{
  (uint8_t)(0x0409),     /* Supported Language Code */
  (uint8_t)(0x0409 >> 8) /* US English as the default */
};


// Строки использумые дескриптором USB устройства
//  String Device Framework:
// Byte 0 and 1: Word containing the language ID: 0x0904 for US
// Byte 2 : Byte containing the index of the descriptor
// Byte 3 : Byte containing the length of the descriptor string
//
static UCHAR usb_strings[]=
{
  /* Manufacturer string descriptor: Index 1 */
  0x09,0x04,
  0x01,
  0x03,
  '*',
  '*',
  '*',

  /* Product string descriptor: Index 2 */
  // Выводится в окне устройств
  0x09,0x04,
  0x02,
  0x05,
  '*',
  '*',
  '*',
  '*',
  '*',


  /* Serial Number string descriptor: Index 3 */
  0x09,0x04,
  0x03,
  0x03,
  '*',
  '*',
  '*'

};
#pragma pack()

 

Поскольку я работаю с ThreadX используя HAL называемый Synergy, то в исходниках можете встретить типы заднные в этом HAL.
У вас на STM используется другой HAL, как понимаю, Cube.
Тут будет трудность перевести с одного HAL на другой.
    
 

Share this post


Link to post
Share on other sites
4 часа назад, AlexandrY сказал:

Ого! Это все таки свершилось. Они выложили исходники всего ThreadX и всего промежуточного софта.
Грандиозно!

...

Поскольку я работаю с ThreadX используя HAL называемый Synergy, то в исходниках можете встретить типы заднные в этом HAL.
У вас на STM используется другой HAL, как понимаю, Cube.
Тут будет трудность перевести с одного HAL на другой.
    
 

Да выложили (повторюсь еще раз) и стиль написания кода, и документация (в стиле MS!), также впечатляют! Спасибо Вам большое и очень благодарен за то что выложили столько кода и начну разбираться тогда (Synergy - это Renesas? Тоже смотрел в нете именно по этим контроллерам - и так и не нашел ничего тут т.к. как я понял у них проприетарный софт - вот это и это макс. что нашел).

Share this post


Link to post
Share on other sites
2 minutes ago, AleksBak said:

Synergy - это Renesas? Тоже смотрел в нете именно по этим контроллерам - и так и не нашел ничего тут т.к. как я понял у них проприетарный софт - вот это и это макс. что нашел

Synergy - это вот это https://www.renesas.com/us/en/products/synergy/software/ssp.html
Они дают его бесплатно с компилятором IAR . Он там в общем пакете находится. 
Проблема только в том что исходники самой ThreadX зашифрованы, но спец. версия IAR умеет компилить зашифрованные исходники.
При отладке исходники видны в открытом виде. Так что проблем отладки не возникает. 
Но теперь когда все исходники открыты все меняется в лучшую сторону. 
В принципе CubeMX тож вариант, но Synergy более адаптирован и теснее связан с ThreadX.
 

Share this post


Link to post
Share on other sites

Добрый день!

Решил я еще попробовать спросить тут т.к. не хватает у меня пока что знаний и не получается тут. Еще раз благодарен AlexandrY за помощь! (аккурат на ДР она мне была (!) - хоть какой-то подарок был и так получилось). С того времени я сделал кое-какой проект работы CDC-ACM на Azure RTOS и все разбирался пытаясь его сделать работоспособным. Изначально пока что на плате STM32F746-Discovery отлаживаю проект т.к. она максимально удобно приспособлена для этого. Также хочу запустить CDC-ACM на HS (через м/с USB HS ULPI). Разницы нет особой, но тут так. Проект, все компоненты Azure RTOS, а также др. демонстрационные примеры (рабочие) от Майкрософт я выложил на github. Также, там, в директории 'docs' собрал по максимуму всевозможную документацию для Azure RTOS и ее компонентов. Документация неплохая. Сам неработающий проект находится там же под названием 'sample_usbx_device_cdc_acm'. Точнее он уже наполовину работоспособен, но есть еще проблемы:

- устройство CDC нормально определяется в системе и проходит энумерацию, но работает только "в одну сторону" :) На EndPoint OUT (выход с хоста - ПК) нет реакции в коде устройства (Device). Я пока искал эту реакцию на более высоком уровне (модуль '_ux_dcd_stm32_transfer_callback') и там 3 части есть: обработка командных пакетов на EP0 (первый if) и обработка data-пакетов EP OUT и IN (внутри else соотв. первому if). Я могу попробовать приводить ссылки на куски кода, там в гитхаб, здесь, если будет нужно, но пока не знаю как это делать. Там еще README.md не дописал до конца.

Т.е. устройство отправляет пакеты на ПК (виртуальный COM порт), а обратно с ПК ничего не получает. Я перепробовал множество вариантов. Изучаю шину USB, но покамест только новичок там.  В конце-концов пришел к выводу, что "чистый" Composite CDC Device тут работоспособен (когда есть IAD дескриптор). Мне непонятно как выбираются адреса у конечных точек канала данных?? Их можно назначать какие хочешь из диапазона 0-32 и чтобы не было конфликтов с другими - это понятно. Эти адреса прописываем в соотв. дескрипторах конечных точек и теперь хост (ПК тут) уже "знает" какая точка для чего. Но почему тогда только определенные номера адресов тут работают? Т.е. если поменять адрес точки EP IN сейчас, там в этом примере, на другой и прописать в ее дескрипторе, то уже не будут приходить пакеты с нашего девайса на ПК (хост) как сейчас! Получается, что только строго определенные адреса можно прописывать этим точкам? Так? И драйвер на ПК работает только через них. А как узнать какие именно эти адреса? Случайно обнаружил, что с таким как сейчас адресом EP IN работает и ПК получает пакеты от устройства. А обратно нет их.

Еще, хочу отметить, что другой пример там - sample_usbx_device_mass_storage (уже от Майкрософт) рабочий и все четко в нем работает (инициализация и пр. точно такое же), а это означает, что сама библиотека USBX (проект 'ux' там) функционирует и вроде дело не в ней.

Извините, что много написал - пока закончу свой длинный пост и отправлю его. Если есть еще какие дополнительные вопросы, то отвечу конечно. Продолжаю отлаживать код и искать решение проблемы, но не удержался и решил спросить у знающих людей. Спасибо.

Share this post


Link to post
Share on other sites
4 hours ago, AleksBak said:

Мне непонятно как выбираются адреса у конечных точек канала данных?? Их можно назначать какие хочешь из диапазона 0-32 и чтобы не было конфликтов с другими - это понятно. Эти адреса прописываем в соотв. дескрипторах конечных точек и теперь хост (ПК тут) уже "знает" какая точка для чего. Но почему тогда только определенные номера адресов тут работают?

У STM32F746NG есть всего 8 конечных точек. Поэтому можно назначть только из диапазона 1-7 у HS интерфейса и 1-5 у FS интерфейса (0- всегда занята)

Надо помнить, что CDC-ACM требует 3-и конечные точки для своей реализации и 2-а интерфейса. В одном 1-а точка в другом две. 
Все надо правильно назначить.  Какая interrupt, какая на вход, какая на выход...
Я выбирал в Azure RTOS достаточно произвольно конечные точки из доступных и не заметил проблем.
 
 

Share this post


Link to post
Share on other sites
19 часов назад, AlexandrY сказал:

У STM32F746NG есть всего 8 конечных точек. Поэтому можно назначть только из диапазона 1-7 у HS интерфейса и 1-5 у FS интерфейса (0- всегда занята)

Я покамест подробно не изучал регистры и пр. связанные с USB тут, в этом контроллере. Но думаю это пока что. Спасибо за информацию. Скажите, а у Вас имеется такая плата (STM32F746-DISCO) или что-то похожее?

Я вот такие дескрипторы использовал тут:

Скрытый текст

#define USB_CLASS_MISCELLANEOUS             0xEF
#define USB_CDC_ACM_SUBCLASS                0x02
#define USB_CDC_AT_COMMAND_PROTOCOL         0x01
#define USB_CLASS_CDC_DATA                  0x0A
#define USB_DESCTYPE_CS_INTERFACE           0x24

UCHAR device_framework_high_speed[] =
{
    /* Device Descriptor (must be first in this array) */
    0x12,                                       /* 0 bLength */
    UX_DEVICE_DESCRIPTOR_ITEM,                  /* 1 bDescriptorType     : Device Descriptor */
    0x00,                                       /* 2 bcdUSB */
    0x02,                                       /* 3 bcdUSB */
    USB_CLASS_MISCELLANEOUS,                    /* 4 bDeviceClass        : if there 3 bytes one by one are equal */
    0x02,                                       /* 5 bDeviceSubClass     : to 0xEF, 0x02 and 0x01,  */
    0x01,                                       /* 6 bDeviceProtocol     : then here Composite Device with IAD (see below) */
    0x40,                                       /* 7 bMaxPacketSize0     : (only 8, 16, 32, or 64 are valid) */
    LOBYTE(USBD_VID),                           /* 8 idVendor */
    HIBYTE(USBD_VID),                           /* 9 idVendor */
    LOBYTE(USBD_PID),                           /* 10 idProduct */
    HIBYTE(USBD_PID),                           /* 11 idProduct */
    LOBYTE(USBD_DEV),                           /* 12 bcdDevice */
    HIBYTE(USBD_DEV),                           /* 13 bcdDevice */
    0x01,                                       /* 14 iManufacturer      : Index of Manufacturer string (String Descriptor 1) */
    0x02,                                       /* 15 iProduct           : Index of Product string (String Descriptor 2) */
    0x03,                                       /* 16 iSerialNumber      : Index of Serial Number string (String Descriptor 3) */
    0x01,                                       /* 17 bNumConfigurations : 1 Configuration used */

    /* Device Qualifier Descriptor (describes information about a high-speed capable device that
     * would change if the device were operating at the other speed) */
    0x0A,                                       /* 0 bLength */
    UX_DEVICE_QUALIFIER_DESCRIPTOR_ITEM,        /* 1 bDescriptorType */
    0x00,                                       /* 2 bcdUSB              : 0x0200 (must be at least 2.0) */
    0x02,                                       /* 3 bcdUSB */
    USB_CLASS_COMMUNICATIONS,                   /* 4 bDeviceClass        : Device Class */
    0x00,                                       /* 5 bDeviceSubClass     : none */
    0x00,                                       /* 6 bDeviceProtocol     : none */
    0x40,                                       /* 7 bMaxPacketSize      : size for other speed*/
    0x01,                                       /* 8 bNumConfigs         : 1 (number of Other-speed Configurations) */
    0x00,                                       /* 9 bReserved           : 0 (must be zero) */

    /*--------------------------------------------------------------------------------------------*/

    /* Configuration Descriptor */
    0x09,                                       /* 0 bLength */
    UX_CONFIGURATION_DESCRIPTOR_ITEM,           /* 1 bDescriptorType     : Configuration Descriptor */
    0x4B,                                       /* 2 wTotalLength        : This will be calculated at run-time. (0x4B) */
    0x00,                                       /* 3 wTotalLength        : This will be calculated at run-time. */
    0x02,                                       /* 4 bNumInterfaces      : 2 Interfaces used */
    0x01,                                       /* 5 bConfigurationValue : Configuration 1 */
    0x00,                                       /* 6 iConfiguration      : No String Descriptor */
    0x80 | (1 << 6) | (0 << 5),                 /* 7 bmAttributes        : D7-Reserved, set 1; D6-Self Powered; D5-Remote Wakeup; D4..0-Reserved, set 0 */
    0x32,                                       /* 8 bMaxPower           : 0x32 = 100 mA, 0xFA = 500 mA */

    /* Interface Association Descriptor (IAD) (should be declared before the Interfaces and contain
     * the first interface of the CDC-ACM class and how many interfaces are attached) */
    0x08,                                       /* 0 bLength */
    UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM,   /* 1 bDescriptorType     : */
    INTERF_COM_NUM,                             /* 2 bFirstInterface     : */
    0x02,                                       /* 3 bInterfaceCount     : */
    0x02,                                       /* 4 bFunctionClass      : Communications and CDC Control */
    0x02,                                       /* 5 bFunctionSubClass   : Abstract Control Model */
    0x01,                                       /* 6 bFunctionProtocol   : Standard or enhanced AT Command set protocol */
    0x00,                                       /* 7 iFunction           : No String Descriptor */

    /*--------------------------------------------------------------------------------------------*/

    /* Header Functional Descriptor */
    0x05,                                       /* 0 bFunctionLength */
    USB_DESCTYPE_CS_INTERFACE,                  /* 1 bDescriptorType        : CS_INTERFACE */
    0x00,                                       /* 2 bDescriptorSubtype     : HEADER (0x00) */
    0x10,                                       /* 3 bcdCDC                 : CDC Version 1.10 */
    0x01,                                       /* 4 bcdCDC */

    /* Call Management Functional Descriptor */
    0x05,                                       /* 0 bFunctionLength */
    USB_DESCTYPE_CS_INTERFACE,                  /* 1 bDescriptorType        : CS_INTERFACE */
    0x01,                                       /* 2 bDescriptorSubtype     : CALL MANAGEMENT (0x01) */
    0x00,                               /*0x03*//* 3 bmCapabilities */
    INTERF_DAT_NUM,                             /* 4 bDataInterface */

    /* Abstract Control Management (ACM) Functional Descriptor */
    0x04,                                       /* 0 bFunctionLength */
    USB_DESCTYPE_CS_INTERFACE,                  /* 1 bDescriptorType        : CS_INTERFACE */
    0x02,                                       /* 2 bDescriptorSubtype     : ABSTRACT CONTROL MANAGEMENT (0x02) */
    0x02,                                       /* 3 bmCapabilities         : Supports subset of ACM commands:
                    D7..4	: 0x00 (Reserved)
                    D3		: 0x00 (not supports the notification Network_Connection)
                    D2		: 0x00 (not supports the request Send_Break)
                    D1		: 0x01 (supports the request combination of Set_Line_Coding,
                              Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State)
                    D0		: 0x00 (not supports the request combination of Set_Comm_Feature,
                              Clear_Comm_Feature, and Get_Comm_Feature) */

    /* Union Functional Descriptor */
    0x05,                                       /* 0 bFunctionLength */
    USB_DESCTYPE_CS_INTERFACE,                  /* 1 bDescriptorType        : CS_INTERFACE */
    0x06,                                       /* 2 bDescriptorSubtype     : UNION (0x06) */
    INTERF_COM_NUM,                             /* 3 bControlInterface      : Interface 0 */
    INTERF_DAT_NUM,                             /* 4 bSubordinateInterface0 : Interface 1 */

    /*--------------------------------------------------------------------------------------------*/

    /* Command Interface Descriptor */
    0x09,                                       /* 0 bLength */
    UX_INTERFACE_DESCRIPTOR_ITEM,               /* 1 bDescriptorType     : Interface Descriptor */
    INTERF_COM_NUM,                             /* 2 bInterfaceNumber    : Index of this Interface */
    0x00,                                       /* 3 bAlternateSetting   : No alternate for 'SET INTERFACE' Request */
    0x01,                                       /* 4 bNumEndpoints       : 1 Endpoint for this Command Interface */
    USB_CLASS_COMMUNICATIONS,                   /* 5 bInterfaceClass     : Communications and CDC Control (0x02) */
    USB_CDC_ACM_SUBCLASS,                       /* 6 bInterfaceSubClass  : Abstract Control Model (0x02) */
    USB_CDC_AT_COMMAND_PROTOCOL,                /* 7 bInterfaceProtocol  : AT Commands defined by ITU-T V.250 etc (0x01) */
    0x00,                                       /* 8 iInterface Index    : No string descriptor */

    /* Command Endpoint Descriptor */
    0x07,                                       /* 0 bLength */
    UX_ENDPOINT_DESCRIPTOR_ITEM,                /* 1 bDescriptorType     : Endpoint Descriptor */
    (UX_ENDPOINT_IN | 3),                       /* 2 bEndpointAddress    : IN EP address for CDC commands (3 or 2) */
    UX_INTERRUPT_ENDPOINT,                      /* 3 bmAttributes        : EP type is Interrupt */
    LOBYTE(CDC_CMD_PACKET_SIZE),                /* 4 wMaxPacketSize */
    HIBYTE(CDC_CMD_PACKET_SIZE),                /* 5 wMaxPacketSize */
    CDC_HS_BINTERVAL,                           /* 6 bInterval           : */

    /* Data Interface Descriptor */
    0x09,                                       /* 0 bLength */
    UX_INTERFACE_DESCRIPTOR_ITEM,               /* 1 bDescriptorType     : Interface Descriptor */
    INTERF_DAT_NUM,								/* 2 bInterfaceNumber    : Index of this Interface */
    0x00,                                       /* 3 bAlternateSetting   : No alternate for 'SET INTERFACE' Request */
    0x02,                                       /* 4 bNumEndpoints       : 2 Endpoints for this Data Interface */
    USB_CLASS_CDC_DATA,                         /* 5 bInterfaceClass     : Data Interface Class (0x0A) */
    0x00,                                       /* 6 bInterfaceSubClass  : No class specific subclass required */
    0x00,                                       /* 7 bInterfaceProtocol  : No class specific protocol required */
    0x00,                                       /* 8 iInterface Index    : No string descriptor */

    /* Data Endpoint Descriptor (IN) */
    0x07,                                       /* 0 bLength */
    UX_ENDPOINT_DESCRIPTOR_ITEM,                /* 1 bDescriptorType     : Endpoint Descriptor */
    (UX_ENDPOINT_IN | 1),                       /* 2 bEndpointAddress    : EP address for Data IN (1) */
    UX_BULK_ENDPOINT,                           /* 3 bmAttributes        : EP type is Bulk */
    LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),        /* 4 wMaxPacketSize */
    HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),        /* 5 wMaxPacketSize */
    0x00,                                       /* 6 bInterval           : never NAKs */

    /* Data Endpoint Descriptor (OUT) */
    0x07,                                       /* 0 bLength: Endpoint Descriptor size */
    UX_ENDPOINT_DESCRIPTOR_ITEM,                /* 1 bDescriptorType     : Endpoint Descriptor */
    (UX_ENDPOINT_OUT | 2),                      /* 2 bEndpointAddress    : EP address for Data OUT (2 or 1) */
    UX_BULK_ENDPOINT,                           /* 3 bmAttributes        : EP type is Bulk */
    LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),        /* 4 wMaxPacketSize */
    HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),        /* 5 wMaxPacketSize */
    0x00,                                       /* 6 bInterval           : never NAKs */
};

 

При таких дескрипторах у меня сейчас работает только на передачу от девайса. А вот то что хост шлет на девайс - не доходит до него (смотрел в отладчике внутри функции '_ux_dcd_stm32_transfer_callback'). А если я поменяю в предпоследнем (EP DATA IN) или последнем (EP DATA OUT) дескрипторах поля 'bEndpointAddress' на какие-то другие значения, то либо вообще перестает принимать что-то и  уже хост теперь, либо никакого толку нет. Т.е. только такая "комбинация" адресов сейчас работает и то только в одну сторону. Я вот Вас уверяю оно так! И если есть возможность/желание, то можете проверить и убедиться в этом! Может быть драйвер (usbser.sys кажется наз.) так тут работает (не со всеми адресами) - я не знаю и поэтому спросил. Сам даже в недоумении.

При этом та же самая библиотека USBX работает нормально работает с примером USB Mass Storage как писал я.

Наверно у Вас другой контроллер используется с этой библиотекой. Но вот покамест буду надеяться, что нет. В любом случае благодарен за пояснения и помощь.

Вообще - что такое Azure RTOS хотелось пояснить тем кто не знает. Это бывшая проприетарная ThreadX которую недавно приобрела вместе с ее компанией expresslogic Майкрософт и выложила все ее коды/документацию в открытый доступ. Согласно информации эта RTOS работает на 1.5 миллиард девайсов в мире. Тут есть GUI, USB, TCP/IP стеки. Также есть софт для работы с GUI виджетами на ПК (предварительная сборка). Если кому-то интересно, то можете попробовать/посмотреть. Может кто-то сможет проверить заодно и этот нерабочий пример и пояснить/подсказать что там не так.

Edited by AleksBak
код сделал "сворачиваемым"

Share this post


Link to post
Share on other sites
9 hours ago, AleksBak said:

Я вот такие дескрипторы использовал тут (заранее извиняюсь если получится опять "простыня" кода, но я вроде использую теги что надо. А можно пред. "простыню" как-то удалить/сжать?):

Скрывают код в постах с помощью пиктограмки Spoiler - image.png.54e73c9185a1f131210eaeeb55df10ed.png

Посмотрел ваши дескрипторы и ошибок не нашел.
А так у Microsoft-а есть утилита USB Device Viewer
image.thumb.png.0a3654f6053a2c701b21cc4a977049db.png

Она показывает все траблы с дескрипторами у дивайсов.
Причем винда довольно толерантна к неточностям дескрипторов. 

Я больше склоняюсь к версии что у вас неправильно настроен DMA из USB конечной точки.
Проверить не могу. С STM32 сейчас не работаю. 

 

Share this post


Link to post
Share on other sites

Спасибо. Я ее использую тоже и смотрю по ней свои дескрипторы. Она у MS кажется в виде исходников только (USB View), а готовые утилиты в нете от тех кто скомпилировал. У меня один из ее аналогов:

701512930_DesktopScreenshot2020_07.27-15_17_32.28cut.thumb.png.736a06adfd748b005c36166db5a8219f.png

4 часа назад, AlexandrY сказал:

Я больше склоняюсь к версии что у вас неправильно настроен DMA из USB конечной точки.

Но ведь майкрософтский пример USB Mass Storage работоспособен в "обе стороны" с набортной памятью 8МБайт на STM32F746-Discovery (где-то под 15-20 Мбайт в секунду вроде примерно дает, но на плате всего 8МБайт как писал). И использует точно такие же настройки и инициализацию контроллера/периферии (на скорости HS) и ту же самую либу USBX. Проблема в этом. Но я посмотрю и попытаюсь разобраться - спасибо.

Share this post


Link to post
Share on other sites

Работает сейчас. Также помогли программисты из Azure RTOS (бывшая ThreadX). Один из них - Scott Larson (Azure IoT Senior Engineer). На гитхаб выложил готовый пример. Оказывается ошибка в том, что инициализацию (девайса, его класса и USB стека задачи) надо делать в одной задаче, что и работа. Это пока предварительные наблюдения и выводы. Я пока продолжаю изучать эту ОС и решил поделиться тут.

Вообще, почему решил ее изучить: 1) ОС считается очень распространенной (бывшая ThreadX и она работает на более 1.5 миллиарда устройств); 2) открытый (!) исходный код; 3) практически весь "набор" сопутствующих библиотек (TCP/IP, USB, GUI, файловая система); 4) есть неплохая GUI и средства на ПК для моделирования виджетов; 5) есть трассировщик на ПК; 6) очень слабая зависимость (!) от Cube HAL (мизерная и легко от нее избавиться совсем); 7) очень неплохая документация и комментарии в коде (!); 8) COVID-19.

 

Share this post


Link to post
Share on other sites
On 6/16/2020 at 6:42 AM, AlexandrY said:

Ого! Это все таки свершилось. Они выложили исходники всего ThreadX и всего промежуточного софта.
Грандиозно!

Ага. И на хабре появилась статья для новичков в RTOS. Т.е. и для меня :) Давно искал хорошую RTOS и чтобы можно было железку в кубике настраивать

https://habr.com/ru/company/quarta/blog/514084/

Почитал, за выходные набросал изменения примера для другой платы дисковери, за неделю по вечерам разобрался с непонятками. Мну понравилось. :yes:

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this