Skip to main content
Robmar
Senior II
July 12, 2026
Solved

USB microphone to H743 host streams mic then data freezes

  • July 12, 2026
  • 33 replies
  • 599 views

Connected an USB microphone to an H743 as host and it streams mic audio perfectly at 48 KHz for around 5 seconds then the data freezes.
SOF is still being called as is AudioHost_IsoDataReadyISR() from the STM IRQ driver, DMA is running (its set to use DMA, I tried without but same behaviour), but the same 96 bytes are transfered every uS: I can clear the receive buffer but it gets refilled with the same data.  Attempts to re-init the pipes etc etc fail to restore streaming.
Also, any pause in the servicing of the call to AudioHost_IsoDataReadyISR() results in exactly the same repeat data arriving.

This is my own code based on STM’s examples, as I said it runs perfectly for many seconds, if I unplug the microphone it runs again when plugged back in for the same good few seconds.

Is there an approved way to restore audio streaming without a full reset when there is an occasional timing glitch in servicing the AudioHost_IsoDataReadyISR() call?

Best answer by Robmar

You need to test it with an actual commerical USB microphone otherwise the tests aren’t

 going to be conclusive.

https://docs.espressif.com/projects/esp-usb/en/latest/esp32s2/usb_host/usb_host_notes_dwc_otg.html

UPDATE:  I have now solved the problem by rewritting the STM HOST USB handler and adding extensive driver code, including making it a fully composite CDC, Audio and HID driver.  I would recommend anyone trying to implement a host driver to refer to the above mentioned STM errata for the USB controller in their MCUs.
I have also rewritten the STM Device USB driver to support composite CDC, Audio and HID, with audio rates from 48 to 192 KHz.  If any one is interested in this code they should PM me.

33 replies

Robmar
RobmarAuthor
Senior II
July 16, 2026

The H7XX RM0433 manual doesn’t make it easy to understand the disable/enable process with this one large block of text below.  It would seem that when for example a BLERRR error is detected, the IRQ handler halts the channel and exits.  When the halt completes, another interrupt is generated for the USB_OTG_HCINT_CHH channel halted status, is that correct?
Then and only then can the channel FIFO’s be flushed and the channel restarted, with frame set to odd for starting.  As this is a DMA driven channel, the DMA address and size must be ready as they will start as soon as the channel is reactivated.
Did I miss anything?  Does the device needs no special consideration and should just send more packets?

RM4033 manual:  Halting a channel The application can disable any channel by programming the OTG_HCCHARx register with the CHDIS and CHENA bits set to 1. This enables the OTG_HS host to flush the posted requests (if any) and generates a channel halted interrupt. The application must wait for the CHH interrupt in OTG_HCINTx before reallocating the channel for other transactions. The OTG_HS host does not interrupt the transaction that has already been started on the USB. To disable a channel in DMA mode operation, the application does not need to check for space in the request queue. The OTG_HS host checks for space to write the disable request on the disabled channel’s turn during arbitration. Meanwhile, all posted requests are dropped from the request queue when the CHDIS bit in OTG_HCCHARx is set to 1. Before disabling a channel, the application must ensure that there is at least one free space available in the non-periodic request queue (when disabling a non-periodic channel) or the periodic request queue (when disabling a periodic channel). The application can simply flush the posted requests when the request queue is full (before disabling the channel), by programming the OTG_HCCHARx register with the CHDIS bit set to 1 which automatically clears the CHENA bit to 0. The application is expected to disable a channel on any of the following conditions: 2718/3353 RM0433 Rev 8 RM0433 USB on-the-go high-speed (OTG_HS) 1. 2. 3. 4. When an STALL, TXERR, BBERR or DTERR interrupt in OTG_HCINTx is received for an IN or OUT channel. The application must be able to receive other interrupts (DTERR, Nak, data, TXERR) for the same channel before receiving the halt. When an XFRC interrupt in OTG_HCINTx is received during a non periodic IN transfer or high-bandwidth interrupt IN transfer When a DISCINT (disconnect device) interrupt in OTG_GINTSTS is received. (The application is expected to disable all enabled channels). When the application aborts a transfer before normal completion.

