2025-11-11 12:22 PM
I've set up my STM32U5A9J-DK to use ThreadX and connect to my PC via USBX and Audio Class.
I'm correctly see the Audio Device on my PC and I can easily stream audio to it. The only thing is that, for some reason, the callback for new frame done is not fired
audio_stream_parameter[0].ux_device_class_audio_stream_parameter_callbacks.ux_device_class_audio_stream_change
= USBD_AUDIO_PlaybackStreamChange;
audio_stream_parameter[0].ux_device_class_audio_stream_parameter_callbacks.ux_device_class_audio_stream_frame_done
= USBD_AUDIO_PlaybackStreamFrameDone;The strage thing is that USBD_AUDIO_PlaybackStreamChange is correctly called
VOID USBD_AUDIO_PlaybackStreamChange(UX_DEVICE_CLASS_AUDIO_STREAM *audio_play_stream,
ULONG alternate_setting)
{
/* USER CODE BEGIN USBD_AUDIO_PlaybackStreamChange */
/* Do nothing if alternate setting is 0 (stream closed). */
if (alternate_setting == 0)
{
return;
}
BufferCtl.state = PLAY_BUFFER_OFFSET_UNKNOWN;
/* Start reception (stream opened). */
ux_device_class_audio_reception_start(audio_play_stream);
/* USER CODE END USBD_AUDIO_PlaybackStreamChange */
return;
}Instead, USBD_AUDIO_PlaybackStreamFrameDone is never called
VOID USBD_AUDIO_PlaybackStreamFrameDone(UX_DEVICE_CLASS_AUDIO_STREAM *audio_play_stream,
ULONG length)
{
/* USER CODE BEGIN USBD_AUDIO_PlaybackStreamFrameDone */
UCHAR *frame_buffer;
ULONG frame_length;
/* Get access to first audio input frame. */
ux_device_class_audio_read_frame_get(audio_play_stream, &frame_buffer, &frame_length);
...
}
Solved! Go to Solution.
2025-11-18 4:49 AM - edited 2025-11-18 4:54 AM
So why does your example code do just that?
en.x-cube-azrtos-h7-v3-3-0.zip\Projects\STM32H743I-EVAL\Applications\USBX\Ux_Device_Audio2.0_PlayBack\
https://www.st.com/en/embedded-software/x-cube-azrtos-h7.html
Or am I reading it wrong? As I've followed your example above
2025-11-18 6:30 AM
Hi @nico23 again,
I agree example firmware should be updated (internal ticket 204777). As of now, the recommendation is to move the MX_USBX_Host_Init() to USBX_APP_Host_Init().
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-11-18 12:09 PM
I can confirm that invoking USBX_APP_Device_Init within a thread fixes the first issue.
Now I'm still experiencing the return code 38 from the dcd function https://community.st.com/t5/stm32-mcus-embedded-software/usbx-audio-class-frame-done-callback-not-called/m-p/856896/highlight/true#M70159
2025-11-19 6:12 AM
Why have you accepted the solution? The problem hasn't been resolved. The frame done callback not called is STILL NOT CALLED!
Who said the issue on the top was resolved!
2025-11-19 6:54 AM
Hi @nico23
I thought you have confirmed that movingUSBX_APP_Device_Init() inside a ThreadX thread fixes the mutex acquisition error.
You should not see an HCD context error since you are using device only. It seems an issue to be reported and need further investigation.
The value 38 decimal = 0x26 hex, which matches UX_TRANSFER_BUS_RESET in ux_api.h meaning the transfer request is failing. I suggest use USB protocol analyzer to see USB traffic and errors better than error handler.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-11-20 11:33 PM - edited 2025-11-20 11:36 PM
After sniffing the USB communication, it seems that the host sends a correct URB_FUNCTION_CONTROL_TRANSFER
USB URB [Source: host] [Destination: 1.11.0] USBPcap pseudoheader length: 28 IRP ID: 0xffffe28a5cfbc4b0 IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000) URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008) IRP information: 0x00, Direction: FDO -> PDO 0000 000. = Reserved: 0x00 .... ...0 = Direction: FDO -> PDO (0x0) URB bus id: 1 Device address: 11 Endpoint: 0x00, Direction: OUT 0... .... = Direction: OUT (0) .... 0000 = Endpoint number: 0 URB transfer type: URB_CONTROL (0x02) Packet Data Length: 12 [Response in: 14444] Control transfer stage: Setup (0) [bInterfaceClass: Audio (0x01)] Setup Data bmRequestType: 0x21 0... .... = Direction: Host-to-device .01. .... = Type: Class (0x1) ...0 0001 = Recipient: Interface (0x01) bRequest: CUR (0x01) wValue: 0x0100, Clock Source Control Selector: CS_SAM_FREQ_CONTROL .... .... 0000 0000 = Channel Number: 0x00 0000 0001 .... .... = Clock Source Control Selector: CS_SAM_FREQ_CONTROL (0x01) wIndex: 0x1800 .... .... 0000 0000 = Interface Number: 0 0001 1000 .... .... = Entity ID: 24 wLength: 4 Layout 3 Parameter Block: Frequency [Hz] dCUR: 48000 Data Fragment: 80bb0000but the device answers with USBD_STATUS_STALL_PID
USB URB [Source: 1.11.0] [Destination: host] USBPcap pseudoheader length: 28 IRP ID: 0xffffe28a5cfbc4b0 IRP USBD_STATUS: USBD_STATUS_STALL_PID (0xc0000004) URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008) IRP information: 0x01, Direction: PDO -> FDO 0000 000. = Reserved: 0x00 .... ...1 = Direction: PDO -> FDO (0x1) URB bus id: 1 Device address: 11 Endpoint: 0x00, Direction: OUT 0... .... = Direction: OUT (0) .... 0000 = Endpoint number: 0 URB transfer type: URB_CONTROL (0x02) Packet Data Length: 0 [Request in: 14443] [Time from request: 214.000 microseconds] Control transfer stage: Complete (3) [bInterfaceClass: Audio (0x01)]After debugging inside the USBX library, it seems the STM32 responds with stalled because it executes the function _ux_device_class_audio20_control_process and it reaches the end where there's
/* Request or parameter not supported. */
_ux_device_stack_endpoint_stall(endpoint);From what I'm understanding, the device is failing one of the checks inside the case UX_DEVICE_CLASS_AUDIO20_CUR: regarding the audio sampling frequency.
My host has a set frequency of 48kHz, and my device descriptor (https://github.com/NicoCaldo/NovaSonus_ThreadX/blob/main/USBX/App/ux_device_descriptors.c) which is a copy-paste of the one linked by @T_Hamdi https://github.com/stm32-hotspot/STM32WBA-BLE-USBx-Class-Audio/blob/main/Projects/STM32WBA65I-DK1/Applications/USBX/Ux_Device_Audio_2.0_Standalone/USBX/App/ux_device_descriptors.c ) defines the frequency as 48kHz
ULONG USBD_AUDIO20_PLAYBACK_FREQENCIES[USBD_AUDIO_PLAY_FREQ_COUNT] = {
USBD_AUDIO_FREQ_48_K,
};and in VOID USBD_AUDIO_SetControlValues(VOID)
audio_control[0].ux_device_class_audio20_control_cs_id = USBD_AUDIO_PLAY_CLOCK_SOURCE_ID;
audio_control[0].ux_device_class_audio20_control_sampling_frequency = USBD_AUDIO_FREQ_48_K;
audio_control[0].ux_device_class_audio20_control_fu_id = USBD_AUDIO_PLAY_FEATURE_UNIT_ID;So I'm not understanding why it's failing
2025-11-21 5:48 AM
So, I think ultimately there's a bug in the USBX api when it comes to setting frequency.
If I'm choosing to support a single frequency, i.e. 48k, why does the device in the sampling frequency control SET request break and return if multiple frequencies are not supported?
It does the same while checking if it's a fixed single frequency.
/* Sampling frequency control, SET request. */
if ((request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_OUT &&
(control_selector == UX_DEVICE_CLASS_AUDIO20_CS_SAM_FREQ_CONTROL))
{
switch(request)
{
case UX_DEVICE_CLASS_AUDIO20_CUR:
/* Check request parameter. */
if (request_length != 4)
break;
/* Check if multiple frequency supported. */
if (control -> ux_device_class_audio20_control_sampling_frequency != 0)
break;
...
/* Check if it's fixed single frequency. */
if (n_sub <= 1 && res == 0)
break;Isn't it more correct to first check if the frequency the host is trying to set matches the only frequency the device can set? If not, it breaks and returns, stalling the device.
2025-11-21 6:01 AM
Hi @nico23
An internal ticket 222275 is submitted to dedicated team regarding the HCD context issue.
Regarding the stall, would you simplify your project to narrow down the issue to simply streaming via SAI like the example N6 here.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-11-21 6:27 AM - edited 2025-11-21 6:27 AM
Hi @nico23
I think the order of initialization regarding setting the audio frequency and control is different.
If this function is called too early, the USBX audio class control handler may see a zero or invalid frequency, causing it to stall on frequency SET requests.
The example firmware sets explicit audio playback parameters (sample rate, bits per sample, volume) after USBX init, which may also be required to keep the device and USBX stack synchronized.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-11-21 12:51 PM - edited 2025-11-21 1:25 PM
I'll try to use SAI as in the project you linked, but the issue regarding the frequency check still remains. If you choose a single frequency and, for some reason, the host checks if multi-frequency is supported, it automatically stalls.
Setting
audio_control[0].ux_device_class_audio20_control_sampling_frequency = USBD_AUDIO_FREQ_48_K;automatically triggers
if (control -> ux_device_class_audio20_control_sampling_frequency != 0)
break;if there's a set request UX_DEVICE_CLASS_AUDIO20_CUR
One question @FBL about your example, I think the BSP_AUDIO_Init_t struct, which is then used to initialize the various parameters, is declared in #include "stm32n6570_discovery_audio.h" (which I can't find on the project you linked)
Where do I get the source code files for the STM32U5A9?