UAC2.0 on STM32

Did host send a "Set Interface" request to select the alternate setting of your output interface?
Yes, host does send a "Set Interface" request.
SetInterface.jpg

You should then make the first call to USBD_LL_PrepareReceive() for receiving data from host.
Yes, USBD_LL_PrepareReceive() is called.

static uint8_t USBD_AUDIO_SetInterfaceAlternate(USBD_HandleTypeDef *pdev,
uint8_t as_interface_num, uint8_t new_alt)
{
USBD_AUDIO_HandleTypeDef *haudio;

haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData;

if(new_alt == 0)
{
(void)USBD_LL_CloseEP(pdev, AUDIO_OUT_EP);
pdev->ep_out[AUDIO_OUT_EP & 0xFU].is_used = 0U;
pdev->ep_out[AUDIO_OUT_EP & 0xFU].bInterval = 0U;

(void)USBD_LL_CloseEP(pdev, EPNUM_AUDIO_FB);
pdev->ep_in[EPNUM_AUDIO_FB & 0xFU].is_used = 0U;
pdev->ep_in[EPNUM_AUDIO_FB & 0xFU].bInterval = 0U;
}
else
{
pdev->ep_out[AUDIO_OUT_EP & 0xFU].bInterval = AUDIO_HS_BINTERVAL;
(void)USBD_LL_OpenEP(pdev, AUDIO_OUT_EP, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET_MAX);
pdev->ep_out[AUDIO_OUT_EP & 0xFU].is_used = 1U;

haudio->wr_ptr = 0U;
haudio->rd_ptr = 0U;
haudio->rd_enable = 0U;

(void)USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, haudio->buffer, AUDIO_OUT_PACKET_MAX);

//Feedback
pdev->ep_in[EPNUM_AUDIO_FB & 0xFU].bInterval = 1;
USBD_LL_OpenEP(pdev, EPNUM_AUDIO_FB, USBD_EP_TYPE_ISOC, AUDIO_FEEDBACK_EP_PACKET_SIZE);
USBD_LL_FlushEP(pdev, EPNUM_AUDIO_FB);
pdev->ep_in[EPNUM_AUDIO_FB & 0xFU].is_used = 1U;

get_usb_high_speed_rate(((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->GetPlaybackFeedback());

USBD_LL_Transmit(pdev, EPNUM_AUDIO_FB, AudioFB, AUDIO_FEEDBACK_EP_PACKET_SIZE);

FBAllowed = 0;
}

return USBD_OK;
}

That way host receive feedback, but device does not recieve audio data. If USBD_LL_Transmit(...) is commented, host does not receive feedback, but device does recieve audio data. Two ways do not work simultaneously.
 
I open the OUT_EP when USBD audio is initialized (so only once). When host calls Set Interface for alternate setting 0 I just flush OUT_EP.
Tried that, result is the same. If IN endpoint sends packet first then device only sends packets and do not receive audio data. If OUT endpoint receive packet first then device do not send packets and do receive audio data. What version of USB HAL drivers do you use?
 
Tried that, result is the same. If IN endpoint sends packet first then device only sends packets and do not receive audio data. If OUT endpoint receive packet first then device do not send packets and do receive audio data. What version of USB HAL drivers do you use?
Ok, now I understand your explanation. Start sending feedback only after you have received enough data (depends on your buffering scheme). SOF interrupts should occur anyhow if you have SOF enabled in USBD_LL_Init().
@bohrok2610 , have you tried your UAC2.0 implementation with external HS PHY?
I started my development with Nucleo board and external HS PHY but that did not work well with HS. It is practically not possible to connect external HS PHY to Nucleo board since the required pins are scattered all over the board and max trace lengths will be next to impossible to meet. That is why I switched to 723DISCO. And soon after that I made my own board as external I2S clock with 723DISCO is not possible without hacking the board.
 
Start sending feedback only after you have received enough data (depends on your buffering scheme).
Tried that. IN packets are enabled when data fills half a buffer, at the very same moment SAI starts outputting buffered data. After IN packets are enabled audio data is not received anymore. Sometimes I can hear sound played cyclically that the buffer has already been filled with. It is like IN packets have priority over OUT packets. So IN packets "push out" OUT packets.
 
IN packets are enabled when data fills half a buffer...
Does "enabled" mean that you start then sending feedback but SOF interrupts are enabled already at initialization?

What STM32F7 board and external HS PHY are you using? IIRC for ULPI the recommended max length of traces (or wires) is about 75mm and length of ULPI signal traces should be within 10mm of CLK trace.
 
Does "enabled" mean that you start then sending feedback but SOF interrupts are enabled already at initialization?
Yes, SOF interrupts are enabled already at initialization in USBD_LL_Init(...) and always active. IN packets are enabled by a variable flag after Interface Alternate swithes from 0 to 1 and the buffer is filled at half of size.

What STM32F7 board and external HS PHY are you using?
I am using a 4-layer PCB board of my design with ULPI traces length matching to 0,05 mm. MCU is STM32F722VC, HS PHY is USB3300. I tested it in HS applications with interrupt endpoints (HID) and bulk endpoints (custom CDC with DMA enabled). But UAC2.0 is the first application with simultaneous bidirectional (IN and OUT) HS transfers.
 
So you get SOF interrupts, transmit feedback but host does not appear to get them?
No. I will describe the situation step by step:
1) Plug device into PC, audio stream is not active. Device starts getting SOF interrupts.
2) Start audio stream. Device starts getting Data Out interrupts, receiving audio data and filling it's buffer.
3) As the buffer is filled half of it's size, SAI starts outputting data from the buffer and variable flag is changed to indicate that feedback is allowed to be sent.
4) In the nearest SOF interrupt feedback is transmitted for the first time.
5) After transmitting feedback (step 4) device stops getting Data Out interrupts and audio data is not received any more.
6) From step 5 device only get SOF interrupts and transmit feedback, but it do not receive audio data. Nethertheless I do not get Iso Incomplete interrrupts in device; Windows UAC2.0 log does not contain errors and says audio stream is running and feedback stream is running. It seems like IN packets block OUT packets in device side.