Robmar
RobmarAuthor
Senior II
July 17, 2026

The Host USB IN driver is running the same without any BLERR or TXERR errors, and it still freezes after about 5 seconds.
Whether I set the USB host IN to use DMA or not, its still the same, works perfectly for 5 seconds, then the data repeats, only a replug of the cable can reset it.
Is this a bug that STM know about and explains the total lack of any USB Host audio IN examples?

Jgleckg
Visitor II
July 17, 2026

This looks like the USB host stream is starting correctly, but something is blocking or overflowing after the audio data begins. I would first check whether the freeze happens at the USB host layer, the audio class callback, or the buffer handling code.

A few things worth checking:

  • confirm the USB host task is still running after the freeze

  • check if the audio receive callback continues firing

  • make sure the audio buffer is not being overwritten or filled faster than it is processed

  • verify cache/DMA handling on the H743, especially if buffers are in cacheable memory

  • test with a larger circular buffer to see if the freeze is timing-related

  • add logs around the last successful packet/frame before it stops

On H7 devices, cache coherency and buffer placement can easily cause issues that look like the USB stream has frozen, even when the real issue is memory/cache handling.

Johny Gleck
Robmar
RobmarAuthor
Senior II
July 18, 2026

Hi thanks for your reply.  We did find that around when it froze a couple of times there was an BLERR or TXERR error detected in the STM driver that then called (void)USB_HC_Halt(hhcd->Instance, chnum);, but we just could NOT restart the channel using any known method apart from replugging the USB mic.
Later we found that the freeze occurs even when there are no errors or calls to (void)USB_HC_Halt(hhcd->Instance, chnum);,   and everything keeps workin, SOF and Notify calls, so its hard to know why this repeat of the last packet is occuring.
We disabed the .DMA on the channel, and the same freeze occurs under software transfer of frames.

What we do see on the oscilloscope which is monitoring a GPIO line toggled in AudioHost_IsoDataReadyISR() IRQ handler call, is a stable looking 1ms between calls, with a very slight occasional jitter.

The receiver buffer is just one buffer, it gets unloaded on the AudioHost_IsoDataReadyISR callback, so not sure how that could affect behaviour.

ST Technical Moderator
July 20, 2026

Hi ​@Robmar 

As I could not reproduce the issue on my side, we need to narrow it down methodically.

At this stage, the symptom could still be related to:

  • packet size / frame alignment
  • host service latency
  • state recovery in your custom audio receive path: AudioHost_IsoDataReadyISR()

Since you already observed a slight timing jitter before the freeze, that could be a useful clue.

  • If the issue appears reliably after a certain delay, the stream is likely service latency sensitive.
  • If it appears even with a completely idle CPU, the issue is less likely to be caused by scheduling load.

Try a different audio format, for example 32 kHz, to see whether the issue disappears or changes behavior.
That would point more toward a USB audio packet alignment / stream handling issue than a general device failure.

It would be helpful to provide a USB trace at least covering:

  • the moment before the freeze
  • the freeze itself
  • errors/debug log and halt
To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Robmar
RobmarAuthor
Senior II
July 20, 2026

That’s great news if you got host USB microphone streaming, can you send me a copy of the code to test on our board?

Adding the ISO IN streaming is so little code, I’m surprised it wasn’t included with STM’s HOST USB example which only handles a speaker output, with the mic side left missing just a dozen lines of code.

If you haven’t tested it at STM, I’m going to think there is a serious bug in the STM USB controller!

When the freeze in the audio IN stream data occurs there is no error at all, there were a couple of instances of BLERR and TXERR, but this freeze occurs 99% of the time with no error bits or interrupts at all.  The whole USB engine keeps working as if nothing is wrong, but the same frame is copied to the buffer each 1ms period, timing is perfect viewed on the scope, and with our without DMA enabled on the USB, it does the same.

