В моём случае, дескриптор взят из заведомо рабочего проекта, но под другой МК (ARM от атмела, ATSAM3S). Там я писал полностью сам, без библиотек, так что в протоколе USB немного понимаю (как мне кажется).
Решил пересесть на STM, и вот такой затык.
Цитата
Далее можно просто записать все, что отправляется/принимается хостом (соот. прогой)
К сожалению, не всё. Я пробовал SniffUSB, но он начинает запись только после корректного опознания устройства, тоесть абсолютно бесполезен в моём случае.
Мой текущий дескриптор девайса выглядит так (как я уже сказал, он заведомо рабочий):
Код
static char device_descriptor[18]={
/* Standard USB device descriptor for the CDC serial driver */
sizeof(device_descriptor), // size
1, // USBGenericDescriptor_DEVICE
0x00,0x02, // USBDeviceDescriptor_USB2_00
2, // CDCDeviceDescriptor_CLASS
0, // CDCDeviceDescriptor_SUBCLASS
0, // CDCDeviceDescriptor_PROTOCOL
64, // BOARD_USB_ENDPOINTS_MAXPACKETSIZE
0xEB,0x03, // CDCDSerialDriverDescriptors_VENDORID
0x24,0x61, // CDCDSerialDriverDescriptors_PRODUCTID
0x10,0x01, // CDCDSerialDriverDescriptors_RELEASE
1, // Index of manufacturer description //0
2, // Index of product description //0
3, // Index of serial number description //0
1, // One possible configuration
};
(остальные не привожу, т.к. до них вообще дело не доходит)
Что происходит на
заведомо рабочей плате с SAM3S:
1. usb сброс
2. приходит setup пакет с запросом дескриптора девайса
3. МК отправляет дескриптор (18 байт)
4. usb сброс
5. приходит фрейм, назначающий адрес usb устройству
6. и т.д.
Что происходит с STM32F4:
не работает.
1. usb сброс
2. приходит setup пакет с запросом дескриптора девайса
3. МК отправляет дескриптор (18 байт)
4. а дальше тишина, и через 3 секунды переходим к п.1
Приблизительный код для стм32 (упрощено до безобразия
в целях отладки):
Код
volatile uint32_t * fifo=(uint32_t *)(OTG_FS_DFIFO0_BASE);
OTG_FS->DIEPTSIZ0=(1<<19)|18; // PKTCNT; XFRSIZ
OTG_FS->DIEPCTL0=(1<<31)|(1<<26); // EPENA; CNAK
*fifo=0x02000112;
*fifo=0x40000002;
*fifo=0x612403EB;
*fifo=0x02010110;
*fifo=0x00000103;
Работу с FIFO предполагаю, на основе того, что
чтение работает таким образом:
Код
volatile uint32_t * fifo=(uint32_t *)OTG_FS_DFIFO0_BASE;
int i=0;
for(i=0;i<BCNT;i+=4){
int data=*fifo;
rbuf[i+0]=(data>>0)&0xFF;
rbuf[i+1]=(data>>8)&0xFF;
rbuf[i+2]=(data>>16)&0xFF;
rbuf[i+3]=(data>>24)&0xFF;
pprintf("< %02X%02X%02X%02X", rbuf[i+0], rbuf[i+1], rbuf[i+2], rbuf[i+3]);
}
Исходя из даташита, я делаю правильно.
1. DIEPTSIZ0 должен устанавливаться до того, как поставлю EPENA в DIEPCTL0
Цитата
The application must modify this register before enabling endpoint 0. Once endpoint 0 is
enabled using the endpoint enable bit in the device control endpoint 0 control registers
(EPENA in OTG_FS_DIEPCTL0), the core modifies this register. The application can only
read this register
2. EPENA в DIEPCTL0 должен устанавливаться до того, как начну писать данные в FIFO.
Цитата
1. Program the OTG_FS_DIEPCTLx register with the endpoint characteristics and set the
CNAK and EPENA bits.
2. Write the data to be transmitted in the next frame to the transmit FIFO.
Цитата
1. The application must set the transfer size and packet count fields in the endpointspecific
registers and enable the endpoint to transmit the data.
2. The application must also write the required data to the transmit FIFO for the endpoint.
Однако,
я пробовал и другой порядок действий, безрезультатно.