Open VaZso opened 5 years ago
What length parameter do you use USBD_CDC_Receive()
with? Try using 64. If the host sends data with size that is the multiple of the max packet size of the endpoint (64), and the length is larger, the shorter than expected data will sit in the buffer until the host sends more.
Otherwise, if the USB interrupt doesn't fire at all when the host is sending data, there must be another problem. Only in this case, I have no idea what it could be. Honestly I never tried an F1 device yet, so it may be that there are differences in its USB IP and that of the later series, such as F3.
Basically, I call USBD_CDC_Receive function with the length of USBD_CDC_AppType .Received callback was called. Initially it is 64. Setting it to fixed 64 does not change the behaviour.
I think if I send data several times, a received message should appear anyway.
However, I have looked it again now and I see an interrupt when I send data from host to device (sorry, maybe it was too late yesterday when I have tried it).
So, in USB_vIRQHandler, the
if ((usEpReg & USB_EP_CTR_RX) != 0)
is true, then
if ((usEpReg & USB_EP_SETUP) != 0)
is also true, so it handles a SETUP Packet with usEpId value of 0. Should I do something at EP0?
It is interesting... currently when microcontroller restarts and USB is plugged in first time, I can not see any interrupt when trying to send data from host to device and host also can not read some data of the device, for example:
bcdDevice 1.00
iManufacturer 16 (error)
iProduct 32 (error)
iSerial 48 (error)
When I keep powering the MCU and reconnect USB cable, interrupts are starting to arrive like above (SETUP packages) and iManufacturer, iProduct, iSerial (and so on) are displayed correctly.
Tell me about the 1.5kOhm pullup on USB_DP line, how did you implement it? Is it hardwired to 3.3V, or to a GPIO that you control via the ConnectCtrl
callback?
The STM32F4 board was designed by me, but this one is not.
It is a really cheap "Minimum System Development Board" from China. This one
USB_DP line is hardwired to 3.3V in this case.
In that case I recommend that you pull the DP and DM lines to ground as output pins for 1ms at startup, then reconfigure them into USB alternate function mode once the USB stack is initialized. This is necessary so the host detects the device attach-detach, and restarts the communication.
Done that. Host detects the reset of the board and restarts communication.
After restart, I can use USB device to send data from device to host. Sending data from host to device seems to do nothing.
If I unplug USB and plug it again while uC is still running, I can also send data from device to host and if I try to send data from host to device, a SETUP Packet arrives described above.
I don't have an F1 device, so I cannot test your scenario, you are on your own now. Perhaps you could try with a Cube example to compare the behavior.
Do you have a board which has "USB_Device" instead of "USB_OTG" interface?
If so, on that board, do both send and receive directions work on USB-CDC virtual communication port?
I am afraid I would need deeper knowledge of USB protocol in order to find out what is wrong and why data from host to device doesn't arrive and what to do with the SETUP request coming instead of my data.
Anyway, some debugging of USB communication at host side...
Sending data from device to host:
ffff9d07429f6480 2566553931 C Bi:5:030:1 0 1 = 53 ffff9d07429f6480 2566553954 S Bi:5:030:1 -115 128 < ffff9d07429f6900 2566553965 C Bi:5:030:1 0 3 = 6f7220 ffff9d07429f6900 2566553968 S Bi:5:030:1 -115 128 < ffff9d07429f6240 2566553971 C Bi:5:030:1 0 7 = 28323330 290d0a ffff9d07429f6240 2566553972 S Bi:5:030:1 -115 128 <
The message was "Sor (230)\n", which is in hex 53 6f 72 20 28 32 33 30 29 0d 0a
Sending data from host to device:
ffff9d077e343600 2421470733 S Co:5:030:0 s 21 22 0003 0000 0000 0 ffff9d07429f6480 2421470828 C Bi:5:030:1 0 1 = 49 ffff9d07429f6480 2421470833 S Bi:5:030:1 -115 128 < ffff9d077e343600 2421470992 C Co:5:030:0 0 0 ffff9d07429f6900 2421471002 C Bi:5:030:1 0 23 = 52510d0a 53455455 50202d20 75734570 49643a20 300d0a ffff9d07429f6900 2421471008 S Bi:5:030:1 -115 128 < ffff9d07bf4c6300 2421471098 S Bo:5:030:1 -115 6 = 5465737a 740a ffff9d07bf4c6300 2421471166 C Bo:5:030:1 -32 0
The message was "Teszt\n" which is in hex 54 65 73 7a 74 0a
So, these data going through the bus between host and device.
Still, on device, I only see an interrupt coming which ends up as a SETUP Packet with usEpId value of 0 when I send "Teszt\n" to device.
I have two shared projects which use USB peripheral and CDC-ACM interface: https://github.com/IntergatedCircuits/CanDybugFW (F0 and F3) https://github.com/IntergatedCircuits/DebugDongleFW (F0)
They both work in both directions, I haven't had issues like yours so far.
Check if you have the endpoint numbers set correctly, and debug the USB_vAllocateEPs()
function to see if it allocates registers and memory correctly.
I think endpoint numbers are set correctly as my STM32F4 works well using the same settings.
Anyway, USB configuration shown at host side is here:
Bus 005 Device 034: ID 0483:572b STMicroelectronics
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x572b
bcdDevice 1.00
iManufacturer 16 VaZso
iProduct 32 Serial Test Device
iSerial 48 56FF73066780535340461867
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 75
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 64 Device Configuration parameters
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 1 COM1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 1 COM1
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x8f EP 15 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 20
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0
iInterface 1 COM1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)
At USB_vAllocateEPs(), device goes through endpoint number (ulEpNum) 0 to 8, where endpoint 0 and 1 has MaxPacketSize of 64 both IN and OUT directions... others has MaxPacketSize of 0.
...then it goes through initialization of endpoint 0, then it initializes endpoint 1 of both directions.
Unfortunately, I have no F0 or F3 MCUs, but I think if it works on F0 and F3, it should also work on F1...
I have tried to put notification endpoint also on 0x83 and is currently set to 0x8F. However, I don't know where it is initialized, but not in above functions when ulEpNum value is set to 7. Anyway, it should be initialized as enumeration of VCP fails if it is not used ( I have "cdc_acm: probe of 5-4:1.0 failed with error -22" message that case).
If I set OUT endpoint number to 0x02, then it initializes IN direction when ulEpNum==1 and OUT direction when ulEpNum==2, but otherwise the behaviour is the same.
If you use USBD_CDC_NOTEP_USED 1
then the NotEpNum
should be valid for the peripheral, in this case between 0x81 and 0x87.
Ouch, you are right... it has 8 possible endpoints instead of 16 like USB_OTG peripherals.
I set it to 0x87 and now I see it when ulEpNum reaches 7, then pxEP2->MaxPacketSize is 8 and it goes through initialization.
However, behaviour looks like the same. (When sending data from host to device, I have IRQ only on EP0.)
Current configuration:
Bus 005 Device 073: ID 0483:572b STMicroelectronics
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x572b
bcdDevice 1.00
iManufacturer 16 VaZso
iProduct 32 Serial Test Device
iSerial 48 56FF73066780535340461867
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 75
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 64 Device Configuration parameters
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 1 COM1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 1 COM1
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x87 EP 7 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 20
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0
iInterface 1 COM1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)
(For the record, USB_OTG has even less endpoints.)
Could you check these values when you are expecting to receive data through the endpoint:
Sorry for the late answer, I was on the roads yesterday...
When I send data from host to device, USB_vIRQHandler comes up. The value of USB->ISTR.w is 0b1000001100010000 So, it sets usEpReg to USB->EPR[0].w and then checks if USB_EP_CTR_RX bit is high. It is, so it handles OUT request on endpoint 0.
On the second round of for cycle, (usISTR & USB_ISTR_CTR) != 0 is false.
As of the state of endpoint 1 when USB_vIRQHandler comes up, the STAT_RX field of USB->EPR[1] has the value of 3 and the state of IN[1] endpoint is "USB_EP_STATE_DATA", so as far as I can see, it seems data interrupt is coming up at the appropriate IN endpoint.
However, it is not handled there,
The cheap STM32F103C8T6 "Blue Pill" dev board has a known bug in its USB implementation. It has a 10kΩ or 4.7kΩ pull-up resistor on D+ (R10 on the PCB) instead of the 1.5kΩ pull-up specified in the standard. Try replacing the resistor with the correct value and see if that solves your problem.
Thank you your reply.
I have replaced this resistor on one of my boards and tried the same code which has three virtual ports set up (these are the output of two sensors and a message port).
One of them also has an input buffer set up, but not even .Received callback comes up.
The other direction (USB data output) is still working.
Dear IntergatedCircuits,
(I have pressed enter by mistake, that was the cause of initial empty issue...)
I put your code on an STM32F103C8T6 board together with USBDevice in Eclipse + HAL project.
Host can enumerate USB device and my keyboard interface work well - I can send keystrokes to host and receive Num Lock / Caps Lock status change signals, so it works well.
If I mount a USB-CDC interface, it also accessible by host and I can send data from device to host without problems. However, I can not send messages from host to device.
The vcp_if interface is the same what I used together with my STM32F407VET6 microcontroller where both transmit / receive side work well.
So, with STM32F1, USB enumeration and endpoint configuration looks okay at host side, but by the time I try to send data from host to device, I can not see any interrupt happen on device.
STM32F4 family use xpd_usb_otg of XPD library and STM32F103 use xpd_usb from there, so USB low level behaviour differs, but otherwise the higher level interfaces I try to use are the same.
Could you please suggest what may I test on STM32F1 side?
Thank you your help in advance.