IntergatedCircuits / STM32_XPD

STM32 eXtensible Peripheral Drivers
Apache License 2.0
41 stars 10 forks source link

STM32F1 USB-CDC OUT #1

Open VaZso opened 5 years ago

VaZso commented 5 years ago

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.

benedekkupper commented 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.

VaZso commented 5 years ago

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?

VaZso commented 5 years ago

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.

benedekkupper commented 5 years ago

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?

VaZso commented 5 years ago

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.

benedekkupper commented 5 years ago

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.

VaZso commented 5 years ago

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.

benedekkupper commented 5 years ago

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.

VaZso commented 5 years ago

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.

benedekkupper commented 5 years ago

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.

benedekkupper commented 5 years ago

Check if you have the endpoint numbers set correctly, and debug the USB_vAllocateEPs() function to see if it allocates registers and memory correctly.

VaZso commented 5 years ago

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.

benedekkupper commented 5 years ago

If you use USBD_CDC_NOTEP_USED 1 then the NotEpNum should be valid for the peripheral, in this case between 0x81 and 0x87.

VaZso commented 5 years ago

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)
benedekkupper commented 5 years ago

(For the record, USB_OTG has even less endpoints.)

benedekkupper commented 5 years ago

Could you check these values when you are expecting to receive data through the endpoint:

VaZso commented 5 years ago

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,

rljacobson commented 4 years ago

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.

VaZso commented 4 years ago

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.