Anyway, a little progress here, I have a reset routine that recover the mic without unplpugging it, but it takes 3 seconds to recover which is unuseable.
This code indicates that a channel gets blocked causing the audio IN stream to freeze:
 

void USBH_SoftReset(USBH_HandleTypeDef *phost)
{
HCD_HandleTypeDef *hhcd = phost->pData;
USB_OTG_GlobalTypeDef *USBx = ((HCD_HandleTypeDef *)phost->pData)->Instance;
__HAL_LOCK_NO_RET(hhcd);

HAL_StatusTypeDef ret = HAL_OK;
uint32_t USBx_BASE = (uint32_t)USBx;
__IO uint32_t count = 0U;
uint32_t value;
uint32_t i;

(void)USB_DisableGlobalInt(USBx);

/* Flush USB FIFO */
if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
{
ret = HAL_ERROR;
}

if (USB_FlushRxFifo(USBx) != HAL_OK)
{
ret = HAL_ERROR;
}

/* Flush out any leftover queued requests. */
for (i = 0U; i <= 15U; i++)
{
value = USBx_HC(i)->HCCHAR;
value |= USB_OTG_HCCHAR_CHDIS;
value &= ~USB_OTG_HCCHAR_CHENA;
value &= ~USB_OTG_HCCHAR_EPDIR;
USBx_HC(i)->HCCHAR = value;
}

/* BELOW CODE IS CRITICAL OR NO RESTART!! */
/* Halt all channels to put them in a known state */
for (i = 0U; i <= 15U; i++)
{
value = USBx_HC(i)->HCCHAR;
value |= USB_OTG_HCCHAR_CHDIS;
value |= USB_OTG_HCCHAR_CHENA;
value &= ~USB_OTG_HCCHAR_EPDIR;
USBx_HC(i)->HCCHAR = value;

do
{
count++;

if (count > 1000U)
{
break;
}
} while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
}

/* Clear any pending Host interrupts */
USBx_HOST->HAINT = CLEAR_INTERRUPT_MASK;
USBx->GINTSTS = CLEAR_INTERRUPT_MASK;

(void)USB_EnableGlobalInt(USBx);


__HAL_UNLOCK(hhcd);


__HAL_LOCK_NO_RET(hhcd);
__HAL_HCD_ENABLE(hhcd); // Re-enable global interrupt
__HAL_UNLOCK(hhcd);


// URGENT find a faster restart than going to BACK TO idle!

phost->gState = HOST_IDLE; // Restore audio IN but takes 3 secs!
phost->device.is_connected = 1;
phost->device.PortEnabled = 1;
phost->EnumState = ENUM_IDLE;

return;
}

 

Robmar
RobmarAuthor
Senior II
July 21, 2026

In the H743VIT6 revision V errata sheet, ES0392 - Rev 15, it lists a bug in the USB controller similar to what I am seeing:-
2.25.4 Isochronous IN EP disabled when packet fetch is in progress Description In Buffer DMA mode, when an isochronous IN endpoint is disabled and re-enabled, it is possible that the data transferred on the USB bus for the isochronous transfer is from the previous transfer on the same endpoint. This issue can occur if the DMA packet fetch from system memory is pending at the time of the disable operation. Workaround 1. Set the following bit in the DIEPCTLx register for the endpoint to be disabled: DIEPCTLx.EPDIS. 2. Wait for one packet fetch time on the AHB bus. By this time, if an ongoing DMA transfer for this endpoint is completed, new DMA transfers for this endpoint are no longer initiated. 3. The application must set the endpoint into NAK mode (DIEPCTLx.SNAK=1). See the section Setting IN endpoint NAK. 4. Wait for DIEPINTx.INEPNE (NAK effective interrupt). 5. Set the following bit in the DIEPCTLx register for the endpoint to be disabled: DIEPCTLx.EPDIS
In my case, this also seems to happen with the DMA disabled and software copy.  I am NOT using D-Cache.
These are the registers when the freeze occurs:
Audio pipe: pipe no. 2, epsize 96, phost->device.address = 1, Speed = 1, HCCHAR after openPipe 0x20548860.
HCCHAR=20500040 HC00 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=536870920 INT=0x00000020
HCCHAR=00508040 HC01 CHENA=0 CHDIS=0 DIR=IN EP=0 TSIZ=2147483712 INT=0x00000000
HCCHAR=E0548860 HC02 CHENA=1 CHDIS=1 DIR=IN EP=1 TSIZ=524384 INT=0x00000000
HCCHAR=00000000 HC03 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC04 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC05 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC06 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC07 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC08 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC09 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC10 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC11 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC12 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC13 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC14 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000
HCCHAR=00000000 HC15 CHENA=0 CHDIS=0 DIR=OUT EP=0 TSIZ=0 INT=0x00000000

