2
votes

I have generated a project for USB CDC VCP using CubeMX and HAL and now I am trying to figure out how I can implement these two weak functions:

void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)

These fuctions will be called inside HAL_PCD_IRQHandler. What I want to do is place some code inside them so I can retrive received data from host and also find out about end of transaction.

I have seen that CubeMX has reimplemented these weak functions inside usbd_conf.c like this:

    /**
  * @brief  Data Out stage callback.
  * @param  hpcd: PCD handle
  * @param  epnum: Endpoint Number
  * @retval None
  */
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
  USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}

/**
  * @brief  Data In stage callback..
  * @param  hpcd: PCD handle
  * @param  epnum: Endpoint Number
  * @retval None
  */
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
  USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}

I am wondered to know what do these two functions (USBD_LL_DataOutStage and USBD_LL_DataInStage) do? And how I can edit them to achieve my goal.

1
I'm no STM32 expert but from my experience, I believe the functions you should be working with are located in usbd_cdc_if.c. In that file, you'll find the functions CDC_Receive_FS and CDC_Transmit_FS. I believe those are meant to be the points to add your custom code on top of the USB stack for most situations. Do you see those functions?user2027202827
@user2027202827: those two functions you mentioned are examples to show you how you can implement them. and they are usable to pull and send data. The fuctions I have mentioned are used for callbacks in interrupt when operation is done.Nixmd
Do you mind if I ask what the motivation is for using those particular functions rather than the interface CubeMX generates for you?user2027202827
@user2027202827, CubeMX only generates initializations. Those functions you can find in usbd_cdc_if are just some examples which you may use them, but you are advised to improve them. And also my application is time critical, thus I should use interrupts instead of pulling registers or variables to find out end of operations.Nixmd
Well thanks for answering my question :) sorry I'm not much help with yours. I assume you've read the device library manual for the USB stack?user2027202827

1 Answers

0
votes

I encountered this same issue in STM32Cube_FW_L4_V1.10.0 and after looking at this and some other discussions decided to work around it by replacing the CDC DataIn handler with an alternate implementation that adds a call to CDC_TransmitReady_CB() to wake the transmit task:

// Modified CDC DataIn handler to invoke a callback (CDC_TransmitReady_CB) on TX ready
uint8_t altDataInHandler(USBD_HandleTypeDef *pdev, uint8_t epnum) {
  USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
  if (hcdc == NULL) return USBD_FAIL;
  hcdc->TxState = 0;
  CDC_TransmitReady_CB();
  return USBD_OK;
}

void hackCdcClass() {
  USBD_CDC.DataIn = altDataInHandler;
} 

Ugly, but it works like a charm.