UAC2.0 on STM32

Yes of course, ST example is UAC1 and it has to be rewritten for UAC2 implementation. That is what I am trying to do.
Hi, I'm new here. I was googling for UAC2 on STM32 and came across your post.

To save you some time I would like to suggest you to check out the "TinyUSB" implementation stack. It has complete example for UAC2 implementation.

UAC 2.0 implementation example

TinyUSB GitHub Repo

I have tested it on my "STM32F723E Discovery" board, and it enumerates fine on USB-HS port with proper configuration. I'm in progress to make the onboard wolfson codec to work. I have used TinyUSB inside STM32Cube IDE. It was cumbersome process to get both of them to play along.

F723 has built in HS Phy, which F722 doesn't have. You may have to add additional setup for ULPI Phy to work properly.

-Shreyas
 
  • Like
Reactions: 1 user
To save you some time I would like to suggest you to check out the "TinyUSB" implementation stack. It has complete example for UAC2 implementation.
Thank you for taking part. I know about TinyUSB and have checked it's UAC2 implementation. It does not work, don't waste your time. Yes, device enumerates properly and that is all. It is like data is corrupted when being received, buffer overrun or something like this.
Here this issue is described in details https://github.com/hathach/tinyusb/issues/1186
I can confirm it, I got the same results.
I found also sdr widget https://github.com/borgestrand/sdr-widget and
Cherry usb library https://github.com/sakumisu/CherryUSB
They may be usefull. After a couple of days of searching I decided to take ST UAC1 example as a base and rewrite it for UAC2 implementation.
 
Last edited:
  • Like
Reactions: 1 user
Thank you for taking part. I know about TinyUSB and have checked it's UAC2 implementation. It does not work, don't waste your time. Yes, device enumerates properly and that is all. It is like data is corrupted when being received, buffer overrun or something like this.
Here this issue is described in details https://github.com/hathach/tinyusb/issues/1186
I can confirm it, I got the same results.
I found also sdr widget https://github.com/borgestrand/sdr-widget and
Cherry usb library https://github.com/sakumisu/CherryUSB
They may be usefull. After a couple of days of searching I decided to take ST UAC1 example as a base and rewrite it for UAC2 implementation.
Thank you very much for the pointers! I'll look into it.

Please let me know if the UAC2 rehaul works.

If possible please make it open source or make a small tutorial on your project to help people with limited programming prowess (like me) :)

Thanks again!
 
Thank you for taking part. I know about TinyUSB and have checked it's UAC2 implementation. It does not work, don't waste your time. Yes, device enumerates properly and that is all. It is like data is corrupted when being received, buffer overrun or something like this.
Here this issue is described in details https://github.com/hathach/tinyusb/issues/1186
I can confirm it, I got the same results.
I found also sdr widget https://github.com/borgestrand/sdr-widget and
Cherry usb library https://github.com/sakumisu/CherryUSB
They may be usefull. After a couple of days of searching I decided to take ST UAC1 example as a base and rewrite it for UAC2 implementation.

Buffer overrun/underrun are all per of the design. I had a look at the tinyusb source code and it doesn’t support isochronous for the STM32. So there’s no guarantees for when the usb bus will transport the data!

If you want to open source your implementation i’m happy to join projects. I have a UAC2 that’s enumerating and controls work so it’s recognised under linux ALSA - just doing the streaming coding but a little slow due to the day job getting in the way (I’ve a BSc in software engineering and 25+ years in the software industry). Currently I’m writing the code for a 24/32bit ADC i2s/pcm board. DMA i2s working but the STM32F723 has a bug in the USB DMA.
 
Hi! I'm following along here.

Might not help you, but the USB UAC1 code from STM is utter rubbish. I've been trying to use it and after finding multiple issues with it I'm now desparately trying to get rid of it.

On your problem. It's a long shot, but... everytime you generate a new project with an STM32 USB library change the product ID. If you don't then windows can become "sticky" to the last firmware you had on the device when you plugged it in. It will show as "Port Reset Failed". The best way to get round this and other windows doesn't see the device ... in device manager uninstall the device entirely, then scan for new hardware changes. If that doesn't fix it, try changing the product id in the descriptor to force it into seeing a new device.

The bugs in the UAC1 driver are around it's buffer handling and audio-sync. None of it actually works they way it was intended (as written) and even that approach is ... ill advised in the first place. It implements no error cases, no fault handling and in the event that ANY messages get dropped the entire device just stops. Mostly this is caused by a iterrupt loop ping-pong for the PrepareReceive() call. The receive is only called once in each interrupt. If an interrupt or packet is missed at any stage the device deadlocks with no interrupt impetrus.

Presently there is also a bug in the I2S driver code which 100% prevents you from using an external I2S clock. The register macros to checking it is missing a right shift after the AND. So it comes back with the value of that bit in the register instead of 1 | 0.

Then there is their Audio-Sync method. If you read it, read it more than once and ask... WTAF? Is it doing? The answer is, nothing much, half the code is innert due to it throwing away the local variable it calculated the offset into. When it does apply a buffer offset it simple adds 2U to the buffer size.... but the buffer is NOT THAT SIZE! So it will write off into unprotected memory.... it updates the buffersize on the HALF callback, but only takes any action on hte FULL callback.

The discovery board examples are just not worth using either, they have all been hacked and overly focused for very specific examples for very specific hardware. Disappointing really. Worse is the documentation for the various Middleware libraries is next to non-existant.

Several people have strongly advised me, if I want any working USB device, to start at the PHY layer in the LL libraries and do it myself. It will be less hassle.
 
