cancel
Showing results for 
Search instead for 
Did you mean: 

USB device audio class up or IN stream not working.

MWolt.1
Associate II

Device: STM32F411RE NUCLEO

Hello, I am having some issues with STM USBD AUDIO library. For some reason I cannot get it to stream audio data to a host device in a proper way.

The device is successfully recognized as 2 channel 16 bit microphone by my PC.

When I press the record button in windows recorder or audacity nothing happens.

So far all I know is the USBD_AUDIO_DataIn is not getting called and from what I have read so far this is the function where I am supposed to be handling the sending data to host.

I have been trying to get this working for weeks and I have had it working in the past with the following conditions: I put the LL_Transmit function in the USBD_AUDIO_SOF function. This worked as the audio data is supposed to get polled every 1ms anyway. Then I had the problem that every other packet sent was empty, so I added the LL_Transmit function back into DataIn stage and now my sine wave was being sent perfectly. Which is really weird if you think about it. I cannot imagine that the library was designed to be used this way.

The weird thing is, if I do not use the SOF cb the DataIn stage is also not called.

I tried reading documentation but I just don't get this code. Too many layers too much stuff, and fully implemented for only speakers class so I constantly need to back up my workspace in case I do any "code generation" since I cannot work in the STM pre-approved user code spaces. Honestly I feel like throwing this whole library except the USB descriptors in the thrash. I mean previously I have also found the RM and registers much easyer to work with that STM Libraries and LL/HAL documentation. I'll just tell my boss to screw him and his time constraints. Since i'm not getting anywhere anyway.

Unless anyone here has some experience with this library and could tell me what I am doing wrong.

EDIT:::

Here is a picture of some code where I am trying to send just a single array over and over again.


_legacyfs_online_stmicro_images_0693W00000bhfj6QAA.png 

Here follows a picture of wireshank showing empty packets:


_legacyfs_online_stmicro_images_0693W00000bhfkxQAA.pngAs you can see

all packets are empty.

why?

13 REPLIES 13
vinux
Associate II

for future reference: i have rudimentary working version (V1.28).

IS2 source -> USB audio dst working, just for for anybody that cares for the topic.

 

the buffer mechanism is "crude" presently, read: artifacts while ingesting i2s, likely issue of mis-aligned clocks from host -> stm <-i2s source.

 

As my source is presently a Bluetooth module, i cannot change it's clock behavior.... future works.

code: VincentGijsen/STM32F401_working_i2s_to-USB (github.com)

 

 

Hello, I have exactly the same problem as you have. Could you share the code you implemented for solving?

vinux
Associate II

Hi, 

this works somehow; https://github.com/VincentGijsen/STM32F401_working_i2s_to-USB/blob/main/Middlewares/ST/STM32_USB_Device_Library/Class/AUDIO/Src/usbd_audio.c but quite hacky.. ok for hobby, perhaps not so much for commercial products ;)

 

I also observed issues between various versions of the SDK. (Tip: double check any code example is done with identical STM library version !!)

I never succeeded in implementing it flawless. Issue ( in my code) remains to deal with 2 independend clocks (usb and i2s source). Naive implementation will problem latch fixed set of frames on SOF trigger, and throw away or duplicate frames cached from I2s, if I cannot/will not try to slave either usb or i2s to other end..

 

at this point I’m contemplating to try other mcu product for future audio/usb hobby projects. 

Georgy Moshkin
Senior II

I found the solution.

1) You do not need SOF interrupts, disable them.

2) STM32 HAL works perfectly fine. The problem emerges because the HOST reacts to USBD_LL_Transmit() only after several SOF frames. This means that USBD_LL_Transmit() in this code is useless:

USBD_LL_OpenEP(pdev, AUDIO_IN_EP, USBD_EP_TYPE_ISOC, USB_BUF_SIZE);
pdev->ep_in[AUDIO_IN_EP & 0xFU].is_used = 1U;
USBD_LL_FlushEP(pdev, AUDIO_IN_EP);
USBD_LL_Transmit(pdev, AUDIO_IN_EP, (uint8_t*)&someData, SEND_SAMPLES * 2);

3) All we need is to wait for some time (5 SOF frames on my Windows 11 system) after USBD_LL_OpenEP() and only then call USBD_LL_Transmit()

Bad way: call USBD_LL_Transmit() from SOF interrupt. As soon as you've got first USBD_AUDIO_DataIn() callback, only call USBD_LL_Transmit() from USBD_AUDIO_DataIn().

The good way: disable SOF interrupts. Monitor when HOST selected alternate mode, do a first USBD_LL_Transmit() with some delay from the main loop. All the consequent transfers will be automatically handled by USBD_AUDIO_DataIn(), from which you transfer microphone signal using USBD_LL_Transmit().

I will use the latter method in my mic for youtubers project. Both methods work and tested on STM32H7B0 under Windows 11, but I need to confirm yet if it is the same for Android/Linux and MacOS.

 

Check my STM32 Bootloader - flash your STM32 with AES-encrypted binaries right from web browser!