LINUX.ORG.RU

STM32 - определить отключение USB

 , , , ,


0

1

Дано: микроконтроллер STM32F407, при программировании используется библиотека libopencm3, реализован USB CDC ACM Device. Плата питается НЕ от USB.

Надо: определить, собственно, пропадание USB подключения. Момент его появления определить легко - вызывается callback выбора активной конфигурации.

★★★★★

О, сам как раз этой библиотечкой пользуюсь. Можно просто питание мониторить, а можно как я на 103-м сделал:

static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
        uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{
    (void)complete;
    (void)buf;
    (void)usbd_dev;
    char local_buf[10];
    struct usb_cdc_line_coding  lc;

    switch (req->bRequest) {
    case SET_CONTROL_LINE_STATE:{
        if(req->wValue){ // terminal is opened
            USB_connected = 1;
            //P("\n\tUSB connected!\n", uart1_send);
        }else{ // terminal is closed
            USB_connected = 0;
            //P("\n\tUSB disconnected!\n", uart1_send);
        }

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от KivApple

Некоторое время назад подключал USB на discovery. Цель был интерфейс для libusb. А то у них там есть почти всё (виртуальный ком-порт, hid,..), но нет raw примера. Пришлось сделать «custom» самому из cdc.

Сейчас глянул, как там этот disconnect реализован. Вот вся цепочка от объявления прерывания до printf():

startup_stm32f407xx.s

g_pfnVectors:

/* ...cut... */

  .word     OTG_FS_IRQHandler                 /* USB OTG FS                   */

===============================================================================

stm32f4xx_it.c

/**
  * @brief  This function handles USB-On-The-Go FS global interrupt request.
  * @param  None
  * @retval None
  */
#ifdef USE_USB_FS
void OTG_FS_IRQHandler(void)
#else
void OTG_HS_IRQHandler(void)
#endif
{
  HAL_PCD_IRQHandler(&hpcd);
}

===============================================================================

stm32f4xx_hal_pcd.c

/**
  * @brief  Handles PCD interrupt request.
  * @param  hpcd: PCD handle
  * @retval HAL status
  */
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
{
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  uint32_t i = 0, ep_intr = 0, epint = 0, epnum = 0;
  uint32_t fifoemptymsk = 0, temp = 0;
  USB_OTG_EPTypeDef *ep;
    
  /* ensure that we are in device mode */
  if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
  {

/* ... cut ... */

    /* Handle Disconnection event Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
    {
      temp = hpcd->Instance->GOTGINT;
      
      if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
      {
        HAL_PCD_DisconnectCallback(hpcd);             /* <==================================== */
      }
      hpcd->Instance->GOTGINT |= temp;
    }
  }
}

===============================================================================

usbd_conf.c

/**
  * @brief  Disconnect callback.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
{
  USBD_LL_DevDisconnected(hpcd->pData);
}

===============================================================================

usbd_core.c

/**
* @brief  USBD_DevDisconnected 
*         Handle device disconnection event
* @param  pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef  *pdev)
{
  /* Free Class Resources */
  pdev->dev_state = USBD_STATE_DEFAULT;
  pdev->pClass->DeInit(pdev, pdev->dev_config);  
   
  return USBD_OK;
}

===============================================================================

usbd_custom.c

/**
  * @brief  USBD_CUSTOM_DeInit
  *         DeInitialize the CUSTOM layer
  * @param  pdev: device instance
  * @param  cfgidx: Configuration index
  * @retval status
  */
static uint8_t  USBD_CUSTOM_DeInit (USBD_HandleTypeDef *pdev, 
                                 uint8_t cfgidx)
{
  /* Close EP IN */
  USBD_LL_CloseEP(pdev, CUSTOM_IN_EP);
  
  /* Close EP OUT */
  USBD_LL_CloseEP(pdev, CUSTOM_OUT_EP);
 
  /* DeInit  physical Interface components */
  if(pdev->pClassData != NULL)
  {
    ((USBD_CUSTOM_ItfTypeDef *)pdev->pUserData)->DeInit();
    USBD_free(pdev->pClassData);
    pdev->pClassData = NULL;
  }

  return USBD_OK;
}

===============================================================================

usbd_custom_interface.c

/**
  * @brief  CDC_Itf_DeInit
  *         DeInitializes the CDC media low layer
  * @param  None
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
static int8_t CUSTOM_Itf_DeInit(void)
{
  usb_connected = 0;

  printf("USB disconnected\n");

  return (USBD_OK);
}

gag ★★★★★ ()
Ответ на: комментарий от gag

У USB OTG всё вообще по-другому. Там резисторы подтяжки, например, все внутри кристалла. Соответственно, есть битики в регистрах для программного отключения/подключения. И вообще много всяких вкусностей - хост-режим, аппаратный FIFO и т. д.

А на STM32F103 всё куда примитивнее.

KivApple ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.