cancel
Showing results for 
Search instead for 
Did you mean: 

USBX CDC ACM Write problem

Misterxyz83
Associate II

Hello everyone,

I'm developing an application using USBX CDC ACM class in standalone mode. I've written an execution loop for scheduling USB stack operations and there are no problem with READ transaction; i'm able to receive correctly every data from my host pc.

There is a problem or perhaps my misunderstanding on WRITE transaction (i mean from STM32 device to host pc). I'm not sure how to interpret state returned by ux_device_class_cdc_acm_write_run function. 

The device receive a packet (few bytes from host) and it has to answer back few bytes. On first packet, my host receive every byte sent by device but when the host send another packet, the device will send back data but nothing is received; i need to send another packet to "push" data to host.

It is not very clear (for me) what is the correct behavior in respect of ux_device_class_cdc_acm_write_run exit status.

  • when device has to send N bytes so the write_run function is called with requested_length == N;
  • the write_run function returns UX_STATUS_WAIT with actual_length == 0, i don't understand why because it has sent every byte (following with debugger in source code);
  • my firmware will run again on the same block because of actual_length == 0, so i cannot move forward on my buffer and on the second call of write_run (with same data and length!) it returns UX_STATUS_NEXT with actual_length == N, so i will move forward my buffer but it stucks because i sent all data needed.
  • The host will receive all N bytes correctly;
  • after that, when it need to send other N bytes it calls again write_run but in this case the host will not receive nothing; the internal state machine seems to be in a non-reset status and i will pass over.

I'm not sure on how to use that write_run function. I've used the ZLP define on ux_user.h but no change.

Everyone can help me to understand how to handle UX_STATUS_WAIT and UX_STATUS_NEXT status? 

How does should be used in standalone mode the write process?

Thanks in advance

6 REPLIES 6
BarryWhit
Lead II

I've got no specifics about your issue, but have you looked at

https://community.st.com/t5/stm32-mcus/how-to-implement-the-usb-device-cdc-vcom-in-stm32-using-the/ta-p/599170

The comments there also suggest some example projects you could look up.

 

If you do figure out the issue, please do post an update.

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.
Misterxyz83
Associate II

Thanks for your help @BarryWhit 

I've read the @B.Montanari articles and they are very useful, but i can't find there a solution for my problem. 

I've found something in here:

https://github.com/eclipse-threadx/usbx/blob/master/test/regression/usbx_standalone_cdc_acm_basic_test.c 

It uses the ux_device_class_cdc_acm_write_run API like i need. i will investigate and keep the post updated :)

 

Thanks again

Lukasz Nowak
Associate III

In case anybody is interested, I was able to implement a CDC_ACM in USBX standalone mode on STM32 H523, based on the usbx regression test quoted here.

I ended up using ux_device_class_cdc_acm_write_with_callback().

In order to have that function available, the UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE define in CubeMx needs to be set to false.

The application needs to provide read/write callback functions which need to be registered after CDC becomes active:

      cdc_acm_slave_callback.ux_device_class_cdc_acm_parameter_read_callback = USBX_cdc_acm_device_read_callback;
      cdc_acm_slave_callback.ux_device_class_cdc_acm_parameter_write_callback = USBX_cdc_acm_device_write_callback;
      ux_device_class_cdc_acm_ioctl(cdc_acm, UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_START, (VOID*)&cdc_acm_slave_callback);

Then just call ux_device_class_cdc_acm_write_with_callback() and wait for the write callback, before doing it again.

It seems to be quite stable, no data gets lost, and I am able to get around 3Mbps throughput to a Windows PC doing printf-like output (5-10k lines per second, depending on length).

@B.Montanari, since you wrote a few good KB articles about USBX, maybe it would be possible to properly document how to do CDC_ACM in USBX standalone mode?

It took me a lot of time to implement a simple printf() over a USBX virtual com port. It used to be much easier with the old STM32 usb library...

Hi,

I just use this -

...
	UserTxBufferFS[0] = 'H';
	UserTxBufferFS[1] = 'i';
	UserTxBufferFS[2] = 0x0A;
	UserTxBufferFS[3] = 0x0D;
	CDC_Transmit_FS(&UserTxBufferFS[0], 4);
...

 UserTxBufferFS[] is predefined so you don't need to Set it. Just make sure it's big enough for your purpose.

As usual, just make sure things are thread-safe...

I hope this helps.

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.

CDC_Transmit_FS() is part of the old STM32 USB Device library. Unfortunately it is no longer available for the newer families (U5 and H5 so far). For those chips the only option offered by CubeMx is USBX, which is much more complicated.

And by default USBX expects to have the full ThreadX RTOS enabled. As an option, USBX has a "standalone mode", which can be executed from the main application loop, without an RTOS. But it is not documented very well. CubeMx only contains examples for the HID class, not anything else.

I think that USBX is actually quite good, but it has a bit of a steep learning curve. And the code generated by CubeMx is quite incomplete - a substantial amount needs to be added to implement even the simplest usb application.

@Lukasz Nowak   Thanks for the heads-up. None of my projects can cope with an OS. So, any new projects that require CDC, I'll take U5 and H5 off the menu...

Kind regards
Pedro

 

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.