2020-01-07 07:10 PM
Dear STM Team,
dear STM Community,
please, who can help for intended project: "USB MIC Device on STM Board as USB Host Audio with Input Steaming"?
The code, provided in CubeHAL (drivers, STM USB Middleware) as well as the generated code by CubeMX tool seems to be incomplete:
How to extend the USBH (host) Audio Class for 'microphone' input streaming?
Which code where to add?
Issues:
What is missing?
If I see the code, the audio data from MIC (every 1 ms an USB packet, via Endpoint 0x81) is not coming (no interrupts anymore, nothing stored in memory)
It cannot, because the code is missing!
The function 'USBH_AUDIO_InputSteam()' is empty (and optimized to do nothing, no code at all at the end).
So, I think, I had to add code to get IN, Input, EP 0x81 input data. If a Pipe for it is already configured (just not triggered) - I cannot say right now (but the EP 0x81 seems to be known by the driver).
Even, I do not know (sorry):
I think, this STM USB Host Audio Class for a MIC Input was never implemented (never tested and never used- sorry). It should be missing on all STM boards and projects (USB Middleware). The counterpart, the 'headphone' Host Audio Class, seems to be complete, just the opposite direction looks like never used and never implemented (sorry).
Please, how to extend the code to bring-up an USB MIC Device on an STM board with STM USB Middleware as USB Host Audio Class Input device?
Thank you.
Best regards
Torsten
2020-01-07 07:45 PM
As I see right now in some manuals - the Host Audio (MIC) Input is not officially supported (just Host Audio Output to a speaker).
how to add/extend for Audio Microphone?
2020-01-08 07:00 PM
OK, just a need to add a call of USBH_IsocReceiveData() function with pipe as AUDIO_Handle->microphone.pipe. This can be done synchronized with the SOF process (in SOF handler or using helper flags to sync with code in the USBH_Process() and its sub-functions called).
But new issue!
It works for few seconds, in a random way how long it will be working. After a short while (0.5 up to few seconds), the 'idle' code, the code in main() with the function USBH_Process() is never called again. Instead, the code runs only and all the time in the USB Interrupt handler. It means: there seems to be a pending, still active USB interrupt (not cleared) so that the USB INT handler is entered immediately again.
Potentially, there is an INT condition which is not cleared and it triggers again immediately an interrupt. No chance for the main() 'thread' to run.
No idea yet where the problem is. But it is related to calling the USBH_IsocReceiveData() function. If I do not do this call, this condition does not happen. If I do the call, after a short period of time the entire code keeps running only in the interrupt handler code, never back to main().
Or: maybe one IN data reception is missing, after sending the URB request nothing is sent from the external USB MIC device. Maybe this Even/Odd frame indication gets out of sync. Or the clock drift is an issue (MIC internal clock is asynchronous to the host clock, but actually the SOF should be there to cope with).
If I call this USBH_IsocReceiveData() function inside the SOF handler (which is part of the INT handler) - it works to update my memory/buffer with the MIC USB PCM packets. But the same issue: endlessly running in the INT handlers, even this USBH_IsocReceiveData() fetches still new IN data from MIC. The main() 'thread' is 'dead'.
2020-01-09 03:16 PM
YES! I can confirm:
Details:
Debugging the USB stack (host, ISO IN streaming) I found that HCINT flag in GINTSTS is always set (remains set), never cleared. The reason is that one channel (channel 2 for my ISO IN), has seen a BBERR. This error condition is set in register OTG_HCINT(2) but never checked and never cleared.
(BTW: this BBERR interrupt flag is enabled in file stm32h7xx_ll_usb.c and therefore it 'must' be handled as well somewhere else - 'forgotten to implement consistent code?')
Adding code in file stm32h7xx_hal_hcd.c, in function HCD_HC_IN_IRQHandler() as:
/**
* ATT: add handling of BBERR !!
*/
if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR)
{
__HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
}
solves the problem.
Now, my Audio ISO IN from USB microphone works w/o issues. The main() thread, in function USBH_AUDIO_InputStream(), called from USBH_AUDIO_Process() in file usbh_audio.c, does the USBH_IsocReceiveData() function call to get my audio with PCM words from the USB mic. COOL!
Here the function to get the USB IN audio: the flag is used in combination with the function USBH_AUDIO_SOFProcess() in order to synchronize with the SOF interrupt (and signal).
static USBH_StatusTypeDef USBH_AUDIO_InputStream(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status = USBH_OK;
AUDIO_HandleTypeDef *AUDIO_Handle;
if (flag == 0)
flag = 1;
if (flag == 2)
{
flag = 1;
/* actually, size is AUDIO_Handle->microphone.EpSize */
AUDIO_Handle = (AUDIO_HandleTypeDef *) phost->pActiveClass->pData;
/**
* this function should return if the in data was received
*/
status = USBH_IsocReceiveData(phost, audioInBuffer, sizeof(audioInBuffer), AUDIO_Handle->microphone.Pipe);
cnt++;
if ((cnt % 500) == 0)
BSP_LED_Toggle(LED1);
}
else
status = USBH_BUSY;
return status;
}