cancel
Showing results for 
Search instead for 
Did you mean: 

USB Audio Class losing 50% of my data

Matt Hollands
Associate II

0693W000001sASMQA2.pngHi, I am trying to get a robust isochronous transfer of audio from my STM32F072CB using the audio device class. My code is based on the code generated by STM32CubeMX for a speaker but I have changed the descriptor in order to make it an audio input. Basically all I have changed is usbd_audio.c and usbd_audio.h. I am sending 120 bytes on each DataIn interrupt (which I have confirmed occurs every millisecond) but when I record from this source, I only get 50% of the data and if I look at the USB trace using WireShark I can see that all my packets have errors and every second packet has no data! I have managed to find a few examples such as the X-CUBE-MEMSMIC1 example and as far as I can tell I am doing the same thing they are. Any help to get a reliable audio data transfer much appreciated!

static uint8_t  USBD_AUDIO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
	HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
	//TODO: Check alternate setting
	USBD_LL_Transmit(pdev, AUDIO_IN_EP, FAKEDATA, AUDIO_IN_PACKET);
  return USBD_OK;
}
static uint8_t  USBD_AUDIO_SOF(USBD_HandleTypeDef *pdev)
{
	HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
  return USBD_OK;
}
static uint8_t  USBD_AUDIO_Setup(USBD_HandleTypeDef *pdev,
                                 USBD_SetupReqTypedef *req)
{
  USBD_AUDIO_HandleTypeDef *haudio;
  uint16_t len;
  uint8_t *pbuf;
  uint16_t status_info = 0U;
  uint8_t ret = USBD_OK;
 
  haudio = (USBD_AUDIO_HandleTypeDef *)pdev->pClassData;
 
  switch (req->bmRequest & USB_REQ_TYPE_MASK)
  {
    case USB_REQ_TYPE_CLASS :
      switch (req->bRequest)
      {
        case AUDIO_REQ_GET_CUR:
          AUDIO_REQ_GetCurrent(pdev, req);
          break;
 
        case AUDIO_REQ_SET_CUR:
          AUDIO_REQ_SetCurrent(pdev, req);
          break;
 
        default:
          USBD_CtlError(pdev, req);
          ret = USBD_FAIL;
          break;
      }
      break;
 
    case USB_REQ_TYPE_STANDARD:
      switch (req->bRequest)
      {
        case USB_REQ_GET_STATUS:
          if (pdev->dev_state == USBD_STATE_CONFIGURED)
          {
            USBD_CtlSendData(pdev, (uint8_t *)(void *)&status_info, 2U);
          }
          else
          {
            USBD_CtlError(pdev, req);
            ret = USBD_FAIL;
          }
          break;
 
        case USB_REQ_GET_DESCRIPTOR:
          if ((req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE)
          {
            pbuf = USBD_AUDIO_CfgDesc + 18;
            len = MIN(USB_AUDIO_DESC_SIZ, req->wLength);
 
            USBD_CtlSendData(pdev, pbuf, len);
          }
          break;
 
        case USB_REQ_GET_INTERFACE :
          if (pdev->dev_state == USBD_STATE_CONFIGURED)
          {
            USBD_CtlSendData(pdev, (uint8_t *)(void *)&haudio->alt_setting, 1U);
          }
          else
          {
            USBD_CtlError(pdev, req);
            ret = USBD_FAIL;
          }
          break;
 
        case USB_REQ_SET_INTERFACE :
          if (pdev->dev_state == USBD_STATE_CONFIGURED)
          {
            if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES)
            {
              haudio->alt_setting = (uint8_t)(req->wValue);
              if ((uint8_t)(req->wValue) == 1)
              {
            	  // Must send dummy packet to begin data in packets (not sure why?)
            	  USBD_LL_Transmit(pdev, AUDIO_IN_EP, FAKEDATA, 0);
              }
            }
            else
            {
              /* Call the error management function (command will be nacked */
              USBD_CtlError(pdev, req);
              ret = USBD_FAIL;
            }
          }
          else
          {
            USBD_CtlError(pdev, req);
            ret = USBD_FAIL;
          }
          break;
 
        default:
          USBD_CtlError(pdev, req);
          ret = USBD_FAIL;
          break;
      }
      break;
    default:
      USBD_CtlError(pdev, req);
      ret = USBD_FAIL;
      break;
  }
 
  return ret;
}
static uint8_t  USBD_AUDIO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
 
	for(uint8_t i = 0; i < AUDIO_IN_PACKET; i+=2)
	{
		FAKEDATA[i+1] = i;
		FAKEDATA[i] = 0;
	}
 
  USBD_AUDIO_HandleTypeDef   *haudio;
 
  /* Open EP OUT */
  USBD_LL_OpenEP(pdev, AUDIO_IN_EP, USBD_EP_TYPE_ISOC, AUDIO_IN_PACKET);
  pdev->ep_in[AUDIO_IN_EP & 0xFU].is_used = 1U;
 
  /* Allocate Audio structure */
  pdev->pClassData = USBD_malloc(sizeof(USBD_AUDIO_HandleTypeDef));
 
  if (pdev->pClassData == NULL)
  {
    return USBD_FAIL;
  }
  else
  {
    haudio = (USBD_AUDIO_HandleTypeDef *) pdev->pClassData;
    haudio->alt_setting = 0U;
    haudio->offset = AUDIO_OFFSET_UNKNOWN;
    haudio->wr_ptr = 0U;
    haudio->rd_ptr = 0U;
    haudio->rd_enable = 0U;
 
    /* Initialize the Audio output Hardware layer */
    if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->Init(USBD_AUDIO_FREQ,
                                                         AUDIO_DEFAULT_VOLUME,
                                                         0U) != 0)
    {
      return USBD_FAIL;
    }
  }
 
  return USBD_OK;
}

0 REPLIES 0