Buffer overrun/underrun are all per of the design. I had a look at the tinyusb source code and it doesn’t support isochronous for the STM32. So there’s no guarantees for when the usb bus will transport the data!
TinyUSB does support isochronous endpoints for STM32. I believe the problem of TinyUSB is USB events handler mechanism which is not interrupt driven. All events on USB bus are placed in a queue and serviced in the main loop. Such a way is not suitable for applications with high data load such as USB audio especially USB Audio 2.0. Yes, it is all about design. But it seems that in case of TinyUSB the problem hides in the library itself not in device class implementation.

As for open source, I don't mind. I am going to share my results step by step.
 
  • Like
Reactions: 1 user
I’ll put up my code to github if we want a version to work from. I agree there’s some oddity in the HAL examples, however it offers a starting point (although not clean to offers some portability and futureproofing with new cube ide releases of devices.
For my i2s I poke the registers directly for configuration.
 
  • Like
Reactions: 1 user
TinyUSB does support isochronous endpoints for STM32. I believe the problem of TinyUSB is USB events handler mechanism which is not interrupt driven. All events on USB bus are placed in a queue and serviced in the main loop. Such a way is not suitable for applications with high data load such as USB audio especially USB Audio 2.0. Yes, it is all about design. But it seems that in case of TinyUSB the problem hides in the library itself not in device class implementation.

As for open source, I don't mind. I am going to share my results step by step.
The low level code has some comments about not supporting isochronous (at least on the main branch) and the EP type in the switch statement is commented out with if(0) which prods all my buttons (hate the use if if(0) in production code!

This next week is going to be crazy but i should have some time over the next couple of weeks to have a look at any code base you have. I’ll be able to look on tuesday evening but for now I don’t have access.

I have the STM32F723 disco board so i’ll offer some different testing options.
 
ST offers very good example of UAC1 https://www.st.com/en/embedded-software/x-cube-usb-audio.html which may be a very good starting point.
I did have a look at this before - it doesn't follow the HAL (no surprise there). From the comments on my previous thread, windows likes a +1 to -1 frame in the microframes to match the sample rates. So that will need attention in that version. I can’t remember if that used iso or not (i’m away from my dev machine atm).
 
My understanding of USB is you either frame duplicate/drop or you provide endpoint feedback in the SOF event. As to how to get the later working from HAL or even the LL code ... I'm still working that out.

You can maybe see why I am very seriously considering moving ALL USB endpoints to hardware ICs. That does present a distinct lack of easy Jelly bean ICs as 99% of them only do UAC1. DVD quality. However I got an Atmel+XLinx USB Bridge in the post from China to try. It does everything I2S up to 384/32 AND... if you enable the DS On pin it supports all the DS512/1024 for DTS and multi-channel theatre audio. I'm quite likely to end up running it at way, way less than that :)

On searching around the HAL bugs I mostly ran into people having low level issues the H7 chips. Some of them have a nasty hardware bug that catches people out though I think there was a work around.
 
As I've said before STM32F723 is perfectly capable of 768k/32 simultaneous output & input I2S (see e.g. here). I have also implemented PCM support (as in AD1862/PCM63/PCM1702) but not yet DSD support as I have not yet needed that.

I have not stumbled on any HAL bugs. The only bug I've found is what NickKUK already mentioned which is that USB OTG DMA does not work for I2S input but that is only a very minor issue and does not really impact performance. Another minor issue (not bug) is that SAI clock generator is not as flexible as I would like. This has been improved in H7.
 
  • Like
Reactions: 1 user
That's an expansion pack for their Discovery board with a codec. All the code is written bespokely for that setup and no, the audio sync is NOT fixed in it. It will work for 5 minutes and then buffer crash and then repeat.
As I have mentioned before this expansion pack is a very good example of UAC1. Of course, the example must be rewritten according to hardware. Audio sync is emplemented well and works without crashes and clicks. I used this example as a base for a multifrequency multichannel sound card with two SAIs. It works well.
 
I decided to start with "adaptive" isochronous endpoint. that is, without sync. The device can receive data and play it via SAI, but sound is not ideal now.
During receving data "Incomplete isochronous OUT transfer" interrupt rises. Does it require to be handled specifically? ST example does nothing in it's handler.
Windows USBAudio2 driver log does not contain anything about transfer errors.

But the log has the following message:

PIN 1 HostPin InPin
KSPROPERTY_PIN_PROPOSEDATAFORMAT SET
SET: ValueSize=64 < sizeof(KSDATAFORMAT_WAVEFORMATEX)
0xc0000023(STATUS_BUFFER_TOO_SMALL)

Could please someone clarify what it is about?
 
I decided to start with "adaptive" isochronous endpoint. that is, without sync. The device can receive data and play it via SAI, but sound is not ideal now.
During receving data "Incomplete isochronous OUT transfer" interrupt rises. Does it require to be handled specifically? ST example does nothing in it's handler.
Windows USBAudio2 driver log does not contain anything about transfer errors.
Incomplete isochronous OUT transfer means that the device has not completed the transfer of out data of current frame when the frame ends. Normally this should never happen because you are then losing data. Typically you should call USBD_LL_PrepareReceive at the end of data out stage.

But the log has the following message:

PIN 1 HostPin InPin
KSPROPERTY_PIN_PROPOSEDATAFORMAT SET
SET: ValueSize=64 < sizeof(KSDATAFORMAT_WAVEFORMATEX)
0xc0000023(STATUS_BUFFER_TOO_SMALL)

Could please someone clarify what it is about?
I'm not sure what is the reason for this message but I do not think it has anything to do with your problem.
 
  • Like
Reactions: 1 user
Normally this should never happen because you are then losing data.
Yes, It looks like data loss. Audio stream is 48 kHz / 16 bit. I can hear pure sound without noise and clicks but it's like only a part not the whole melody. If I change SAI output frequency to 24 kHz - exactly 2 times slower - I can hear the whole melody but it's not pure, some noise can be distinguished.