Have you tried to run your SW/board with FS?
Just tried that, only changed speed to FS and corrected endpoints packets size. Everything works, both data receiving and feedback transmitting. So the same device in UAC2.0 FS mode has no problems described above. The problem relates to HS mode only.
 
Just tried that, only changed speed to FS and corrected endpoints packets size. Everything works, both data receiving and feedback transmitting. So the same device in UAC2.0 FS mode has no problems described above. The problem relates to HS mode only.
Ok, sounds like your external PHY has trouble with bidirectional HS transfers. Just one more check: in USBD_LL_Init() do you set hpcd_USB_OTG_HS.Init.phy_itface to USB_OTG_ULPI_PHY?
 
You seem to have similar issue as I had with Nucleo + external PHY board (USB3300): FS worked but not HS. Although in my case it was most probably timing issue due to wire lengths.
HS works with STM32F723DISCO, but as I mentioned it also has shortcomings (external I2S clock). Custom board with STM32F723 is probably the best option but the MCU is out-of-stock until late next year.
 
  • Like
Reactions: 1 user
Well, after many experiments I think the solution is found. Poll interval of data endpoint is encreased to 250 us (bInterval = 2), poll interval of feedback endpoint is encreased to 1 ms (bInterval = 4).
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] ENDPOINT_DESCRIPTOR bLength=0x07 bDescriptorType=0x05
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bEndpointAddress 0x01
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bmAttributes 0x05
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] wMaxPacketSize 0x0038
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bInterval 0x02
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] CS_ENDPOINT_DESCRIPTOR bLength=0x08 bDescriptorType=0x25
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bDescriptorSubtype 0x01
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bmAttributes 0x00
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bmControls 0x00
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bLockDelayUnits 0x01
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] wLockDelay 0x01
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] ENDPOINT_DESCRIPTOR bLength=0x07 bDescriptorType=0x05
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bEndpointAddress 0x83
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bmAttributes 0x11
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] wMaxPacketSize 0x0004
[1]0004.2C70::12/23/2022-01:11:37.154 [USBAudio2] bInterval 0x04

[3]0004.2C70::12/23/2022-01:11:37.155 [USBAudio2] Format Type I PCM (0x00000001) SubSlotSize=2 BitsPerSample=16 ChannelCount=2
[3]0004.2C70::12/23/2022-01:11:37.155 [USBAudio2] Data Endpoint 0x01 Isochronous Asynchronous Data ActualMaxPacketSize=56 ActualPacketFrequency=4000/s (HS Endpoint)
[3]0004.2C70::12/23/2022-01:11:37.155 [USBAudio2] Feedback Endpoint 0x83 Isochronous None Feedback ActualMaxPacketSize=4 ActualPacketFrequency=1000/s (HS Endpoint)

After several hours of streaming device seems to work without transfer errors, it receives audio data and send feedback.
0]0000.0000::12/23/2022-01:11:51.397 [USBAudio2]EP 0x01 OUT stream running at PCM ch=2 sz=16/16 sr=48000
.......................................
[0]0000.0000::12/23/2022-01:11:51.493 [USBAudio2]feedback value 0x0000c000 is out of range [0x000b0000,0x000d0000], ignoring value
[0]0000.0000::12/23/2022-01:11:51.493 [USBAudio2]feedback value 0x0000c000 is out of range [0x000b0000,0x000d0000], ignoring value
[0]0000.0000::12/23/2022-01:11:51.493 [USBAudio2]feedback value 0x0000c000 is out of range [0x000b0000,0x000d0000], ignoring value
[0]0000.0000::12/23/2022-01:11:51.493 [USBAudio2]EP 0x83 FB stream running

Now I need to correct feedback value in accordance to new poll interval and test for sound correctness and pureness.