Robmar
RobmarAuthor
Senior II
July 21, 2026

The STM USB controller is from Synopsis and used by other manufacturers, such as E S P ---3 2, and the error is listed but not limited to DMA mode:

Supplemental Notes

Some of the DWC_OTG’s behaviors are not mentioned in the Databook or Programming Guide. This section describes some of those behaviors that are relevant to the Host Stack’s implementation.

Port Errors Do Not Trigger a Channel Interrupt

If a port error occurs (such as a sudden disconnection or port over-current) while there are one or more active channels,

  • the active channels remains active (i.e., HCCHAR.ChEna remains set) and no channel interrupts are generated.

  • channels could in theory be disabled by setting HCCHAR.ChDis, but this does not work for Isochronous channels as the channel disabled interrupt is never generated.

Therefore, on port errors, a controller soft reset should be used to ensure all channels are disabled.

ST Technical Moderator
July 24, 2026

Hi ​@Robmar 

This USBX host audio example uses speaker device. You can refer to this project to create record thread similar to playback and reproduce the issue so we can help you. 

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Robmar
RobmarAuthor
Senior II
July 24, 2026

Come on be serious, this is a microphone issue, and USBX requires AzzureRTOS, which requires large memory that most applications can’t spare, its a bit like walking into a shop asking for an FM radio, and being told “No problems sir, we have and excellent FM radio available as part of a this lovelly car!”

I don’t need the car, just the radio. :/

In addition USBX is totally different coding, so you know well that to use this, we’d need to rebuild our entire large application, it would take us months!

ST Technical Moderator
July 27, 2026

 ​@Robmar 

Could you share the ESP32 errata reference you mentioned, so I can compare it with the STM32H7 behavior?

On my side, I tested USB Host Audio streaming using two STM32H7 boards:

  • one STM32H7 acting as the USB microphone device, sending a known incrementing pattern
  • the other STM32H7 acting as the USB host

The host receives the pattern correctly, which lets me verify both data continuity and payload integrity.

  

 

 

I can share the test case with you in a private message, or you may send me your GitHub ID so I can share it with you there. To help narrow this down further, you may also try it on your hardware setup and let me know whether you can reproduce the issue.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Robmar
RobmarAuthorBest answer
Senior II
July 28, 2026

You need to test it with an actual commerical USB microphone otherwise the tests aren’t

 going to be conclusive.

https://docs.espressif.com/projects/esp-usb/en/latest/esp32s2/usb_host/usb_host_notes_dwc_otg.html

UPDATE:  I have now solved the problem by rewritting the STM HOST USB handler and adding extensive driver code, including making it a fully composite CDC, Audio and HID driver.  I would recommend anyone trying to implement a host driver to refer to the above mentioned STM errata for the USB controller in their MCUs.
I have also rewritten the STM Device USB driver to support composite CDC, Audio and HID, with audio rates from 48 to 192 KHz.  If any one is interested in this code they should PM me.